Навигация по курсу
На телефоне широкие таблицы и схемы прокручивайте влево и вправо.
| Дата | День | Время | Тип | Тема | Открыть |
|---|---|---|---|---|---|
| 08.09 | Вт | 16:00–17:35 | Лекция | Л.1. Основные понятия баз данных и СУБД |
| Дата | День | Время | Тип | Тема | Открыть |
|---|---|---|---|---|---|
| 15.09 | Вт | 12:30–14:05 | Лаб. | ЛР №1. SSMS: системные и учебные БД | |
| 16.09 | Ср | 14:15–15:50 | Лекция | Л.2. Реляционная модель. Функциональные зависимости | |
| 16.09 | Ср | 16:00–17:35 | Лаб. | ЛР №2. Таблицы и первый SELECT |
| Дата | День | Время | Тип | Тема | Открыть |
|---|---|---|---|---|---|
| 22.09 | Вт | 14:15–15:50 | Лекция | Л.3. Нормализация. Аномалии обновления | |
| 22.09 | Вт | 16:00–17:35 | Лаб. | ЛР №3. Новые таблицы, ключи и ограничения | |
| 23.09 | Ср | 12:30–14:05 | Лаб. | ЛР №4. FK, ALTER TABLE, GO |
| Дата | День | Время | Тип | Тема | Открыть |
|---|---|---|---|---|---|
| 29.09 | Вт | 12:30–14:05 | Лекция | Л.4. Многопользовательские и распределённые БД | |
| 29.09 | Вт | 14:15–15:50 | Лаб. | ЛР №5. INSERT, SELECT, WHERE | |
| 30.09 | Ср | 12:30–14:05 | Лаб. | ЛР №6. UPDATE, DELETE, ORDER BY |
| Дата | День | Время | Тип | Тема | Открыть |
|---|---|---|---|---|---|
| 06.10 | Вт | 12:30–14:05 | Лекция | Л.5. Транзакции. Свойства ACID | |
| 06.10 | Вт | 14:15–15:50 | Лаб. | ЛР №7. Агрегатные функции | |
| 06.10 | Вт | 16:00–17:35 | Лаб. | ЛР №8. GROUP BY, HAVING, ROLLUP |
| Дата | День | Время | Тип | Тема | Открыть |
|---|---|---|---|---|---|
| 13.10 | Вт | 12:30–14:05 | Лекция | Л.6. Аномалии параллельного доступа | |
| 13.10 | Вт | 14:15–15:50 | Лаб. | ЛР №9. Вложенные подзапросы | |
| 14.10 | Ср | 12:30–14:05 | Лаб. | ЛР №10. Коррелированные подзапросы и EXISTS |
| Дата | День | Время | Тип | Тема | Открыть |
|---|---|---|---|---|---|
| 20.10 | Вт | 12:30–14:05 | Лекция | Л.7. Уровни изоляции транзакций | |
| 20.10 | Вт | 14:15–15:50 | Лаб. | ЛР №11. INNER и OUTER JOIN | |
| 21.10 | Ср | 12:30–14:05 | Лаб. | ЛР №12. UNION, EXCEPT, INTERSECT |
| Дата | День | Время | Тип | Тема | Открыть |
|---|---|---|---|---|---|
| 27.10 | Вт | 12:30–14:05 | Лекция | Л.8. Блокировки, тупики, репликация | |
| 27.10 | Вт | 14:15–15:50 | Лаб. | ЛР №13. Функции строк, чисел, дат | |
| 28.10 | Ср | 12:30–14:05 | Лаб. | ЛР №14. CASE, ISNULL, COALESCE |
| Дата | День | Время | Тип | Тема | Открыть |
|---|---|---|---|---|---|
| 03.11 | Вт | 12:30–14:05 | Лекция | Л.9. Структурированные и неструктурированные данные | |
| 03.11 | Вт | 14:15–15:50 | Лаб. | ЛР №15. Переменные и IF | |
| 04.11 | Ср | 12:30–14:05 | Лаб. | ЛР №16. Циклы WHILE и TRY/CATCH |
| Дата | День | Время | Тип | Тема | Открыть |
|---|---|---|---|---|---|
| 10.11 | Вт | 12:30–14:05 | Лекция | Л.10. Язык XML | |
| 10.11 | Вт | 14:15–15:50 | Лаб. | ЛР №17. XML в SQL Server | |
| 11.11 | Ср | 12:30–14:05 | Лаб. | ЛР №18. Иерархические данные |
| Дата | День | Время | Тип | Тема | Открыть |
|---|---|---|---|---|---|
| 17.11 | Вт | 12:30–14:05 | Лекция | Л.11. Администрирование и мониторинг СУБД | |
| 17.11 | Вт | 14:15–15:50 | Лаб. | ЛР №19. MongoDB — документная БД | |
| 18.11 | Ср | 12:30–14:05 | Лаб. | ЛР №20. Представления VIEW |
| Дата | День | Время | Тип | Тема | Открыть |
|---|---|---|---|---|---|
| 24.11 | Вт | 12:30–14:05 | Лекция | Л.12. Программирование в БД: процедуры, триггеры | |
| 24.11 | Вт | 14:15–15:50 | Лаб. | ЛР №21. Хранимые процедуры | |
| 01.12 | Вт | 12:30–14:05 | Лаб. | ЛР №22. Триггеры DML и INSTEAD OF |
| Дата | День | Время | Тип | Тема | Открыть |
|---|---|---|---|---|---|
| 01.12 | Вт | 14:15–15:50 | Лекция | Л.13. Резервное копирование | |
| 02.12 | Ср | 12:30–14:05 | Лаб. | ЛР №23. GRANT, REVOKE, роли |
| Дата | День | Время | Тип | Тема | Открыть |
|---|---|---|---|---|---|
| 08.12 | Вт | 12:30–14:05 | Лекция | Л.14. Восстановление данных и защита | |
| 08.12 | Вт | 14:15–15:50 | Лаб. | ЛР №24. Восстановление данных и итоговый практикум |
| Дата | День | Время | Тип | Тема | Открыть |
|---|---|---|---|---|---|
| 15.12 | Вт | 12:30–14:05 | Лекция | Л.15. Распределённые БД и двухфазная фиксация |
| Дата | День | Время | Тип | Тема | Открыть |
|---|---|---|---|---|---|
| 15.12 | Вт | 14:15–15:50 | Лекция | Л.16. Хранилища данных и подготовка к экзамену |
О чём эта лекция. Перед SQL и таблицами — базовые слова: данные, база данных, СУБД, клиент. Без этого на лабораторных легко превратиться в «копировальщика кода».
Главная мысль одной фразой: база — это упорядоченные связанные данные; СУБД — программа, которая ими управляет; SSMS — окно, через которое вы отправляете запросы на сервер.
После прочтения вы сможете:
UniversityDB.| Тема |
|---|
| Организация курса |
| Данные, база данных, СУБД — на примерах |
| От данных к информации (пирамида DIKW) |
| Почему не хватает Excel и Word |
| Три «этажа» одной базы (ANSI/SPARC) — коротко |
| Демо SQL Server Management Studio (SSMS) и подготовка к ЛР №1 |
Данные — это то, что уже записано: число, слово, дата. Сами по себе они часто мало о чём говорят.
| Ситуация | Что видим | Это данные? |
|---|---|---|
| На термометре | 38.5 | Да — просто число |
| В списке группы | Иванов | Да — просто фамилия |
| В календаре | 08.09.2026 | Да — просто дата |
| В SMS банка | -500 | Да — пока неясно, списание это или пополнение |
Чтобы число стало понятным, нужен контекст: кто, что, когда, в каких единицах. Об этом — в разделе про пирамиду.
База данных (БД) — это большой упорядоченный набор связанных данных по одной теме. Не одна таблица на листочке, а система хранения.
Пример из вуза: в одной базе UniversityDB лежат студенты, вузы, предметы, оценки — и они связаны: у каждого студента есть вуз, у каждой оценки — студент и предмет.
Пример из жизни: каталог интернет-магазина — товары, цены, заказы, покупатели. Это тоже база, только тема другая.
Аналогия: база данных — как картотека в библиотеке: не одна книга, а весь фонд с правилами, где что лежит.
СУБД — программа, которая хранит базу, принимает запросы, следит, чтобы данные не потерялись и не испортились.
Примеры СУБД в курсе:
.db.Аналогия: если база — картотека, то СУБД — библиотекарь и правила работы с картотекой: выдаёт книги, не даёт двум людям одновременно испортить одну карточку, следит за порядком.
| Название | Что это на самом деле | Пример |
|---|---|---|
| База данных | Данные + структура (таблицы, связи) | UniversityDB |
| СУБД | Программа, которая базой управляет | SQL Server, SQLite |
| Клиент | Окно, через которое мы пишем SQL | SQL Server Management Studio (SSMS), DB Browser for SQLite |
| Файл Excel | Файл с таблицей, но это не полноценная СУБД | группа31.xlsx |
Рисунок 1. Вы работаете в клиенте. Клиент обращается к СУБД. СУБД хранит базу.
Спросите группу:
Мы уже выучили три слова: данные, база, СУБД. Теперь логичный вопрос: зачем всё это нужно, если можно записать оценки в тетрадь? Организации хотят не просто цифры, а понимание и решения — для этого данные проходят несколько шагов. Их часто рисуют пирамидой DIKW.
Рисунок 2. Снизу вверх: от «голых» цифр к решению. СУБД помогает на нижних двух уровнях.
Разберём три разные ситуации — так проще запомнить, чем одной длинной таблицей.
| Пример | Уровень | Как это звучит |
|---|---|---|
| 1. Оценка в вузе | Данные | 5 |
| Информация | Иванов получил 5 по информатике 15.01.2026 | |
| Знания | Средний балл Иванова 4.5 — стипендию, скорее всего, сохранит | |
| Мудрость | Деканат решает: предложить пересдачу или оставить как есть | |
| 2. Погода | Данные | −5 |
| Информация | Сегодня в Воронеже −5 °C | |
| Знания | Такая температура опасна для длительной прогулки без перчаток | |
| Мудрость | Лучше перенести outdoor-мероприятие в помещение | |
| 3. Банк | Данные | 1500 |
| Информация | На счёте осталось 1500 ₽ после оплаты общежития | |
| Знания | До зарплаты 10 дней — денег может не хватить | |
| Мудрость | Отложить крупную покупку или взять часть из резерва |
Где здесь СУБД?
Если данные — это фундамент, то Excel часто даёт «кривой фундамент»: удобно на первый день, больно через месяц. Представьте: староста ведёт список группы, кафедра — оценки, методист — нагрузку. В каждом файле есть Иванов и телефон деканата.
База данных решает это так:
Рисунок 3. Вместо разрозненных файлов — одна база с правилами.
Это не пирамида DIKW из раздела 3. Здесь другая мысль: одни и те же данные в СУБД можно описать на трёх этажах — от «что видит человек» до «как всё записано на диске». Это трёхуровневая архитектура ANSI/SPARC — три взгляда на одну базу.
Рисунок 4. Один запрос студента «проходит» через схему таблиц; СУБД сама обращается к файлам на диске.
| Этаж | Что это | Пример |
|---|---|---|
| 1. Внешний | Каждому пользователю показывают свою часть данных | Студент видит только свои оценки; деканат — всю группу |
| 2. Концептуальный | Общая схема базы: таблицы, столбцы, связи — здесь пишете SQL | STUDENT, UNIVERSITY, EXAM_MARKS |
| 3. Внутренний | Физическое хранение на диске сервера — настраивает администратор | Файлы базы, индексы, журнал транзакций |
VIEW и права GRANT на ЛР №17 и №23).Зачем это знать? Чтобы не путать «таблицу в Object Explorer» и «файл на диске». Таблица STUDENT для вас — логическая. Если администратор добавит индекс для ускорения, столбцы таблицы не меняются — меняется только устройство на 3-м этаже.
Кратко — «карта» на весь семестр, без деталей.
Кто работает с базой:
(local), .\SQLEXPRESS или имя учебного сервера).master, model, msdb, tempdb — их не трогаем, только смотрим.UniversityDB, OK.CREATE DATABASE UniversityDB;UniversityDB, выполнить:Проверьте для себя: вы в клиенте SSMS; запрос выполняется на сервере SQL Server; база UniversityDB создана или открыта для работы.

Шаг 1. Подключение: Connect to Server, тип Database Engine.

Шаг 2. После подключения — Object Explorer с базами сервера.

Шаг 3. Узел System Databases (master, model, msdb, tempdb).

Шаг 4. Создание UniversityDB (или команда CREATE DATABASE).

Рисунок 5. Основные окна SSMS на ЛР №1.
STUDENT_ID.UNIVERSITY_ID у студента.Итог. Вы различаете данные, БД, СУБД и клиент; понимаете три уровня ANSI/SPARC; готовы к ЛР №1.
О чём эта лекция. На ЛР №1 вы создали базу UniversityDB. Сейчас важно понять не «как нажать кнопки в SSMS», а почему данные хранят в нескольких таблицах и откуда берутся столбцы STUDENT_ID, UNIVERSITY_ID, ограничения PRIMARY KEY и FOREIGN KEY.
Главная мысль одной фразой: в реляционной модели мы формулируем правила между столбцами: «зная значение одного столбца (или пары столбцов), однозначно определяется значение другого». Пример: по STUDENT_ID однозначно известна SURNAME — по номеру студента всегда одна и та же фамилия. Такое правило называется функциональной зависимостью. Из неё следуют ключи и нормализация.
После прочтения вы сможете:
STUDENT и UNIVERSITY;STUDENT_ID определяет SURNAME» и привести свой пример;| Тема |
|---|
| Зачем не одна большая таблица |
| Таблица = отношение: строка, столбец, правила |
| Первичный и внешний ключ |
| Функциональная зависимость |
| Замыкание X⁺ — проверка ключа |
| Связь с ЛР №2 и темой нормализации |
Успеваемость группы часто ведут в Excel: файл Университет.xlsx, лист Группа. В столбце A — фамилии (со 2-й строки), в первой строке начиная с B — названия предметов, в ячейках — оценки. У каждого студента одна строка, фамилия не повторяется — для журнала это удобно и логично.
База данных решает другие задачи: связать студентов с вузами, преподавателями, множеством предметов и оценок; отвечать на запросы без переделки листа; не дублировать справочную информацию. Поэтому сравнение «Excel vs SQL» — не «фамилия три раза на листе», а ограничения такой схемы при росте данных.
| Ситуация | Что не так (или чем неудобно) |
|---|---|
| Новый предмет в семестре | Нужен новый столбец; меняются формулы, сводные таблицы, шаблон отчёта |
| К журналу добавили «Название вуза» и «Город вуза» | Оба поля копируются в каждой строке студента — переименовали вуз, правите весь лист |
| Другой формат: каждая оценка — отдельная строка (студент + предмет + балл) | Фамилия и курс повторяются в каждой строке с оценкой |
| Несколько групп, курсов, преподавателей | Много листов или файлов; сводный отчёт по кафедре собирается вручную |
| Запрос «все пятёрки по «Базам данных» по всем группам» | Поиск по разным столбцам и листам; в SQL — один SELECT по таблице оценок |
Решение в UniversityDB: разделить данные по смыслу и связать таблицы числовыми ключами:
UNIVERSITY — справочник вузов (название и город хранятся один раз);STUDENT — кто учится (ссылка UNIVERSITY_ID на вуз, без повторения названия);EXAM_MARKS — оценки (отдельная строка на каждую пару «студент + предмет»).Рисунок 1. Слева — привычный журнал (фамилия в строке, предметы в столбцах). Справа — как те же смыслы разложены в UniversityDB.
В учебниках таблицу называют отношением, строку — кортежем, столбец — атрибутом. В SSMS вы по-прежнему видите обычную таблицу — термины нужны для экзамена и курсовой, когда описываете модель.
ORDER BY — отдельная команда). Столбцы тоже можно переставить в SELECT, смысл данных не меняется.| STUDENT_ID | SURNAME | KURS | UNIVERSITY_ID |
|---|---|---|---|
| 1 | Иванов | 2 | 10 |
| 2 | Петров | 3 | 10 |
| 19 | Сидоров | 1 | 12 |
Здесь одна строка — один студент. Номер STUDENT_ID не повторяется. По UNIVERSITY_ID видно, что Иванов и Петров из одного вуза (10), но это не ключ студента: у одного вуза много студентов.
Ключ — это столбец или набор столбцов, по которым строку можно однозначно найти или связать с другой таблицей.
У каждой строки свой уникальный идентификатор. В STUDENT это STUDENT_ID.
STUDENT_ID.Столбец в одной таблице ссылается на первичный ключ другой. STUDENT.UNIVERSITY_ID ссылается на UNIVERSITY.UNIVERSITY_ID.
Смысл: «студент ссылается на существующий вуз». Если в справочнике нет вуза с номером 999, вставить студента с UNIVERSITY_ID = 999 нельзя — СУБД вернёт ошибку. Так сохраняется целостность данных.
Рисунок 2. PK — «имя строки внутри таблицы». FK — «ссылка на строку другой таблицы».
Правило:STUDENT_IDопределяетSURNAME. Оно читается так: если в двух строках таблицы совпадает номер студента, совпадает и фамилия. Ещё проще: по номеру студента фамилия определяется однозначно — не «может быть Иванов, а может Петров».
Если правило задают два столбца сразу: «STUDENT_ID и SUBJECT_ID вместе определяют MARK» — у одного студента по одному предмету одна оценка.
Когда зависимости нет: по UNIVERSITY_ID нельзя однозначно узнать фамилию студента — в одном вузе учатся и Иванов, и Петров. Правила «UNIVERSITY_ID определяет SURNAME» для таблицы STUDENT нет.
Рисунок 3. Номер студента определяет фамилию (в рамках нашей базы).
| Запись | Смысл | Где живёт |
|---|---|---|
STUDENT_ID определяет SURNAME, KURS, UNIVERSITY_ID | По номеру студента известны фамилия, курс и вуз | Таблица STUDENT |
UNIVERSITY_ID определяет UNIVERSITY_NAME, CITY | По номеру вуза известны название и город | Таблица UNIVERSITY |
STUDENT_ID и SUBJ_ID вместе определяют MARK | Одна оценка студента по предмету (составной ключ) | Таблица EXAM_MARKS |
Если добавить в STUDENT столбец UNIVERSITY_NAME «для удобства», возникает зависимость UNIVERSITY_ID определяет UNIVERSITY_NAME, но название вуза будет копироваться у каждого студента.
| STUDENT_ID | SURNAME | UNIVERSITY_ID | UNIVERSITY_NAME | |
|---|---|---|---|---|
| Плохо | 1 | Иванов | 10 | МГУ |
| Плохо | 2 | Петров | 10 | МГУ |
Переименовали вуз — нужно обновить все строки студентов. Правильно: имя вуза только в UNIVERSITY, у студента — только UNIVERSITY_ID.
Важно: функциональная зависимость — это правило предметной области («один человек — одна фамилия»), а не команда SQL. Сначала формулируем правила, потом создаём таблицы на ЛР.
Иногда ключ составной (из нескольких столбцов). Чтобы проверить, может ли один столбец (или набор столбцов) быть ключом всей таблицы, строят замыкание — список всех столбцов, которые из него однозначно следуют по вашим правилам зависимостей.
На экзамене задачу часто дают в «абстрактном» виде — столбцы A, B, C, D и зависимости A определяет B. Это то же самое, что STUDENT_ID определяет SURNAME, только без имён из базы. Ниже — такой учебный пример; в работе с UniversityDB мысленно подставляйте свои столбцы.
STUDENT_ID или, в абстрактной задаче, только {A}).Таблица с столбцами A, B, C, D (без привязки к предметной области — типичная учебная задача на замыкание). Зависимости:
Шаг 1. Старт: {A}.
Шаг 2. Из правила «A определяет B»: добавляем B — получаем {A, B}.
Шаг 3. Из правила «B определяет C»: добавляем C — получаем {A, B, C}.
Шаг 4. Из правила «A определяет D»: добавляем D — получаем {A, B, C, D} — все столбцы таблицы.
Вывод: A — ключ (суперключ) этой таблицы.
Рисунок 4. Каждый шаг — применение одного правила «столбец определяет столбец».
Формальные правила вывода (аксиомы Армстронга) в программе экзамена упоминаются; для практики достаточно уметь пройти один пример, как выше, и понимать смысл «X определяет Y».
На ЛР №2 вы создаёте таблицы UNIVERSITY, STUDENT, SUBJECT и другие: команды SQL берутся из приложения, раздел «Сборка базы по шагам». Затем выполняете первые SELECT.
Вопросы для самопроверки:
STUDENT_ID, если есть фамилия?UNIVERSITY_ID, если можно хранить название вуза текстом в строке студента?UNIVERSITY_ID, которого нет в UNIVERSITY?STUDENT_ID определяет SURNAME?Краткие ответы:
Итог. Реляционная модель — это язык правил между столбцами. Ключи находят строки и связывают таблицы. Функциональные зависимости описывают, кто из кого следует. Без этого SQL превращается в набор скриптов «по образцу», а на курсовой и экзамене нужно объяснять почему схема устроена так.
О чём эта лекция. Вы уже разделяли данные на таблицы и записывали функциональные зависимости. Сегодня — одна линия повествования: сначала увидим, что ломается, если всё свалить в одну таблицу; затем введём термины сущность и нормализация; в конце — нормальные формы как чек-лист проектирования.
Главная мысль одной фразой: один и тот же факт должен храниться в одном месте; повторение «старосты» или «названия вуза» в каждой строке — источник ошибок при UPDATE, INSERT и DELETE.
После прочтения вы сможете:
UniversityDB;Связь с реляционной моделью
Вы уже знаете: UNIVERSITY_IDопределяетUNIVERSITY_NAME, поэтому название вуза не копируют в каждую строку STUDENT. Лекция 3 даёт имя этому приёму — нормализация — и показывает, что бывает, если правило «один факт — одно место» нарушить.
| № | Тема |
|---|---|
| 1 | Один пример «плохой» таблицы — три аномалии |
| 2 | Сущность и связь (определения) |
| 3 | Нормализация и нормальные формы 1НФ–3НФ |
| 4 | Декомпозиция и схема UniversityDB |
| 5 | Мини-задача и самопроверка |
Дальше держим в голове одну учебную таблицу ОЦЕНКИ_ПЛОХО. Каждая строка — оценка студента по предмету, но в таблицу «навешали» ещё данные о группе и старосте:
| STUDENT | GROUP_NO | MONITOR | SUBJECT | MARK |
|---|---|---|---|---|
| Иванов | 31 | Петрова | SQL | 5 |
| Петров | 31 | Петрова | БД | 4 |
| Сидорова | 32 | Козлов | SQL | 3 |
Фамилия «Петрова» (староста 31-й группы) повторяется в двух строках. Это не «мелочь Excel» — при работе через SQL Server те же правила: если факт записан много раз, его трудно менять согласованно.
Группе 31 назначили нового старосту. Нужно найти все строки с GROUP_NO = 31 и везде заменить MONITOR. Забали одну строку — в базе две разные «истины» об одной группе.
Завели новый предмет «Архитектура БД», но пока никто не сдал — строк с этим предметом нет. Если предмет «живёт» только внутри строк с оценками, справочник предметов в базу не добавить.
Из группы 32 ушли все студенты (удалили последние строки с GROUP_NO = 32). Вместе с оценками исчезла и единственная запись «староста группы 32 — Козлов», хотя группа как учебная единица могла бы остаться в справочнике.
Запишите в тетрадь — три аномалии
Аномалия обновления — один факт продублирован во многих строках; изменить его нужно везде сразу.
Аномалия вставки — нельзя занести справочные данные, не создав «лишнюю» строку с оценкой или студентом.
Аномалия удаления — удаляя строку по одному смыслу, теряем данные по другому смыслу, записанные в той же строке.
Общий вывод шага 1: в одной строке смешаны факты разного типа (оценка, студент, группа, староста). Разделим их — аномалии исчезнут. Как именно делить — шаги 2–4.
Рисунок 1. Справа — та же информация без дублирования старосты в каждой строке с оценкой.
Вы уже создавали отдельные таблицы UNIVERSITY, STUDENT, EXAM_MARKS. Каждая описывает свой тип объектов из предметной области (вуз, студент, факт сдачи). В проектировании БД такой тип называют сущностью.
Запишите в тетрадь — сущность
Сущность — тип объектов предметной области, о которых нужно хранить однотипные сведения (студенты, вузы, предметы, оценки).
Одна сущность в реляционной модели обычно соответствует одной таблице. Строка таблицы — один конкретный объект этого типа (один студент, одна оценка).
Запишите в тетрадь — связь между сущностями
Связь — правило, как объекты разных сущностей соотносятся друг с другом.
STUDENT.UNIVERSITY_ID → UNIVERSITY.EXAM_MARKS (студент + предмет → оценка).Пример на UniversityDB: сущности «Вуз», «Студент», «Предмет»; связь студент–вуз — 1:N; связь студент–предмет через оценку — M:N и вынесена в EXAM_MARKS. Название вуза хранится один раз в UNIVERSITY — это уже следствие нормализации, к формальным правилам переходим дальше.
Запишите в тетрадь — нормализация
Нормализация — приведение схемы БД к виду, где каждый факт хранится в одном месте, без лишних повторов и без смешения разных сущностей в одной «широкой» строке.
Инструмент проверки — нормальные формы (1НФ, 2НФ, 3НФ). Идём по шагам: каждый следующий шаг устраняет свой класс ошибок.
Сначала таблица должна быть «атомарной»: в каждой ячейке одно значение, без списков «SQL, БД, физика» в одной клетке и без повторяющихся столбцов «Предмет1, Предмет2, Предмет3» (как в журнале Excel с новым предметом = новым столбцом).
Запишите в тетрадь — 1НФ
1НФ: все значения атомарны; нет повторяющихся групп столбцов. Таблицы после CREATE TABLE в SQL Server, как правило, уже в 1НФ.
1НФ выполнена. Дальше смотрим на составной первичный ключ (два столбца и больше). Правило: каждый неключевой столбец должен зависеть от всего ключа, а не от одной его части.
Пример. В EXAM_MARKS ключ — пара (STUDENT_ID, SUBJ_ID). Оценка MARK имеет смысл только когда известны и студент, и предмет. Зависимость «только от STUDENT_ID» для оценки была бы ошибкой (один студент — одна оценка на все предметы).
Запишите в тетрадь — 2НФ
2НФ: 1НФ + каждый неключевой атрибут зависит от полного первичного ключа (важно при составном ключе).
2НФ выполнена. Запрет «цепочек» между неключевыми столбцами: если A → B и B → C, то C не должно висеть в той же таблице, что и A, когда B — не ключ.
Пример из проектирования таблиц. Таблица STUDENT(STUDENT_ID, SURNAME, UNIVERSITY_ID, UNIVERSITY_NAME) нарушает 3НФ: UNIVERSITY_ID → UNIVERSITY_NAME, но UNIVERSITY_ID не ключ всей таблицы студентов. Исправление — вынести вуз в UNIVERSITY, оставить только UNIVERSITY_ID.
Запишите в тетрадь — 3НФ
3НФ: 2НФ + нет транзитивных зависимостей: неключевой столбец не должен зависеть от другого неключевого столбца (только от ключа).
Нормальная форма Бойса — Кодда (НФБК) строже 3НФ: любая нетривиальная зависимость «X определяет Y» должна исходить из суперключа. На экзамене часто достаточно 3НФ; UniversityDB спроектирована в духе 3НФ/НФБК.
Запишите в тетрадь — декомпозиция
Декомпозиция (без потерь) — разбиение одной таблицы на несколько так, что исходные данные можно восстановить соединением (JOIN) по ключам, без потери и без лишних «выдуманных» строк.
| До декомпозиции | После (без потерь) | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Пример 1 — нарушение 3НФ Один «широкий»
Название вуза дублируется — аномалия обновления при переименовании. | Две таблицы + JOIN
Имя вуза — один раз; студент ссылается числом | ||||||||||||||||||||
| Пример 2 — таблица из §1
| Три сущности (рис. 1)
Восстановление: | ||||||||||||||||||||

На скриншоте ищите:
UniversityDB → Tables.UNIVERSITY, STUDENT, EXAM_MARKS — не одна «широкая».Рисунок 2. Эталон на сервере уже декомпозирован — так должна выглядеть схема после нормализации.
Связка шагов 1–4
Сначала увидели аномалии в «широкой» таблице (§1), ввели сущности и связи (§2), проверили 1НФ–3НФ (§3), затем декомпозировали без потери данных (§4). На ЛР №3 вы повторите тот же ход для предметной области «Библиотека».
Цена и выигрыш: в запросах чаще нужен JOIN; зато переименование вуза или смена старосты — одна правка в справочнике, без аномалий обновления.
Связь с практикой: схема из ЛР №2 уже декомпозирована. На ЛР №3 вы спроектируете схему «Библиотека» с PK, FK, UNIQUE и CHECK и сможете аргументировать, какие нормальные формы выполняет каждая таблица.
Интернет-магазин свалили в одну таблицу: (order_id, customer_name, customer_city, product_name, price, qty).
Ожидаемый ответ: CUSTOMER, PRODUCT, ORDERS (шапка), ORDER_ITEM (товар, количество, цена на момент покупки); аномалия обновления при смене города клиента; связи через ключи заказа и покупателя.
UniversityDB.ОЦЕНКИ_ПЛОХО?EXAM_MARKS — отдельная таблица, а не столбцы «математика», «физика» в STUDENT?STUDENT(UNIVERSITY_ID, UNIVERSITY_NAME) без UNIVERSITY?Итог. Сначала — аномалии «широкой» таблицы; затем — сущности и связи как язык проектирования; затем — нормализация и 1НФ–3НФ как чек-лист. UniversityDB — готовый образец; на лабораторных вы повторяете тот же ход мысли для новой предметной области.
О чём эта лекция. Вы уже знаете схему UniversityDB в «одиночном» режиме. В реальности к одному серверу СУБД подключаются десятки пользователей, а данные крупных организаций могут лежать на нескольких серверах. Разберём, чем отличается многопользовательский режим от «одного файла на диске» и что такое распределённая база данных.
Главная мысль одной фразой: многопользовательская СУБД — это общий сервер с отдельными сеансами; распределённая БД — логически одна база на нескольких узлах, где приложение не должно знать физическое размещение каждой строки.
После прочтения вы сможете:
| № | Тема |
|---|---|
| 1 | Многопользовательский режим, клиент–сервер, файлы базы |
| 2 | Распределённая БД, фрагментация, сравнение с «двумя Excel» |
| 3 | Конфликты одновременного доступа — введение |
| 4 | Мини-задачи, частые ошибки в понимании |
| 5 | Самопроверка; изменение схемы (ALTER TABLE) — на практике |
Как разобрать тему. Идите по материалу на странице: рис. 1 → таблица §1.1 → задание §1.3 в тетради; затем рис. 2 и таблица §3.1. Так вы свяжете «один работал один» с моделью «много сеансов — одни таблицы на сервере».
Вы уже создали UniversityDB, таблицы и первые SELECT — каждый выполнял задания сам по себе. В этом разделе разберём по схемам и таблицам ниже, что меняется, когда к одному экземпляру СУБД на сервере одновременно обращаются много пользователей: у каждого свой сеанс (session) — свой запрос, свой результат, свои права, но общие таблицы на диске сервера.
Тот же принцип в вузе: деканат, бухгалтерия, электронная библиотека обращаются к одной серверной базе через разные программы (учётные системы, порталы), а не через «личный файл на ноутбуке». Промышленные СУБД (в том числе SQL Server) изначально рассчитаны на такой режим.
Запишите в тетрадь — многопользовательский режим
Многопользовательская СУБД — один экземпляр сервера баз данных обслуживает много одновременных подключений; данные хранятся централизованно, доступ координирует СУБД.
Запишите в тетрадь — сеанс (session)
Сеанс — одно логическое подключение клиента к серверу: свой идентификатор сеанса, свой текущий запрос и результат. Два пользователя = два сеанса, одна и та же база на сервере.
| Ситуация | Многопользовательский сервер (SQL Server) | Файл SQLite |
|---|---|---|
| Кто хранит данные | Служба SQL Server на диске сервера | Один файл .db на диске |
| Кто подключается | Много клиентов по сети | Обычно одно приложение рядом с файлом |
| Запись одновременно | СУБД координирует блокировки и транзакции | Часто один писатель, остальные ждут |
| Наш курс | Основной стенд в классе | Упоминаем как «база в одном файле» для сравнения |
Аналогия: банк — не один кассир с тетрадкой, а общая система учёта, к которой обращаются многие операторы; SQLite ближе к личной записной книжке на одном столе.
Запишите в тетрадь — SQLite vs сервер (образ)
SQLite — часто один файл и одно приложение рядом; удобно для прототипа. SQL Server на курсе — образец сетевой многопользовательской СУБД с центральным хранением.
Клиент — программа на компьютере пользователя (или приложение вуза): формирует запрос на языке SQL и показывает результат. Сервер СУБД — служба на машине сервера: принимает запрос, выполняет его и возвращает ответ или сообщение об ошибке. Каждое подключение клиента — отдельный сеанс.
Важно: таблицы UniversityDB, с которыми вы уже работали при сборке схемы, физически хранятся на диске сервера, а не «внутри окна программы» на вашем ПК. У SQL Server это обычно пара файлов:
.mdf — основной файл данных (таблицы, индексы);.ldf — журнал транзакций (протокол изменений до их окончательной фиксации в базе).Закрыли клиент — база на сервере осталась; другие сеансы продолжают работу.
Запишите в тетрадь — клиент и сервер
Клиент — отправляет SQL и показывает результат. Сервер СУБД — хранит данные, выполняет запросы, следит за правилами (PK, FK). Данные на диске сервера, не в клиенте.
Запишите в тетрадь — файлы .mdf и .ldf
.mdf — основное хранилище таблиц. .ldf — журнал изменений для надёжной фиксации транзакций. Это физический уровень; логически вы по-прежнему видите таблицы STUDENT, UNIVERSITY и т.д.
Рисунок 1. Два клиента — два сеанса; одни и те же таблицы на диске сервера (.mdf / .ldf).

Рисунок 1а. Клиент: диалог подключения к серверу (Database Engine).

Рисунок 1б. Клиент: окно запроса — сюда пишут SQL; выполняет сервер, результат показывает клиент. Логическая цепочка «два сеанса — один сервер — .mdf/.ldf» — на рис. 1.
Нарисуйте схему: два «Клиента», один «SQL Server», стрелки запрос–ответ, справа — блок «.mdf + .ldf». Подпишите: у клиента 1 сеанс 52, у клиента 2 сеанс 61; оба читают таблицу STUDENT с теми же 19 строками, из эталонного набора (19 студентов).
Вопрос для ответа устно: если клиент 1 только читает, а клиент 2 меняет стипендию одной строки — почему без правил СУБД возможен конфликт? (Разбор — в §3 ниже.)
Запишите в тетрадь — распределённая БД
Распределённая БД — логически одна база для приложения, физически данные на нескольких узлах. Не путать с двумя несвязанными Excel или двумя копиями базы на флешках.
Распределённая БД — логически одна база для приложения, физически данные на нескольких узлах (серверах, городах, дата-центрах). Идеал — прозрачность размещения: формулируется обычный запрос к таблице STUDENT, а система сама обращается к нужному узлу.
Запишите в тетрадь — прозрачность размещения
Прозрачность размещения — приложение не обязано знать, на каком сервере лежит строка; маршрутизацию выполняет СУБД или промежуточный слой.
| Ситуация | Это распределённая БД? | Почему |
|---|---|---|
| Деканат — Excel, кафедра — Access, без связи | Нет | Нет общих FK, нет единой транзакции, дубли и расхождения |
Две копии UniversityDB на разных флешках | Нет | Это две независимые базы, не один каталог |
| Студенты Воронежа на сервере A, Москвы — на B, запрос «как к одной STUDENT» | Да (идея) | Единая схема, согласованность, общий SQL |
Горизонтальная — строки таблицы делят по правилу. Пример для UniversityDB: студенты с CITY = N'Воронеж' на узле 1, остальные — на узле 2. Для пользователя запрос SELECT COUNT(*) FROM STUDENT может прозрачно собрать сумму с обоих узлов.
Вертикальная — редкие или «тяжёлые» столбцы выносят на отдельный узел. Пример: в STUDENT оставить STUDENT_ID, SURNAME, KURS на основном сервере, а BIRTHDAY — на узле архива. На курсе вертикальную фрагментацию достаточно понимать на уровне идеи.
Запишите в тетрадь — фрагментация
Горизонтальная — делим строки таблицы по правилу (например, по городу). Вертикальная — делим столбцы (редкие или большие поля на отдельный узел).
Рисунок 2. Одна таблица «логически», физически — части на разных серверах.
Когда два сеанса меняют одни и те же строки, без правил координации возможны сбои. СУБД решает это через транзакции (группа команд «всё или ничего»), блокировки и настраиваемые уровни изоляции — их свойства разберём по курсу отдельно; здесь — картина целиком и один наглядный пример.
Запишите в тетрадь — конкурентный доступ
Конкурентный (параллельный) доступ — несколько сеансов одновременно читают и пишут одни таблицы. Ограничения PK/FK не заменяют правила согласования одновременных изменений одной строки.
Студенту STUDENT_ID = 1 стипендия 150. Сеанс A и сеанс B одновременно делают разные изменения:
| Шаг | Сеанс A | Сеанс B | STIPEND в базе (если нет блокировок) |
|---|---|---|---|
| 1 | Читает 150 | Читает 150 | 150 |
| 2 | Пишет 150 + 50 = 200 | — | 200 |
| 3 | — | Пишет 150 + 30 = 180 (от старого 150!) | 180 |
Оба изменения «имели право» быть учтёнными (+50 и +30), но в базе осталось 180 — приращение A потерялось. Это потерянное обновление. Решение — согласованные транзакции и блокировки при записи.
Запишите в тетрадь — потерянное обновление
Потерянное обновление — два сеанса прочитали одно значение, оба записали своё; одно изменение затёрлось. Транзакция связывает связанные команды в одно целое; блокировка не даёт второму сеансу испортить чужое незавершённое изменение.
STUDENT_ID.Но FK не мешает двум корректным UPDATE «перезаписать» друг друга — для этого нужны транзакции.
UniversityDB.mdf на диске сервера» — хранилище данных.DROP DATABASE, если их выдали по ошибке.Ответы: (2) нет единой схемы и транзакций между JSON и SQL; (3) сосед работает с тем же сервером, но не «внутри» вашего окна — права ограничивает администратор.
| Ошибка | Как правильно |
|---|---|
| «База хранится в программе на ПК» | Клиент только отправляет SQL; файлы данных — на сервере |
| «SQLite и SQL Server — одно и то же для курса» | Идеи SQL общие; многопользовательская модель — на SQL Server |
| «Распределённая = две копии на флешках» | Нужна согласованность и единый логический каталог |
| «FK защищает от всех конфликтов двух пользователей» | FK про ссылки между таблицами; параллельные UPDATE — про транзакции |
UniversityDB — на диске сервера или «внутри программы-клиента» на ПК?STUDENT.session) и почему у двух пользователей, подключённых к одному серверу, сеансы различаются?ALTER TABLE, индекс, разделитель пакетов GO).Итог. Многопользовательский режим — норма: один сервер СУБД, много сеансов, данные в .mdf/.ldf. Распределённая БД — один логический каталог на нескольких узлах; это не два несвязанных файла. Конфликты при одновременной записи требуют транзакций и правил изоляции. Изменение схемы на живой базе (ALTER TABLE, индексы, GO) — отдельная практическая тема курса.
О чём эта лекция. Когда несколько пользователей меняют одни таблицы, операции нельзя выполнять «как попало»: перевод стипендии — это два UPDATE, и оба должны сохраниться вместе или отмениться вместе. Такие группы операций называются транзакциями.
Главная мысль одной фразой: транзакция с свойствами ACID — договор между приложением и СУБД: после COMMIT изменения надёжны и согласованы с ограничениями, после ROLLBACK — как будто их не было.
После прочтения вы сможете:
UniversityDB;BEGIN TRAN … COMMIT / ROLLBACK;SAVE TRAN для частичного отката.| № | Тема |
|---|---|
| 1 | Зачем транзакция; пример перевода стипендии |
| 2 | ACID на примерах UniversityDB |
| 3 | BEGIN, COMMIT, ROLLBACK, SAVE TRAN — разбор в SSMS |
| 4 | Мини-задачи, что СУБД не гарантирует |
| 5 | Самопроверка, связь с ЛР №6 |
Запишите в тетрадь — транзакция
Транзакция — группа команд: COMMIT или ROLLBACK для всех сразу.
Вы уже видели потерянное обновление: два сеанса читают одну стипендию и пишут разные суммы — одно изменение пропадает. Транзакция — способ сказать серверу: «эти команды — одно целое».
Транзакция — группа операций, которые выполняются как одно целое: либо все изменения сохраняются (COMMIT), либо ни одно (ROLLBACK).
Перевод 1000 рублей стипендии от студента STUDENT_ID = 1 студенту STUDENT_ID = 3:
Если второй UPDATE упадёт (например, нарушится CHECK на отрицательную стипендию), первый тоже должен откатиться — иначе деньги «исчезнут» из системы.
Рисунок 1. Два UPDATE в одной транзакции — атомарность (A).
Запишите в тетрадь — ACID (кратко)
A — атомарность; C — согласованность (PK/FK/CHECK); I — изоляция; D — durability после COMMIT.
| Свойство | Смысл | Пример на UniversityDB |
|---|---|---|
| A — Atomicity | Всё или ничего | Оба UPDATE стипендии зафиксированы или оба отменены |
| C — Consistency | БД остаётся в согласованном состоянии | После COMMIT выполняются FK, CHECK, NOT NULL |
| I — Isolation | Параллельные транзакции не мешают друг другу | Уровни изоляции SQL-92 |
| D — Durability | После COMMIT данные переживут сбой | Запись в журнал .ldf до ответа клиенту |
Гарантирует: ограничения, объявленные в схеме — STIPEND >= 0, оценка 2–5, существующий UNIVERSITY_ID.
Не гарантирует автоматически: «суммарная стипендия группы не больше N», «число отличников не меньше 50%» — такие правила программируют в процедурах или проверяют в приложении.
После успешного COMMIT SQL Server сначала записывает изменения в журнал транзакций (.ldf), затем подтверждает клиенту. При сбое питания восстановление идёт по журналу (подробнее — в разделах о резервном копировании и восстановлении).
На ЛР №6 вы будете выполнять опасные UPDATE и DELETE внутри транзакции с ROLLBACK, чтобы не испортить эталон. Сейчас — та же техника на простом примере.
После ROLLBACK стипендии должны совпасть с тем, что было до BEGIN TRAN. Вкладка Results — два одинаковых набора строк; на Messages — «Rollback Tran».

Окно запроса: транзакция с ROLLBACK — безопасный способ «попробовать» UPDATE на учебном сервере.

Два одинаковых результата SELECT — признак успешного отката.
SAVE TRAN — промежуточная «закладка». ROLLBACK TRAN step1 откатывает до неё, но транзакция продолжается до COMMIT или полного ROLLBACK.
На ЛР №16 разберёте TRY/CATCH подробнее. Здесь важно: при ошибке нужен ROLLBACK, иначе транзакция «висит» открытой.
UNIVERSITY_ID = 999? Почему?BEGIN TRAN не завершён, видят ли соседи ваши незафиксированные строки? (Зависит от уровня изоляции — по умолчанию частично защищены.)ACID не обещает: высокую скорость, отсутствие тупиков, защиту от удаления диска без резервной копии.
| Ошибка | Как правильно |
|---|---|
Забыли COMMIT | Транзакция держит блокировки; закройте окно или выполните ROLLBACK |
UPDATE без WHERE в транзакции и случайный COMMIT | Сначала SELECT с тем же WHERE, на ЛР — только ROLLBACK |
| Путают ROLLBACK и DELETE | ROLLBACK отменяет незафиксированные изменения; DELETE — DML-команда |
STIPEND >= 0 — про Consistency, а «фонд группы ≤ N» — уже нет?ROLLBACK вместо COMMIT?SAVE TRAN отличается от полного ROLLBACK?BEGIN TRAN … ROLLBACK на практике?Итог. Транзакция группирует операции; ACID описывает гарантии СУБД. На практике в SSMS освоите BEGIN TRAN, COMMIT, ROLLBACK и SAVE TRAN. Перед опасными изменениями на общем сервере — откат, а не коммит.
О чём эта лекция. Если две транзакции работают параллельно без изоляции, результат может отличаться от любого последовательного выполнения. У каждой такой ситуации есть имя — аномалия.
Главная мысль одной фразой: потерянное обновление, грязное, неповторяемое и фантомное чтение — четыре классических конфликта; зная их, вы сможете выбрать подходящий уровень изоляции.
После прочтения вы сможете:
| № | Тема |
|---|---|
| 1 | Четыре аномалии на примерах UniversityDB |
| 2 | Расписания операций T1 / T2 |
| 3 | Шпаргалка, отличия похожих случаев |
| 4 | Мини-задачи, частые ошибки |
| 5 | Самопроверка; ЛР №6 |
Запишите в тетрадь — четыре аномалии
Вы уже группировали команды в транзакции. Если две транзакции идут параллельно, а изоляция недостаточна, результат может не совпасть ни с одним «честным» последовательным порядком. Такие эффекты имеют имена — их нужно узнавать на слух.
Два сеанса читают одно значение, оба считают от него, оба пишут — одно изменение затирается.
Пример со складом: 40 учебников. T1 продаёт 10 → пишет 30. T2 продаёт 5, но считала от 40 → пишет 35. Продано 15, в базе 35 — продажа T1 потеряна.
Пример из UniversityDB: два сеанса одновременно меняют STIPEND одного студента — при одновременной работе нескольких сеансов.
T1 изменила строку, но ещё не сделала COMMIT. T2 прочитала «новое» значение. T1 откатилась — T2 опиралась на данные, которых «не было».
Пример: T1 в транзакции начислила стипендию +500 и напечатала ведомость для проверки; T2 по этой сумме выдала справку; T1 сделала ROLLBACK — справка ложная.
T1 дважды читает одну и ту же строку — между чтениями T2 изменила и зафиксировала её.
Пример: T1 дважды читает RATING вуза ВГУ (UNIVERSITY_ID = 10): сначала 450, потом 470 — между чтениями другой сеанс обновил строку и сделал COMMIT.
T1 дважды выполняет один и тот же запрос с условием — второй раз набор строк другой: появились или исчезли строки, подходящие под условие.
Пример: T1: SELECT COUNT(*) FROM dbo.STUDENT WHERE KURS = 1 → 4. T2 вставила нового первокурсника и сделала COMMIT. T1 повторяет COUNT → 5. «Лишняя» строка — фантом.
Рисунок 1. Нарисуйте такую схему на листе для любой аномалии — так проще объяснить конфликт.
| Аномалия | Что ломается | Пример в нашей БД |
|---|---|---|
| Потерянное обновление | Два WRITE одного поля | Два UPDATE STIPEND одного STUDENT_ID |
| Грязное чтение | Чтение до COMMIT | SELECT стипендии до отката чужой транзакции |
| Неповторяемое чтение | Одна строка изменилась | Два SELECT RATING одного вуза |
| Фантом | Изменился набор по условию | Два COUNT первокурсников |
Вопрос для разбора: отчёт дважды посчитал средний балл по предмету: 4.1 и 3.9, потому что между расчётами исправили одну оценку. Это неповторяемое чтение (изменилась конкретная строка в EXAM_MARKS).
Если между двумя COUNT добавили новую ведомость (новую строку) — это фантом.
Если справку напечатали по стипендии до чужого COMMIT, а потом транзакция откатилась — грязное чтение.
ROLLBACK — связь с грязным чтением для соседей?Ответы: (1) потерянное обновление; (2) фантом; (3) незафиксированные изменения не должны остаться в общей базе — откат убирает «мусор» для других сеансов.
| Путают | Как запомнить |
|---|---|
| Неповторяемое и фантом | Неповторяемое — одна строка; фантом — другой набор строк |
| Грязное и неповторяемое | Грязное — читали до COMMIT; неповторяемое — после чужого COMMIT |
| «Транзакция = нет аномалий» | Нужен ещё подходящий уровень изоляции |
STUDENT.Итог. Четыре аномалии — словарь для обсуждения параллельного доступа. Зная названия и примеры на UniversityDB, сопоставите их с уровнями изоляции SQL Server.
О чём эта лекция. Полная сериализуемость — идеал, но дорогой: транзакции будут долго ждать друг друга. SQL Server предлагает несколько уровней изоляции — осознанный компромисс между скоростью и точностью чтения.
Главная мысль одной фразой: уровень изоляции задаёт, какие аномалии допустимы; умолчание SQL Server — READ COMMITTED, для жёстких инвариантов берут REPEATABLE READ или SERIALIZABLE.
После прочтения вы сможете:
SET TRANSACTION ISOLATION LEVEL … в SSMS;| № | Тема |
|---|---|
| 1 | Компромисс «скорость / точность»; четыре аномалии доступа |
| 2 | Четыре уровня SQL-92 и таблица аномалий |
| 3 | Блокировки S и X; как уровень влияет на ожидание |
| 4 | SET TRANSACTION ISOLATION LEVEL в SSMS |
| 5 | Снимки (snapshot), SQLite, выбор уровня на практике |
| 6 | Мини-задачи, самопроверка, связь с ЛР №7–8 |
Вы уже разобрали четыре аномалии параллельного доступа. Идеальный вариант — когда транзакции ведут себя так, будто выполняются строго по очереди (сериализуемость). На практике полная сериализуемость дорога: сеансы долго ждут блокировок друг друга.
Уровень изоляции — явный договор: «я согласен на часть аномалий ради скорости». Вы выбираете, какие из четырёх аномалий допустимы в вашем сценарии.
Деканат строит отчёт «средний балл по предметам» — ему не нужны незафиксированные оценки (грязное чтение), но допустимо, что между двумя SELECT кто-то добавит новую ведомость (фантом). Кассовая операция «списать стипендию и зачислить на другой счёт» — наоборот, нужна жёсткая атомарность и минимум параллельных изменений одних строк.
Запишите в тетрадь — уровень изоляции
Уровень изоляции — какие из четырёх аномалий допускаются ради скорости.
Стандарт SQL-92 задаёт четыре уровня. В SQL Server по умолчанию — READ COMMITTED. Столбец «потерянное обновление» — тот же конфликт двух UPDATE одной строки).
| Уровень | Грязное | Неповтор. | Фантом | Потерянное обновление* | Где применяют |
|---|---|---|---|---|---|
READ UNCOMMITTED | да | да | да | да | Грубая оценка «на сейчас», мониторинг |
READ COMMITTED | нет | да | да | редко** | Умолчание SQL Server; обычные формы |
REPEATABLE READ | нет | нет | да | нет | Два чтения одной строки должны совпасть |
SERIALIZABLE | нет | нет | нет | нет | Короткие критичные операции |
* Упрощённо для курса. ** При обычных блокировках строк SQL Server на READ COMMITTED два одновременных UPDATE одной строки сериализуются — второй сеанс ждёт первый.
| Аномалия | Какой уровень запрещает первым |
|---|---|
| Грязное чтение | READ COMMITTED и выше |
| Неповторяемое чтение | REPEATABLE READ и выше |
| Фантом | SERIALIZABLE (или snapshot с подходящими настройками) |
| Потерянное обновление | Блокировки на запись; часто достаточно READ COMMITTED |
Рисунок 1. Запомните порядок уровней слева направо — его часто спрашивают на самопроверке.
СУБД реализует уровни через блокировки на строках, страницах или таблицах.
Если T1 держит X на строке STUDENT_ID = 1, T2 не сможет ни прочитать её «для изменения», ни обновить, пока T1 не сделает COMMIT или ROLLBACK.
На READ COMMITTED второй сеанс не увидит «грязную» стипендию до COMMIT первого — но может подождать, если первый ещё держит X.
Уровень задаётся для текущего сеанса до следующего изменения:

Окно New Query: команда SET TRANSACTION ISOLATION LEVEL перед BEGIN TRAN.

Результат агрегирующего SELECT — на следующей лабораторной (№7) вы считаете такие же средние без смены уровня изоляции.
Начиная с SQL Server 2005, есть версионность строк: читатели могут видеть согласованный «снимок» на момент начала транзакции, не блокируя писателей так жёстко, как при SERIALIZABLE. Режим включают на уровне базы (ALLOW_SNAPSHOT_ISOLATION) и задают SET TRANSACTION ISOLATION LEVEL SNAPSHOT. Для длинных отчётов по UniversityDB это часто удобнее, чем максимальная блокировка.
В SQLite нет полного набора четырёх уровней. BEGIN DEFERRED / IMMEDIATE / EXCLUSIVE задают, когда сеанс получает право записи. Для курса основной стенд — SQL Server; SQLite упоминаем только для сравнения.
| Сценарий | Разумный выбор | Почему |
|---|---|---|
| Онлайн-форма «показать баланс стипендии» | READ COMMITTED | Не показывать незафиксированные суммы |
| Отчёт «средний балл» на 50 страниц | Snapshot или READ COMMITTED | Долгое чтение не должно блокировать приём оценок |
| Перевод стипендии между двумя студентами | Короткая транзакция + проверки | Атомарность важнее «мягкой» изоляции чтения |
| Инвентаризация: два COUNT подряд должны совпасть | REPEATABLE READ или выше | Запрет неповторяемого чтения |
COMMIT?SELECT COUNT(*) FROM dbo.STUDENT WHERE KURS = 1 дали 4 и 5. Какая аномалия и какой уровень её убирает?SERIALIZABLE «везде по умолчанию»?Ответы: (1) READ COMMITTED; (2) фантом, SERIALIZABLE; (3) лишние ожидания и риск тупиков — блокировки и тупики.
| Ошибка | Как запомнить |
|---|---|
Путают уровень изоляции и BEGIN TRAN | Транзакция группирует команды; уровень — правила для параллельных транзакций |
Ждут, что READ COMMITTED убирает фантомы | Фантомы уходит только на SERIALIZABLE (или snapshot с нужной семантикой) |
| Меняют уровень в середине транзакции | В SQL Server уровень лучше задавать доBEGIN TRAN |
READ COMMITTED?SERIALIZABLE?ROLLBACK, хотя уровень по умолчанию уже READ COMMITTED?Итог. Уровень изоляции — осознанный компромисс: вы отмечаете в таблице, какие из четырёх аномалий допустимы. Умолчание SQL Server (READ COMMITTED) подходит для большинства учебных запросов; для жёстких инвариантов повышают уровень или используют snapshot.
О чём эта лекция. Блокировки защищают данные, но могут привести к тупику, когда две транзакции вечно ждут друг друга. Отдельно — репликация: копирование данных на другой сервер для отчётов и резерва.
Главная мысль одной фразой: тупик — следствие конкуренции, а не «поломка СУБД»; SQL Server выбирает жертву (ошибка 1205), а репликация снимает нагрузку с основного сервера.
После прочтения вы сможете:
CASE, COALESCE).| № | Тема |
|---|---|
| 1 | Связь блокировок с уровнями изоляции |
| 2 | Двухфазный протокол блокировок (2PL) |
| 3 | Тупик на примере UniversityDB |
| 4 | Ошибка 1205, профилактика |
| 5 | Репликация — зачем и виды |
| 6 | Мини-задачи, самопроверка, связь с ЛР №9–14 |
Вы уже выбирали уровень изоляции по таблице аномалий. Реализует это СУБД через блокировки: S на чтение, X на запись. Чем строже уровень, тем дольше блокировки держатся и тем чаще сеансы ждут друг друга.
Идея: блокировка — «бронь» на строку или страницу. Пока T1 держит X на строке STUDENT_ID = 1, T2 не может её изменить — это защита от потерянного обновления и грязного чтения.
Блокировать можно строку, страницу, всю таблицу. Без индекса фильтр WHERE CITY = N'Воронеж' иногда блокирует больше строк, чем нужно — отсюда рекомендация «нужные индексы» при проектировании отчётов по STUDENT.
Запишите в тетрадь — 2PL и тупик
2PL — сначала только берём блокировки, потом только снимаем. Тупик — цикл ожиданий (ошибка 1205).
Двухфазный протокол блокировок — правило, которому следуют многие СУБД:
Строгий вариант (Strict 2PL): все X-блокировки снимаются только при COMMIT или ROLLBACK. Так гарантируется, что никто не прочитает незафиксированную запись.
Рисунок 1. Схема 2PL — основа для понимания порядка конфликтов между транзакциями.
Тупик — цикл ожидания: T1 держит ресурс A и ждёт B; T2 держит B и ждёт A. Без вмешательства обе транзакции зависнут навсегда.
Два сеанса переводят стипендию между студентами, но в разном порядке блокируют строки:
Каждый сеанс держит «свою» строку и ждёт вторую — получается цикл. SQL Server строит граф ожидания, находит цикл и выбирает жертву.
Рисунок 2. Цикл в графе ожидания — признак тупика. СУБД откатывает одну из транзакций.
Код ошибки — 1205. Клиентское приложение может повторить транзакцию (обычно ограниченное число раз). На учебном сервере для демонстрации тупика нужны два окна SSMS — выполняйте только по указанию преподавателя.

Для демонстрации тупика открывают два окна New Query к одной базе — два независимых сеанса.
| Правило | Смысл на UniversityDB |
|---|---|
| Одинаковый порядок таблиц | Везде сначала STUDENT, потом EXAM_MARKS — не наоборот в разных процедурах |
| Короткие транзакции | Не держать BEGIN TRAN, пока пользователь думает над формой |
| Индексы по фильтрам | Меньше «широких» блокировок при WHERE UNIVERSITY_ID = … |
| Обработка 1205 | Повтор транзакции в коде приложения |
| Меньше лишней строгости | Не ставить SERIALIZABLE, если хватает READ COMMITTED |
Репликация — копирование данных (или изменений) на другой сервер. Зачем: отчёты не нагружают основной сервер, резервная копия «живых» данных, филиал в другом городе.
| Вид | Идея | Когда уместна |
|---|---|---|
| Снимковая | Периодически полная копия | Редко меняющиеся справочники |
| Транзакционная | Почти онлайн передача изменений | Актуальная копия для чтения |
| Слиянием (merge) | Изменения на нескольких узлах, потом сводят | Распределённые филиалы с локальной записью |
Реплика не заменяет транзакции и блокировки на основном сервере — это отдельный механизм доставки данных. Распределённая БД может хранить студентов по регионам, репликация — один из способов синхронизации узлов.
EXAM_MARKS, затем STUDENT — в разном порядке. Возможен тупик?ROLLBACK на ЛР №6 снижает риск конфликтов на общем сервере?Ответы: (1) да, если блокируют пересекающиеся ресурсы в разном порядке; (2) меньше времени держит X-блокировки; (3) транзакционная ближе к «онлайн», снимковая — с большим лагом между копиями.
Итог. Блокировки реализуют уровни изоляции; при неудачном порядке доступа возникает тупик — SQL Server выбирает жертву (1205). Репликация снимает нагрузку с основного узла, но не отменяет правила транзакций на master-базе.
О чём эта лекция. Не все данные удобно класть в таблицы с фиксированными столбцами. Разберём три «типа» данных и когда реляционная модель остаётся лучшим выбором, а когда — JSON, документы или файловое хранилище.
Главная мысль одной фразой: структурированные данные — основа курса (UniversityDB); полуструктурированные и неструктурированные требуют других моделей, но метаданные часто всё равно хранят в SQL Server.
После прочтения вы сможете:
| № | Тема |
|---|---|
| 1 | Три типа данных на примерах вуза и UniversityDB |
| 2 | Модели хранения: реляционная, документная, key-value |
| 3 | Где хранят файлы и метаданные |
| 4 | Big Data — три «V» обзорно |
| 5 | Мини-задачи, самопроверка; ЛР №17–19 |
Запишите в тетрадь — три типа данных
Структурированные (SQL), полуструктурированные (JSON/XML), неструктурированные (PDF, видео).
До сих пор курс опирался на структурированные данные — таблицы SQL с фиксированными столбцами. Реальная информационная система вуза смешивает и другие форматы.
Строки и столбцы с типами, ограничениями, связями FK. Весь эталон UniversityDB: STUDENT, EXAM_MARKS, UNIVERSITY. Запросы SELECT, GROUP BY (ЛР №7–8), подзапросы (ЛР №9–10) работают именно с такими данными.
Есть именованные поля и вложенность, но схема гибче таблицы:
{"pair": 3, "subject": "Базы данных", "room": "220"}.timestamp, level, message, но набор полей может меняться.Нет фиксированной таблицы полей: PDF заявления, фото студбилета, видеолекция. В SQL Server обычно хранят метаданные (имя файла, дата, автор, ссылка), а сам файл — в файловом или объектном хранилище (S3, SharePoint, сетевой диск).
Рисунок 1. UniversityDB — левый столбец; к концу семестра добавятся XML и документная MongoDB.
| Модель | Пример СУБД | Как выглядит | Когда уместна |
|---|---|---|---|
| Реляционная | SQL Server | Таблицы, FK, JOIN | Учёт, отчёты, строгие связи (оценки ↔ студенты) |
| Документная | MongoDB | Документ JSON/BSON | Гибкая схема, вложенные объекты (анкета с разным числом полей) |
| Иерархическая / XML | XML в SQL Server | Дерево элементов | Обмен между системами, XSD-контракт |
| Key-Value | Redis | Ключ → значение | Кэш сессий, счётчики, очереди |
Отчёт «средний балл по кафедрам с JOIN трёх таблиц» на нормализованной схеме проще и надёжнее в SQL. Документная модель хороша, когда структура записи часто меняется или глубоко вложена — например, черновик анкеты абитуриента с опциональными блоками.
Гибрид: основные учётные данные — SQL Server; кэш или лог — Redis; обмен — XML; прототип мобильного приложения — MongoDB (ЛР №19).
После §2
Модель хранения под задачу: учёт — SQL; обмен — XML; кэш — key-value. PDF в БД обычно не хранят целиком.
Хранить большой PDF в столбце VARBINARY(MAX)можно, но на практике:
Типичная схема: таблица DocumentMeta(FileId, StudentId, FileName, StoredAt, StorageUrl) — структурированные метаданные; путь или URL — на неструктурированный файл снаружи.
На ЛР №17 вы загрузите настоящий XML в тип XML — это полуструктурированные данные внутри реляционной СУБД.
Когда данных слишком много для одного SQL Server на одном диске, говорят о Big Data. Три «V» (без формул на экзамене — только смысл):
| «V» | Смысл | Пример |
|---|---|---|
| Volume (объём) | Терабайты и больше | Логи посещаемости LMS за годы |
| Velocity (скорость) | Поток данных в реальном времени | Датчики, клики на портале |
| Variety (разнообразие) | Разные форматы одновременно | Таблицы + JSON + видео |
Для учебной UniversityDB (19 студентов, 24 оценки) достаточно одного SQL Server. Big Data — контекст, зачем в индустрии появляются Hadoop, Spark, озёра данных.
EXAM_MARKS, JSON расписания, скан диплома.Ответы: (1) структурированные, полуструктурированные, неструктурированные (+ метаданные в SQL); (2) целостность FK, транзакции, отчёты GROUP BY; (3) когда набор полей у записей сильно различается.
UniversityDB.VARBINARY «на всякий случай»?Итог. Структурированные таблицы — основа курса и большинства учётных систем вуза. Полуструктурированные и неструктурированные данные требуют других инструментов, но метаданные о них часто всё равно лежат в SQL Server.
О чём эта лекция. XML — стандарт обмена иерархическими данными между системами. Разберём синтаксис, отличие well-formed от valid документа и как SQL Server хранит XML в столбце типа XML.
Главная мысль одной фразой: XML описывает дерево элементов и атрибутов; XSD задаёт правила, а XPath и методы .value() / .query() извлекают нужные узлы прямо в T-SQL.
После прочтения вы сможете:
| № | Тема |
|---|---|
| 1 | Синтаксис XML: элементы, атрибуты, пролог |
| 2 | Well-formed и valid; роль XSD |
| 3 | XPath на примере вуза и студентов |
| 4 | Тип XML в SQL Server: .value(), .query() |
| 5 | XML vs JSON; мини-задачи, связь с ЛР №17 |
Запишите в тетрадь — well-formed / valid
Well-formed — корректное дерево; valid — по XSD.
Вы уже различали типы данных на структурированные таблицы и полуструктурированные форматы. XML — один из стандартов обмена иерархическими данными между организациями: банк, деканат, госуслуги могут требовать файл по XSD-схеме, а не «произвольный Excel».
UniversityDB остаётся реляционной; XML понадобится, когда нужно передать фрагмент данных (список студентов вуза) в систему партнёра или сохранить документ в столбце XML рядом с ключами SQL.
<Name>…</Name>.id="22" в открывающем теге; не путать с дочерним элементом.University).<?xml …?> с версией и кодировкой (UTF-8 для кириллицы).Рисунок 1. Корень, дочерние элементы и атрибут — базовая модель для XPath.
| Проверка | Что смотрит | Пример ошибки |
|---|---|---|
| Well-formed | Синтаксис: закрытые теги, одна корневая вершина | <Name>МГУ<City>… без закрытия |
| Valid | Соответствие XSD/DTD: обязательные поля, типы | Нет атрибута id у University |
Парсер SQL Server при вставке в XML сначала проверяет well-formed. Valid — ответственность обмена: партнёр отклонит файл, не прошедший XSD.
maxOccurs="unbounded" — сколько угодно студентов; use="required" — атрибут id обязателен.
XPath — язык путей к узлам. Примеры для документа выше:
| XPath | Результат |
|---|---|
/University/Name | Элемент с названием вуза |
/University/Student[@kurs='1'] | Студенты первого курса |
//Student | Все элементы Student на любой глубине |
(/University/Name)[1] | Первый Name (для .value() в SQL) |
Столбец типа XML хранит документ внутри таблицы. Основные методы T-SQL:
.value() — одно скалярное значение (как подзапрос с одной строкой). .query() — фрагмент XML (несколько узлов). На ЛР №17 вы создадите таблицу dbo.UnivXml и загрузите похожий документ.

Окно New Query: переменная типа XML и метод .value().
| Критерий | XML | JSON |
|---|---|---|
| Типичное применение | Банки, госсистемы, старые интеграции | REST API, веб и мобильные клиенты |
| Схема | XSD, строгий контракт | JSON Schema (реже в старых системах) |
| В SQL Server | Тип XML, XPath | OPENJSON, JSON_VALUE (2016+) |
<Student>Иванов<Stipend>150</Student> — что не так?id у University?XML, а не в NVARCHAR(MAX)?Ответы: (1) не закрыт Stipend; (2) (/University/@id)[1]; (3) проверка well-formed, индексы, методы XPath.
<Student id="101">?XML, если есть NVARCHAR?.value() на ЛР №17?Итог. XML описывает дерево данных; XSD задаёт контракт; SQL Server хранит документы в типе XML и извлекает поля через XPath. Это мост от реляционной UniversityDB к полуструктурированному обмену.
О чём эта лекция. База данных живёт на сервере годами — нужен человек (или команда), который следит за доступностью, резервными копиями, правами и производительностью. Это задачи администратора БД.
Главная мысль одной фразой: экземпляр SQL Server содержит системные и пользовательские базы; мониторинг через SSMS и динамические представления показывает, чего ждут запросы и где узкое место.
После прочтения вы сможете:
master, tempdb;DBCC CHECKDB;wait_type в sys.dm_exec_requests;| № | Тема |
|---|---|
| 1 | Роль DBA; что уже делали на ЛР №1 |
| 2 | Экземпляр SQL Server, системные базы, файлы .mdf/.ldf |
| 3 | Модели восстановления SIMPLE / FULL |
| 4 | Мониторинг: Activity Monitor, sys.dm_exec_requests |
| 5 | Обслуживание, самопроверка; резервное копирование |
Запишите в тетрадь — DBA
DBA — бэкапы, права, мониторинг, место на диске.
На ЛР №1 вы подключались к SQL Server и создавали UniversityDB. База будет жить на сервере месяцами: её нужно копировать, защищать, наблюдать и чинить после сбоев.
Администратор баз данных (DBA) отвечает за:
STUDENT, кто — только VIEW);Разработчик пишет запросы; DBA следит, чтобы сервер выдержал нагрузку и данные не пропали. На маленькой учебной базе роли часто совмещают — но различать их полезно.
Экземпляр (instance) — одна установленная служба SQL Server на машине. В Object Explorer вы видите экземпляр → базы данных.
| База | Назначение |
|---|---|
master | Метаданные сервера: логины, список баз |
msdb | Задания SQL Server Agent, история бэкапов |
tempdb | Временные объекты; пересоздаётся при перезапуске |
model | Шаблон для новых баз |
UniversityDB | Пользовательская учебная база |

Object Explorer → System Databases: master, model, msdb, tempdb. Пользовательские базы (в т.ч. UniversityDB) — в том же узле Databases.
У UniversityDB два основных файла: .mdf (данные) и .ldf (журнал транзакций). Журнал связан с транзакциями и блокировками; без него нельзя надёжно восстанавливать базу в модели FULL.
SIMPLE — журнал усечён автоматически; point-in-time restore ограничен. FULL — нужен для цепочки BACKUP LOG и восстановления «на минуту» (раздел о резервном копировании).
Activity Monitor (ПКМ по экземпляру): Processes, Resource Waits — блокировки и «висящие» запросы.
Activity Monitor (правый клик на экземпляре) показывает:
Для текстового отчёта — динамическое представление sys.dm_exec_requests:
wait_type — чего ждёт запрос: PAGEIOLATCH (диск), LCK_M_* (блокировка), NETWORKIO (сеть). Если отчёт по JOIN трёх таблиц «висит», здесь видна причина.
Activity Monitor открывают правым кликом по имени экземпляра в Object Explorer (тот же узел, что на рисунке в §2).
| Действие | Зачем |
|---|---|
| Перестроение / реорганизация индексов | Точный план запроса, меньше Scan |
| Обновление статистики | Оптимизатор правильно оценивает число строк |
DBCC CHECKDB | Проверка целостности страниц файлов |
| Резервное копирование по расписанию | SQL Server Agent (обзорно) |
На учебном сервере не работайте под sa без необходимости и не запускайте CHECKDB в часы сдачи лабораторных без согласования.
blocking_session_id вместе с wait_type?Ответы: (1) msdb; (2) журнал фиксирует изменения до COMMIT; (3) блокировка — частая причина ожидания при параллельных UPDATE.
wait_type = PAGEIOLATCH?DBCC CHECKDB по расписанию?Итог. SQL Server — не только «место для таблиц», а управляемый сервис с системными базами, журналом и инструментами мониторинга. Администрирование делает учебную UniversityDB пригодной для реальной эксплуатации.
О чём эта лекция. Часть логики можно перенести на сервер: представления, хранимые процедуры и триггеры выполняются рядом с данными — меньше трафика и единые правила для всех клиентов.
Главная мысль одной фразой: VIEW прячет сложный JOIN; процедура параметризует запрос; триггер реагирует на INSERT/UPDATE/DELETE — AFTER после изменения, INSTEAD OF вместо него.
После прочтения вы сможете:
CREATE VIEW для пользователя отчётов;usp_StudentByKurs и вызвать её в SSMS;| № | Тема |
|---|---|
| 1 | VIEW — зачем прятать JOIN |
| 2 | Хранимые процедуры и EXEC |
| 3 | Триггеры AFTER и INSTEAD OF |
| 4 | План запроса: Seek vs Scan |
| 5 | Индексы, самопроверка, связь с ЛР №20–22 |
Запишите в тетрадь — VIEW
VIEW — именованный SELECT; скрывает JOIN от пользователя отчёта.
На ЛР №11 вы писали длинный JOIN «студент + вуз + оценки». Пользователю отчётов неудобно каждый раз повторять связи — им нужна «виртуальная таблица» с понятными столбцами.
VIEW — сохранённый SELECT с именем. Данные не копируются: при SELECT * FROM v_StudentUniv сервер выполняет запрос из определения VIEW.
Не путать с таблицей: в Object Explorer VIEW лежит в папке Views; INSERT в простой VIEW с JOIN обычно невозможен — помогает триггер INSTEAD OF (ЛР №22).
Процедура — программа T-SQL на сервере с параметрами. Один вызов EXEC вместо копирования текста запроса в каждое приложение.
Плюсы: меньше сетевого трафика; единая логика; можно выдать GRANT EXECUTE без права SELECT на таблицу (ЛР №23).
Триггер — код, который SQL Server запускает при INSERT, UPDATE или DELETE.
| Тип | Когда | Пример |
|---|---|---|
| AFTER | После изменения строк | Аудит в AuditLog |
| INSTEAD OF | Вместо операции | INSERT через VIEW с JOIN |
Внутри триггера доступны псевдотаблицы inserted (новые значения) и deleted (старые). На ЛР №22 вы запишете изменения в EXAM_MARKS и запретите понижение оценки.
В SSMS: кнопка Include Actual Execution Plan (Ctrl+M). Смотрите операторы:
Индекс на STUDENT(UNIVERSITY_ID) ускорит JOIN с UNIVERSITY. Выражение в WHERE «ломает» индекс: WHERE YEAR(BIRTHDAY) = 2005 — лучше диапазон BIRTHDAY BETWEEN '2005-01-01' AND '2005-12-31'.
В SSMS включите Include Actual Execution Plan (Ctrl+M), выполните JOIN из §1 и откройте вкладку Execution plan под результатами — ищите операторы Index Seek по ключу FK или Index Scan при его отсутствии. Готового скриншота плана в материалах нет: на ЛР №20–21 сделайте свой.
STUDENT?SET NOCOUNT ON в процедуре?MARK?Ответы: (1) да, VIEW показывает актуальные данные; (2) не слать клиенту «(N rows affected)» на каждый внутренний SELECT; (3) триггер может писать в другую таблицу и откатывать транзакцию.
usp_StudentByKurs, если можно написать тот же SELECT?Итог. VIEW, процедуры и триггеры переносят логику на сервер рядом с данными — меньше дублирования в приложениях и единые правила для всех клиентов SSMS.
О чём эта лекция. Диск может выйти из строя, студент может ошибочно выполнить DELETE, ransomware шифрует файлы — без резервной копии данные не вернуть. Разберём виды backup в SQL Server и правило 3-2-1.
Главная мысль одной фразой: полная, разностная копия и журнал транзакций образуют цепочку восстановления; модель FULL позволяет восстановиться на минуту, SIMPLE — только до последней полной копии.
После прочтения вы сможете:
BACKUP DATABASE и BACKUP LOG;| № | Тема |
|---|---|
| 1 | Зачем копировать: сценарии потери данных |
| 2 | RPO и RTO на примере деканата |
| 3 | FULL, DIFF, LOG backup |
| 4 | Модели SIMPLE и FULL |
| 5 | Правило 3-2-1, связь с ЛР №24 |
Запишите в тетрадь — RPO / RTO
RPO — допустимая потеря данных по времени; RTO — время восстановления.
На ЛР №6 вы делали UPDATE и DELETE. Одна ошибка в WHERE без транзакции может стереть половину EXAM_MARKS. Диск выходит из строя, ransomware шифрует .mdf — без копии восстановить нельзя.
Резервная копия — не «галочка для отчёта», а часть RPO/RTO: сколько данных можно потерять и как быстро поднять сервис.
| Метрика | Вопрос | Пример |
|---|---|---|
| RPO | Сколько истории можно потерять? | «Не больше 1 часа ведомости» → бэкап лога каждый час |
| RTO | Как быстро снова работать? | «Деканат открыт через 4 часа после сбоя» |
| Тип | Содержимое | Файл (пример) |
|---|---|---|
| FULL | Вся база целиком | univ_full.bak |
| DIFFERENTIAL | Изменения с последней FULL | univ_diff.bak |
| LOG | Записи журнала транзакций | univ_log.trn |
Цепочка FULL → DIFF → LOG позволяет восстановиться на конкретную минуту — только в модели восстановления FULL.
SIMPLE — журнал усекается автоматически; point-in-time restore ограничен. FULL — нужен для регулярного BACKUP LOG и STOPAT при восстановлении.
Три копии данных, на двух носителях, одна копия вне площадки (облако, другой офис).
Итог. Стратегия бэкапов выбирается от RPO/RTO; без проверенного восстановления копия не даёт уверенности.
О чём эта лекция. Резервная копия бесполезна, если вы ни разу не пробовали восстановление. Разберём порядок RESTORE, восстановление на момент времени и параллельно — права доступа: login, user, role, GRANT.
Главная мысль одной фразой:NORECOVERY накатывает цепочку файлов, RECOVERY открывает базу; при логической ошибке поднимают копию рядом и переносят нужные строки, а не откатывают всю боевую базу.
После прочтения вы сможете:
STOPAT;UniversityDB.| № | Тема |
|---|---|
| 1 | Цепочка RESTORE: NORECOVERY / RECOVERY |
| 2 | STOPAT — откат ошибочного DELETE |
| 3 | Логическая ошибка: копия «рядом» |
| 4 | Login, user, role, GRANT/REVOKE |
| 5 | Персональные данные в UniversityDB |
Запишите в тетрадь — NORECOVERY / RECOVERY
NORECOVERY — цепочка RESTORE; RECOVERY — открыть базу. STOPAT — откат DELETE.
Копия бесполезна, если вы ни разу не делали RESTORE. Общий порядок:
NORECOVERY.NORECOVERY.RECOVERY.NORECOVERY оставляет базу в режиме «ещё накатываем файлы». RECOVERY открывает базу для работы.
Если в 10:15 выполнили ошибочный DELETE FROM EXAM_MARKS WHERE …, а цепочка лога сохранена — можно откатиться на секунду до ошибки.
Если после ошибки уже наработали новые данные, не откатывайте всю боевую базу на вчера. Поднимите копию рядом (UniversityDB_restore), вытащите нужные строки, вставьте в основную базу — так делают на ЛР №24.
Login — учётная запись на уровне сервера. User — сопоставление login внутри базы. Role — набор прав для группы пользователей.
Принцип минимальных привилегий: только то, что нужно для работы. В UniversityDB есть ФИО и даты рождения — персональные данные; в проекте нужна политика доступа и аудит (триггер на ЛР №22).
NORECOVERY?STOPAT помогает после ошибочного DELETE?EXAM_MARKS для роли «читатель»?Итог. Восстановление и права — две стороны надёжности: данные можно вернуть, а доступ — ограничить.
О чём эта лекция. Возвращаемся к распределённым системам на уровне протоколов: как согласовать COMMIT на двух серверах с помощью двухфазной фиксации (2PC) и зачем фрагментировать таблицы по регионам.
Главная мысль одной фразой: 2PC — «сначала спроси всех, готовы ли зафиксировать, потом COMMIT или ROLLBACK всем»; это цена масштаба распределённой БД.
После прочтения вы сможете:
| № | Тема |
|---|---|
| 1 | Распределённая БД — повторение идеи |
| 2 | Архитектуры доступа к данным |
| 3 | Репликация |
| 4 | Двухфазная фиксация 2PC |
| 5 | Фрагментация, компромиссы |
Запишите в тетрадь — 2PC
2PC: Prepare → Commit или Rollback всем узлам.
Студенты ВГУ в Воронеже, филиал в другом городе — данные могут лежать на разных серверах, но приложение видит одну базу. Важна прозрачность: разработчик пишет обычный SQL, система направляет запрос на нужный узел.
| Вид | Когда |
|---|---|
| Снимок | Редко меняющиеся справочники вузов |
| Транзакционная | Отчёты с копии, минимальная задержка |
| Слиянием | Филиалы с автономной работой офлайн |
Реплика — способ масштабировать чтение и повышать доступность.
Рисунок 1. Две фазы 2PC.
Одна бизнес-операция затрагивает два узла (списание и зачисление на разных серверах). Протокол:
Минус: при сбое координатора участники могут долго ждать. Для курса достаточно понимать идею согласованности vs доступности.
Горизонтальная — строки по регионам (STUDENT Москвы на узле A). Вертикальная — редкие столбцы на отдельном узле. Цель — баланс нагрузки и близость к пользователю.
Итог. Распределённые системы — продолжение многопользовательского режима и репликации; 2PC — цена согласованности на нескольких узлах.
О чём эта лекция. Завершение курса: чем операционная база (OLTP) отличается от аналитической (OLAP), что такое хранилище данных и Data Mining — и как подготовиться к экзамену по материалам семестра.
Главная мысль одной фразой:UniversityDB учит оперативному учёту; хранилище и OLAP отвечают на вопросы «как менялось за годы», а экзамен проверяет связное понимание модели, SQL и надёжности.
После прочтения вы сможете:
| № | Тема |
|---|---|
| 1 | OLTP vs OLAP на примере UniversityDB |
| 2 | Хранилище данных, схема «звезда» |
| 3 | Data Mining — три задачи без формул |
| 4 | Итоги семестра |
| 5 | Формат экзамена и план повторения |
OLTP (UniversityDB) | OLAP / DWH | |
|---|---|---|
| Цель | Выставить оценку, изменить стипендию | «Как менялся средний балл по городам за 5 лет» |
| Схема | 3НФ, много JOIN | «Звезда»: факты + измерения |
| Нагрузка | Короткие INSERT/UPDATE | Тяжёлые отчёты, сканы |
| История | Текущее состояние | Снимки за годы, ETL |
Факт — измеримое событие (оценка, сумма). Измерение — контекст (время, предмет, вуз). Операции OLAP-куба: срез, детализация, свёртка.
DWH собирает данные из учётных систем (ETL). Схема «звезда»: центральная таблица фактов (FactExam), вокруг — справочники (DimStudent, DimSubject, DimDate). Витрины — готовые срезы для конкретного отдела.
Цепочка семестра: модель и нормализация → SQL и JOIN → транзакции и блокировки → XML, иерархии, MongoDB → VIEW, процедуры, триггеры → бэкап, права, аналитика.
UniversityDB — сквозной пример от CREATE TABLE до GRANT и RESTORE.
24 контрольных вопроса и билеты — на странице «Экзамен»; учебный план — на вкладке «Учебный план».
Типичные темы SQL: подзапросы, JOIN, GROUP BY, EXISTS, NULL, VIEW.
UniversityDB отличается от OLAP-отчёта?Итог. Курс связал проектирование, SQL, надёжность и аналитику. Перед экзаменом пройдите учебный план, страницу экзамена (контрольные вопросы + билеты) и повторите ЛР №1–24 на UniversityDB.
Цель: впервые открыть SQL Server Management Studio (SSMS), подключиться к серверу в классе, разобраться с системными и пользовательскими базами, создать UniversityDB.

SQL Server Management Studio (SSMS) в меню Пуск — Microsoft SQL Server Tools.
(local), .\SQLEXPRESS, ИМЯ-ПК\SQLEXPRESS).
Рисунок 1. Окно Connect to Server в SSMS.
master, model, msdb, tempdb.master и tempdb.UniversityDB или базы других групп.
Рисунок 2. Узел System Databases в Object Explorer (скриншот SSMS).
Если база UniversityDB уже есть от прошлой попытки — согласуйте с преподавателем: использовать её или создать UniversityDB_Фамилия.
UniversityDB, OK.UniversityDB появилась.UniversityDB — Properties — вкладка Files: запишите путь к файлам .mdf и .ldf.
Создание базы: New Database… или CREATE DATABASE.

Рисунок 3. Свойства базы — путь к файлам .mdf и .ldf (вкладка Files).
UniversityDB.lab01_FIO.sql (ФИО латиницей).На всех лабораторных имя файла: labNN_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab01_IvanovII.sql.

Окно New Query, выбор базы, команды SELECT.

Рисунок 4. Результат выполнения запроса в панели Results.
lab01_FIO.sql (ФИО латиницей), но после CREATE DATABASE?скриншоты + скрипт lab01_FIO.sql (ФИО латиницей).
Ответы на контрольные вопросы.
Цель: в уже созданной на ЛР №1 пустой базе UniversityDB создать таблицы учебного эталона, загрузить данные и выполнить первые запросы SELECT.
UniversityDB (часто (local) или localhost\SQLEXPRESS на вашем ПК; в аудитории — имя, которое дал преподаватель).UniversityDB → Tables. Список пользовательских таблиц должен быть пуст (или только системные).UniversityDB, выполните:Если базы нет — вернитесь к ЛР №1 или выполните CREATE DATABASE UniversityDB;.
Готовые команды CREATE TABLE и INSERT — на странице Приложение: БД и скрипты, раздел «Сборка базы по шагам». Там же объяснено, что такое SQL-скрипт и зачем он разбит на блоки.
Команды CREATE TABLE и INSERT возьмите из приложения: скопируйте блоки в окно запроса, выполните их и сохраните полный текст работы в файле lab02_FIO.sql (ФИО латиницей).
| Блок в приложении | Что делает |
|---|---|
| 1. База данных | Если на этом экземпляре SQL Server уже есть пустая UniversityDB — достаточно USE UniversityDB;; блок CREATE DATABASE из приложения не выполняйте |
| 2. Очистка таблиц | Только если таблицы уже есть и нужно начать заново* |
| 3. UNIVERSITY, SUBJECT | Справочники без внешних ключей — создаются первыми |
| 4. STUDENT, LECTURER | Строки ссылаются на вуз через UNIVERSITY_ID |
| 5. EXAM_MARKS, SUBJ_LECT, ORG_UNIT | Оценки и связи; FK ссылаются на таблицы из блоков 3–4 |
| 6. INSERT | Эталонные данные — порядок 6.1 → 6.7, как в приложении |
* Если на прошлой попытке таблицы уже есть — выполните блок 2, затем блоки 3–6 заново.
UniversityDB.UniversityDB → Tables должны появиться семь таблиц.dbo.STUDENT → Design — видны столбцы STUDENT_ID, UNIVERSITY_ID, значок ключа у PK и FK.CREATE TABLE завершился ошибкой «foreign key» — вы, скорее всего, перепутали порядок блоков. Сначала родитель (UNIVERSITY), потом дочерние таблицы.Вставляйте блоки 6.1 → 6.7 по порядку из приложения (сначала вузы и предметы, в конце — подразделения). Можно выполнить весь блок 6 целиком или по частям — главное не нарушать порядок таблиц.
Контрольная проверка:
В ответе должно быть 19 студентов и 8 вузов. Сохраните скриншот результата для отчёта.
SELECT читает данные из таблиц; он ничего не меняет. Выполните запросы ниже по очереди, результаты — в отчёт.
Звёздочка * означает «все столбцы строки»:
В результате — 8 строк, столбцы UNIVERSITY_ID, UNIVERSITY_NAME, RATING, CITY.
Список столбцов через запятую — это проекция (выбор нужных полей):
Условие WHERE отбирает строки. Номер 10 — это ВГУ в эталонных данных:
В списке столбцов сначала NAME (имя), затем SURNAME (фамилия) — как требуется в задании.
Агрегатная функция COUNT(*) считает строки. Для эталона ответ снова 19.

Окно New Query: сверху выбрана база UniversityDB, ниже — текст SQL.

Результат SELECT — на вкладке Results.
CHECK (стипендия ≥ 0, курс 1–6, оценка 2–5). Выполните заведомо неверный INSERT, например студента с KURS = 9, и прочитайте текст ошибки.UNIVERSITY_ID = 999. СУБД должна отклонить строку — нет такого вуза, сработал внешний ключ.dbo.EXAM_MARKS и найдите студента без оценок (STUDENT_ID = 19). Эта строка специально нужна для заданий с IS NULL на следующих лабораторных.UniversityDB после ЛР №1 отличается от той же базы после этой работы?UNIVERSITY создают раньше, чем STUDENT?SELECT * FROM UNIVERSITY и чем он отличается от SELECT UNIVERSITY_NAME, CITY FROM UNIVERSITY?INSERT студента с несуществующим UNIVERSITY_ID?lab02_FIO.sql (ФИО латиницей), если база уже создана на сервере?Образец для следующих ЛР: один lab02_FIO.sql + скрин результата SELECT COUNT(*).
lab02_FIO.sql (ФИО латиницей): команды USE, все CREATE TABLE, все INSERT и все SELECT из этой работы.-- ЛР №2, IvanovII, группа ВО-ИСИТ-31 (подставьте свои фамилию и инициалы латиницей).COUNT(*), один из запросов из §4.Ответы на контрольные вопросы.
Цель: в той же UniversityDB добавить четыре таблицы (группы и учебная библиотека) с ограничениями PRIMARY KEY, UNIQUE, CHECK, FOREIGN KEY; загрузить данные и убедиться, что СУБД отклоняет неверные строки.
Что отрабатываете (не «скопировал — забыл»):
F5 прочитать CREATE TABLE и в комментарии -- подписать назначение каждого столбца;UNIVERSITY и STUDENT;INSERT.Идея нормализации здесь. Один факт — одно место: фамилия старосты хранится в строке группы, а не повторяется у каждого студента; автор — в LIB_AUTHOR, описание издания — в LIB_BOOK, конкретный экземпляр на полке — в LIB_COPY.
UniversityDB уже должны быть семь таблиц эталона: UNIVERSITY, STUDENT, LECTURER, SUBJECT, EXAM_MARKS, SUBJ_LECT, ORG_UNIT.UniversityDB. Весь SQL ниже выполняйте только в ней.DROP DATABASE UniversityDB и не пересоздавайте таблицы эталона — только CREATE TABLE для новых имён ниже. Если работу уже сдавали, перед повтором удалите свои таблицы: DROP TABLE для LIB_COPY, LIB_BOOK, LIB_AUTHOR, ACADEMIC_GROUP (в таком порядке).Новые таблицы добавляются в уже существующую UniversityDB, не создавая отдельную базу.
В current_database должно быть UniversityDB. Число таблиц до работы — обычно 7 (после шага 2 станет 11).
Если свалить всё в одну таблицу «группа + староста + ISBN + инвентарный номер + статус выдачи», смена старосты или автора превратится в массу UPDATE. Разделение: справочник групп (фамилия старосты один раз на группу), затем цепочка автор → книга → экземпляр. Создавайте таблицы в указанном порядке.
CREATE TABLE нижеТе же приёмы, что в эталоне UniversityDB (PK, FK, CHECK на курс и оценку), плюс несколько новых имён.
| В SQL | Зачем в этой работе |
|---|---|
INT NOT NULL | Числовой идентификатор или год; пустая ячейка недопустима |
NVARCHAR(n) + N'текст' | Строки с кириллицей (название книги, фамилия) |
CHAR(13) | ISBN — ровно 13 символов |
PRIMARY KEY | Один номер строки (GROUP_ID, BOOK_ID…) не повторяется |
UNIQUE | Два разных BOOK_ID не могут иметь один ISBN или один инв. номер |
CHECK (PUB_YEAR BETWEEN …) | Год издания не «1300» и не будущий |
CHECK (STATUS IN ('in','out')) | Статус экземпляра: на полке или выдан (in / out) |
FOREIGN KEY … REFERENCES | Книга ссылается на существующего автора; экземпляр — на существующую книгу |
DEFAULT ('in') | Если при вставке статус не указали — «на полке» |
ON DELETE CASCADE | Удалили строку книги — СУБД удалит её экземпляры (обсудите: когда это уместно) |
Скопировать блок можно после того, как в черновике комментариями отметили каждый столбец; в отчёте должны быть ваши комментарии, не только голый код.
| Таблица | Назначение | Ключевые ограничения |
|---|---|---|
ACADEMIC_GROUP | Учебные группы | GROUP_ID — PK; код группы; фамилия старосты |
LIB_AUTHOR | Авторы учебников/худ. лит. | AUTHOR_ID — PK |
LIB_BOOK | Книги (издания) | BOOK_ID — PK; ISBN — UNIQUE; PUB_YEAR — CHECK; FK на автора |
LIB_COPY | Экземпляры в библиотеке вуза | COPY_ID — PK; инв. номер — UNIQUE; STATUS — CHECK; FK на книгу + CASCADE |
Столбцы: номер группы, код (например ВО-ИСИТ-31), фамилия старосты — один раз на группу.
Справочник людей; у каждого автора свой AUTHOR_ID.
Одно издание (ISBN, название, год); AUTHOR_ID — ссылка на строку в LIB_AUTHOR.
PUB_YEAR — год издания; CHECK не допускает «1300» и будущие годы.
Физический экземпляр на полке: свой COPY_ID, инвентарный номер, статус; BOOK_ID — какое издание.
ON DELETE CASCADE: при удалении книги СУБД удалит все её экземпляры. STATUS: in — на полке, out — выдан читателю.
Object Explorer (F5): под UniversityDB → Tables — четыре новые таблицы рядом с STUDENT, EXAM_MARKS и др.
Сначала группы и авторы, затем книги, затем экземпляры — тот же принцип «сначала справочник, потом строки со ссылками».
Перед вставкой проверьте: значения AUTHOR_ID и BOOK_ID в INSERT должны уже существовать в родительской таблице.
Можете добавить свои строки (минимум 3–5 в каждой таблице). Проверка:
Выполните команды ниже по одной. Каждая должна завершиться ошибкой — это ожидаемый результат. Сохраните текст ошибки или скриншот для отчёта.
Нарушение UNIQUE на ISBN.
Нарушение CHECK на PUB_YEAR.
Нарушение CHECK на STATUS — допустимы только in и out.
Нарушение внешнего ключа — автора с AUTHOR_ID = 999 нет.
В конце lab03_FIO.sql добавьте комментарии (или ответьте устно на паре):
UniversityDB, а не создают отдельную базу на каждую тему?LIB_BOOK создают после LIB_AUTHOR, а LIB_COPY — после LIB_BOOK?PRIMARY KEY отличается от UNIQUE на примере ISBN и BOOK_ID?ON DELETE CASCADE при удалении строки из LIB_BOOK?LIB_AUTHOR?lab03_FIO.sql + один скрин Results (SELECT COUNT после загрузки) + один скрин Messages (ошибка из §4.1 или §4.3). Неверные INSERT из §4 — в файле закомментированы с пометкой «ожидаемая ошибка».
Ответы на контрольные вопросы.
Цель: изменить существующую схему UniversityDB командами ALTER TABLE, добавить индексы, поработать с пакетами GO и убедиться, что ограничения FK и UNIQUE работают.
На общем сервере: схема живёт на общем сервере; ваш ALTER TABLE видят все сеансы. Внешние ключи с ЛР №2 защищают ссылки; сегодня добавляете столбец и индексы без пересоздания таблиц.
UniversityDB → Tables — как минимум семь таблиц после ЛР №2 (после ЛР №3 — ещё ACADEMIC_GROUP и LIB_*).UniversityDB, выполните контроль:Ожидается: 19 студентов и непустая таблица оценок. Если база пуста — повторите ЛР №2 (блоки приложения 3–6).
DROP DATABASE и не трогайте чужие базы на общем сервере.
Object Explorer: под UniversityDB → Tables — STUDENT, UNIVERSITY, …
На ЛР №2 таблицы создавали через CREATE TABLE. В живой системе схему чаще дополняют — так деканат добавляет поле «email» без пересоздания таблицы и без потери 19 строк.
dbo.STUDENT → Design — в списке столбцов появился EMAIL, тип varchar(100), Allow Nulls = да.student<STUDENT_ID>@edu.local:Конкретный запрос SELECT и ожидаемый фрагмент результата:
| STUDENT_ID | SURNAME | |
|---|---|---|
| 1 | … | student1@edu.local |
| 2 | … | student2@edu.local |
| … | … | … |
Фамилии возьмутся из вашего эталона; важны столбец EMAIL и шаблон адреса. Сделайте скриншот вкладки Results.

Окно New Query: сверху выбрана UniversityDB, ниже — ALTER и UPDATE.

Результат SELECT TOP 5 … EMAIL — приложите к отчёту.
UNIQUE запрещает два одинаковых значения в столбце (кроме NULL — в SQL Server несколько NULL в UNIQUE допустимы, но у вас все EMAIL заполнены).
Теперь намеренно нарушите правило — скопируйте адрес студента 1 студенту 2:
Ожидаемо: выполнение прервётся, на вкладке Messages текст вроде:
Сохраните скриншот вкладки Messages — это доказательство работы ограничения. Верните уникальные значения:
Если бы вы добавляли столбец UNIVERSITY_ID вместо EMAIL, FK не дал бы записать несуществующий вуз. Проверка (ожидается ошибка):
Индекс — отдельная структура для быстрого поиска по столбцу. На ЛР №5–6 вы часто будете писать WHERE CITY = … и WHERE UNIVERSITY_ID = … AND KURS = … — под такие фильтры индексы уместны.
Clustered индекс один на таблицу (обычно PK); nonclustered — дополнительные «указатели» к строкам.
В результате должны быть как минимум:
| index_name | type_desc | is_unique | Комментарий |
|---|---|---|---|
| PK__STUDENT… | CLUSTERED | 1 | первичный ключ |
| UQ_STUDENT_EMAIL | NONCLUSTERED | 1 | ваше UNIQUE |
| IX_STUDENT_CITY | NONCLUSTERED | 0 | создали в §3 |
| IX_STUDENT_UNIV_KURS | NONCLUSTERED | 0 | составной индекс |
Точное имя PK может отличаться — смотрите столбец index_name.
GO — не команда T-SQL, а разделитель пакетов в SSMS. Переменная, объявленная в одном пакете, не видна в следующем.
Ожидаемый результат второго пакета: students = 19.
Эксперимент: уберите оба GO и выполните скрипт целиком. Вторая строка DECLARE @cnt в том же пакете даст ошибку «имя переменной уже объявлено» или конфликт с первым пакетом — зафиксируйте текст ошибки в отчёте.
Cannot find object STUDENT — выполните USE UniversityDB;. Если столбец EMAIL уже добавлен — пропустите §1 или согласуйтесь с преподавателем. Повторный CREATE INDEX даст ошибку — индекс уже есть.EXEC sp_helpindex 'dbo.STUDENT'; — сравните вывод с sys.indexes.IF NOT EXISTS (на курсе достаточно комментария).ALTER TABLE ADD безопаснее, чем «удалить STUDENT и создать заново».ALTER TABLE ADD отличается от повторного CREATE TABLE STUDENT?GO?sys.indexes отличить clustered и nonclustered индекс?скрипт lab04_FIO.sql (ФИО латиницей) + скриншоты из §1–5.
lab04_FIO.sql (ФИО латиницей): USE, все ALTER, UPDATE, CREATE INDEX, SELECT из sys.indexes, скрипт с GO.-- ЛР №4, IvanovII, группа ВО-ИСИТ-31 (подставьте свои фамилию и инициалы латиницей).EMAIL и индексы для ЛР №5+ или удалить в конце скрипта:Имя файла отчёта: lab04_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab04_IvanovII.sql.
Ответы на контрольные вопросы.
Цель: выполнить выборку с проекцией (список столбцов) и селекцией (WHERE): сравнение, AND/OR/NOT, IN, BETWEEN, LIKE, IS NULL на UniversityDB.
Напоминание: вы уже делали простые SELECT на ЛР №2; здесь — систематическая работа с фильтрами. Справочник таблиц и эталонные данные — в приложении.
UniversityDB.EMAIL — он не мешает; все запросы ниже работают и без него.Ожидается: 19 студентов, 24 строки в EXAM_MARKS, 8 предметов в SUBJECT (см. приложение).

Перед работой убедитесь, что в списке баз выбрана UniversityDB.
Проекция — какие столбцы показать. Селекция — какие строки отобрать (WHERE, §2–4).
Ожидается 8 строк, столбцы SUBJ_ID, SUBJ_NAME, HOUR, SEMESTER.
SUBJ_ID = 10)В эталоне — несколько строк (оценки разных студентов). В комментарии к скрипту укажите -- rows: N.
Ожидается 19 строк. Звёздочка * здесь не нужна — вы явно перечисляете столбцы отчёта.
Выполняйте запросы по одному. После каждого — запишите число строк (rows в углу Results или SELECT COUNT(*) … с тем же WHERE).
Ожидается 1 строка — «История» (SUBJ_ID = 56).
Ожидается 4 строки (56, 72, 56, 56 часов в эталоне).
Ожидается 6 вузов (рейтинг 410, 450, 470, 580, 650, 700).

Пример результата с фильтром — приложите один такой скриншот к отчёту.
Буква N перед строкой — Unicode для кириллицы.
Без скобок AND связывал бы только KURS = 2 со стипендией — логика изменилась бы.
% — любое продолжение. Укажите в комментарии, сколько строк вернулось.
Ожидается 1 строка — STUDENT_ID = 19 (специально для этой проверки).
Сохраните скриншот: сравнение «0 строк» и «1 строка» — хороший фрагмент отчёта.
| Ошибка | Что проверить |
|---|---|
| 0 строк там, где ждали данные | Выбрана ли UniversityDB; нет ли опечатки в N'Воронеж' |
CITY = NULL | Только IS NULL / IS NOT NULL |
| Фильтр по SEMESTER в STUDENT | Семестр — столбец таблицы SUBJECT, не студента |
Забыли dbo. | На учебном сервере лучше явно: dbo.STUDENT |
SUBJ_NAME), у которых в названии есть буква «а» или «А» (подсказка: LIKE с %).Таблицы: dbo.STUDENT, dbo.SUBJECT. Проверка на паре: преподаватель просит изменить условие (другой курс или порог стипендии) — вы правите WHERE без подсказки из текста.
SELECT * FROM dbo.STUDENT WHERE NOT (KURS < 3); — сравните с KURS >= 3.UNIVERSITY_ID = 10) с стипендией выше средней по этому вузу (подсказка: подзапрос — ЛР №9).SELECT не меняет данные и не требует ROLLBACK (в отличие от ЛР №6).SELECT?SEMESTER относится к таблице SUBJECT, а не STUDENT?LIKE N'С%' и зачем буква N?IS NULL отличается от = NULL?lab05_FIO.sql (ФИО латиницей), если результат виден на экране?формат сдачи в конце работы.
lab05_FIO.sql: все запросы с пары (§1–4) и два запроса из §6. Один скрин Results — любой из самостоятельных запросов; к блокам — -- rows: N.
Ответы на контрольные вопросы.
Цель: изменять данные (DML), сортировать выборку, использовать TOP и DISTINCT; безопасно экспериментировать в транзакции с ROLLBACK .
На общем сервере: незафиксированные UPDATE/DELETE видят другие сеансы — поэтому учебные изменения только с откатом.
UPDATE, INSERT и DELETE ниже выполняйте внутри BEGIN TRAN … ROLLBACK. Не нажимайте COMMIT, пока не согласовали с преподавателем.Ожидается 19 студентов. Запишите число оценок — после всех ROLLBACK оно должно совпасть.
ORDER BY сортирует результат; TOP n ограничивает число строк (аналог LIMIT в других СУБД). DISTINCT убирает дубликаты в выборке.
Вверху списка — студенты с наибольшей стипендией. Скриншот для отчёта.
Ровно 5 строк (если в таблице ≥ 5 студентов).
В первом запросе — уникальные оценки (2–5); во втором — уникальные пары «курс + город».

Результат TOP 5 … ORDER BY STIPEND DESC — приложите к отчёту.
Сначала «пробные» строки — затем откат. Порядок: родитель UNIVERSITY, потом дочерний STUDENT (FK).
INSERT … SELECT вставляет строку, вычисленную запросом (здесь — рейтинг выше текущего максимума).
Перед изменением — SELECT с тем же WHERE; после UPDATE — повторный SELECT; в конце — ROLLBACK.
После ROLLBACK у студента 15 снова должен быть исходный UNIVERSITY_ID из эталона.
После отката последний COUNT совпадает с первым — двойки (если были) на месте.
Нельзя удалить вуз, пока на него ссылаются студенты. Сначала проверьте ошибку:
Правильный порядок внутри транзакции: сначала DELETE студентов, потом вуза.
| Ошибка | Что делать |
|---|---|
| Случайный COMMIT | На учебном сервере — только ROLLBACK; пересоздайте эталон с преподавателем |
| UPDATE без WHERE | Сначала SELECT с тем же условием — убедитесь, что трогаете нужные строки |
| DELETE родителя раньше ребёнка | Сначала дочерние строки или CASCADE (если задан) |
| Забыли ROLLBACK | SELECT @@TRANCOUNT; — если > 0, выполните ROLLBACK |
SELECT TOP 5 PERCENT STIPEND, … ORDER BY STIPEND DESC; — чем отличается от TOP 5?UPDATE с заведомо неверным CHECK (KURS = 9) внутри TRY/CATCH (ЛР №16).ORDER BY пишут после WHERE?ROLLBACK после демонстрационного UPDATE на общем сервере?INSERT … SELECT отличается от INSERT … VALUES?DELETE вуза без удаления студентов вызывает ошибку FK?скрипт lab06_FIO.sql (ФИО латиницей) + скриншоты результатов.
lab06_FIO.sql (ФИО латиницей).-- ЛР №6, IvanovII, группа ВО-ИСИТ-31.SELECT COUNT(*) FROM dbo.STUDENT; = 19.Имя файла отчёта: lab06_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab06_IvanovII.sql.
Ответы на контрольные вопросы.
Цель: использовать COUNT, SUM, AVG, MIN, MAX; понять, как NULL влияет на агрегаты; сверить ответы с эталоном из приложения.
Напоминание: на ЛР №2 вы делали простые SELECT; здесь одна строка результата суммирует много строк таблицы. На ЛР №8 добавится GROUP BY — группы вместо «всей таблицы сразу».
Напоминание: все агрегаты, кроме COUNT(*), игнорируют строки, где аргумент равен NULL.
Должны быть данные эталона (сверьте с соседом или с преподавателем; эталон — в teacher/lab_answers.md). Если числа другие — восстановите эталон (ЛР №2, блок 6 приложения).
COUNT(*) считает строки. COUNT(столбец) не учитывает NULL в этом столбце. COUNT(DISTINCT …) — число различных значений (NULL не входит).
Запишите три числа в -- rows: и объясните, почему COUNT(CITY) может быть меньше COUNT(*). У студента STUDENT_ID = 19 поле CITY специально NULL — поэтому COUNT(CITY) на 1 меньше, чем COUNT(*).
В комментарии запишите три числа из результата.
Ожидается: min_st = 0, max_st = 250, avg_st ≈ 122.89 (среднее по всем 19, включая нулевые стипендии). Во втором запросе среднее только по студентам с STIPEND > 0 — ≈ 155.67 (15 строк).
Обратите внимание: нули в данных — не NULL; они участвуют в AVG первого запроса и занижают среднее.
Выполняйте запросы по одному; после каждого сверяйте результат с эталоном.
Ожидается: total_hours = 382 (сумма часов восьми предметов); min_rating = 320 (БГУ), max_rating = 700 (МГУ).
Ожидается: avg_mark ≈ 4.08; 9 пятёрок; 1 двойка; первая дата 2026-01-15, последняя 2026-06-12.
CAST(MARK AS FLOAT) нужен, чтобы среднее было дробным, а не целым от деления типа INT.

Пример вкладки Results для блока §3 — одна строка с несколькими агрегатами. Сделайте скриншот для отчёта.
В эталоне у всех 24 строк поле MARK заполнено — оба счётчика дают 24, разница 0. Это нормально: NULL в оценках зарезервирован для других заданий; здесь вы фиксируете, что COUNT(MARK) и COUNT(*) совпали.
Для строк с NULL смотрите §1: COUNT(CITY) vs COUNT(*) у STUDENT.
KURS) — только COUNT(*) и GROUP BY пока не используйте; сделайте отдельный SELECT COUNT(*) … WHERE KURS = 1, затем для 2, 3 (три запроса).AVG) по таблице EXAM_MARKS с CAST(MARK AS FLOAT).SELECT COUNT(*), COUNT(STIPEND) FROM dbo.STUDENT; — совпадут ли счётчики? Почему?SELECT AVG(CAST(STIPEND AS FLOAT)) FROM dbo.STUDENT WHERE KURS = 1; — посчитайте вручную для первого курса (подготовка к GROUP BY на ЛР №8).AVG(STIPEND) по всей таблице и среднее «только по получающим стипендию»?COUNT(CITY) меньше COUNT(*) у STUDENT?AVG(STIPEND) по всей таблице отличается от AVG при STIPEND > 0?CAST(MARK AS FLOAT) перед AVG?COUNT(MARK), если в столбце есть NULL?MIN/MAX по EXAM_DATE вы получили и что это означает для учебного семестра?формат сдачи в конце работы.
По общим правилам: lab07_FIO.sql + один скрин агрегата из §3 или из самостоятельного §5.
Ответы на контрольные вопросы.
Цель: группировать строки (GROUP BY), отбирать группы через HAVING, строить итоги GROUP BY ROLLUP в SQL Server.
Связь с ЛР №7: там агрегаты считали по всей таблице; здесь — отдельно по каждому курсу, городу, предмету. Справочник эталона — в приложении.
Правило SQL: каждый столбец в SELECT должен быть либо в GROUP BY, либо внутри агрегатной функции (COUNT, AVG, …).
Ожидается 19 студентов. Если база пуста — повторите ЛР №2.
GROUP BY делит строки на группы с одинаковым значением столбца; агрегат считается внутри каждой группы.
Ожидается 5 строк (курсы 1–5). Пример значений: курс 1 — 6 студентов, средняя стипендия 135.00; курс 2 — 4 студента, 167.50; курс 3 — 4, 96.25; курс 4 — 3, 120.00; курс 5 — 2, 55.00.
Групп с заполненным городом — 8; отдельная группа с CITY IS NULL (студент 19) — 1 строка. Чаще всего встречаются Воронеж и Москва (по 4 студента).
Ожидается 8 групп (вузы 10, 11, 12, 14, 15, 18, 22, 32). Например: UNIVERSITY_ID = 10 — 5 студентов, средняя стипендия ≈ 95.00; 22 (МГУ) — 4 студента, ≈ 102.50.

Результат GROUP BY KURS — несколько строк вместо одной сводки с ЛР №7.
Ожидается 7 предметов с оценками. Примеры: SUBJ_ID = 10 — 8 экзаменов, средний ≈ 4.00; 43 — 2 экзамена, средний 5.00; 22 — 4 экзамена, средний 3.50.
WHERE отбирает строки до группировки; HAVING — группы после агрегации (можно использовать условие на COUNT(*), AVG, …).
Ожидается 3 строки: курсы 1 (6), 2 (4), 3 (4). Курсы 4 и 5 отсеялись — в группе ≤ 3 студента.
Ожидается 6 предметов: 10, 18, 31, 43, 56, 94. Предмет 22 (средний 3.50) в список не попадает.
Сначала отбрасываются нулевые стипендии, затем считается среднее по оставшимся в группе. Пример: курс 1 — среднее ≈ 162.00 (5 студентов с ненулевой стипендией), курс 4 — 180.00 (студент 6 с нулём не участвует).
Если написать HAVING AVG(STIPEND) > 0 вместо WHERE STIPEND > 0, нули всё равно войдут в расчёт среднего внутри группы — результат будет другим. Это частая ошибка на защите.
ROLLUP добавляет строку с KURS IS NULL — итог по всей таблице: cnt = 19, avg_st ≈ 122.89 (как на ЛР №7 без группировки). Строки с числом в KURS — группы по курсам из §1.1.
ROLLUP в §5 — по желанию (дополнительно); для зачёта достаточно §1–4 без итоговой строки NULL.
GROUP BY KURS, CITY — сколько групп получится? Сравните с группировкой только по KURS.SELECT KURS, SURNAME, COUNT(*) FROM STUDENT GROUP BY KURS вызывает ошибку?WITH ROLLUP к запросу §3.2 — что изменится в результате?скрипт lab08_FIO.sql (ФИО латиницей) + скриншоты результатов.
lab08_FIO.sql (ФИО латиницей).-- ЛР №8, IvanovII, группа ВО-ИСИТ-31.GROUP BY KURS; HAVING COUNT(*) > 3; ROLLUP с итоговой строкой NULL.Имя файла отчёта: lab08_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab08_IvanovII.sql.
Ответы на контрольные вопросы.
Если JOIN (ЛР №11) ещё не проходили — по возможности сначала сделайте №11, затем вернитесь к подзапросам; см. логику навыков (WHERE → агрегаты → GROUP BY → JOIN → подзапросы) на главной.
Цель: писать скалярные подзапросы, использовать IN и NOT IN; понять, почему NOT IN опасен при NULL в подзапросе.
Связь с ЛР №8: там вы считали агрегаты с GROUP BY; здесь тот же MAX/AVG спрятан внутри WHERE — подзапрос возвращает одно значение для сравнения с каждой строкой внешнего запроса.
Ожидается 19 студентов.
Скалярный подзапрос возвращает одно значение (одну строку, один столбец). Его ставят в WHERE после =, >, < и т.д. Если вернётся больше одной строки — ошибка.
Ожидается 1 строка: Морозова, стипендия 250 (STUDENT_ID = 7).
Средняя по ненулевым ≈ 155.67. Ожидается 7 строк (Сидорова, Козлова, Морозова, Соколова, Зайцева, Лебедева, Крылова).
Средний рейтинг ≈ 496.25. Ожидается 3 вуза: НГУ (580), СПбГУ (650), МГУ (700).

Результат §1.1 — одна строка с максимальной стипендией.
IN (подзапрос) проверяет, входит ли значение во множество строк подзапроса. Эквивалентно нескольким OR, но короче и читабельнее.
В эталоне в Москве только МГУ (UNIVERSITY_ID = 22). Ожидается 4 студента (Сидорова, Сидоров, Кузнецов, Лебедева).
Предмет SUBJ_ID = 10 (Информатика). Ожидается 8 строк в EXAM_MARKS по этому предмету.
Тот же результат можно получить через JOIN — на ЛР №11 сравните оба стиля.
NOT IN исключает строки, попадающие в список подзапроса. Важно: если подзапрос вернёт хотя бы один NULL, результат внешнего запроса может стать пустым (логика трёхзначная). Поэтому в подзапросе часто пишут WHERE столбец IS NOT NULL.
В эталоне студенты есть в каждом из 8 вузов — результат 0 строк. Это нормально: запишите в отчёте «пустой результат — все вузы представлены».
Ожидается 1 строка: Медведев (STUDENT_ID = 19) — специально для заданий с NOT EXISTS на ЛР №10.
Ожидается 1 предмет: Физкультура (SUBJ_ID = 73).
WHERE SUBJ_ID IS NOT NULL и в EXAM_MARKS появится строка с SUBJ_ID = NULL, NOT IN может вернуть ноль строк для всех предметов. На ЛР №10 сравните с NOT EXISTS — он NULL не «ломает».JOIN с UNIVERSITY — совпали ли строки?WHERE STIPEND > ALL (SELECT STIPEND FROM STUDENT WHERE STIPEND > 0 AND STUDENT_ID <> 7) — кого оставит?SELECT * FROM STUDENT WHERE STUDENT_ID NOT IN (SELECT STUDENT_ID FROM EXAM_MARKS) без фильтра NULL может вести себя странно, если в EXAM_MARKS появится NULL в STUDENT_ID?WHERE должен вернуть ровно одно значение?IN с подзапросом отличается от JOIN?NOT IN опасен, если в подзапросе есть NULL?NOT IN?DISTINCT в подзапросе для UNIVERSITY_ID?скрипт lab09_FIO.sql (ФИО латиницей) + скриншоты результатов.
lab09_FIO.sql (ФИО латиницей).-- ЛР №9, IvanovII, группа ВО-ИСИТ-31.-- rows: N и краткий вывод.Имя файла отчёта: lab09_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab09_IvanovII.sql.
Ответы на контрольные вопросы.
Цель: писать коррелированные подзапросы; использовать EXISTS, NOT EXISTS, операторы ANY/ALL.
Связь с ЛР №9: там подзапрос был «сам по себе»; здесь внутренний запрос ссылается на строку внешнего (s1.UNIVERSITY_ID) — выполняется заново для каждой строки снаружи.
Внутренний SELECT использует столбец внешней строки (s1.UNIVERSITY_ID, s1.KURS). Для каждого студента заново считается средняя стипендия в его вузе на его курсе.
Ожидается 3 строки: Иванов (ВГУ, 1 курс — выше среднего по группе), Орлов (ЮФУ, 1 курс), Белкин (ВГУ, 3 курс). Нули в знаменателе не мешают — они входят в среднее по группе.
EXISTS (подзапрос) возвращает true, если подзапрос вернул хотя бы одну строку. Часто пишут SELECT 1 — важен факт наличия строк, а не их содержимое.
Ожидается 2 вуза: БГУ (студент 16) и МГУ (студент 10).
В эталоне у каждого вуза есть студенты — результат 0 строк (как NOT IN в ЛР №9).
Ожидается 8 студентов с хотя бы одной «5» (в эталоне — Иванов, Петров, Козлова, Волков, Кузнецов, Лебедева, Крылова и др.).
Ожидается 1 строка: Медведев (STUDENT_ID = 19) — тот же результат, что NOT IN на ЛР №9, но без ловушки NULL.

Результат §3 — один студент без оценок.
Строки, где оценка максимальна для своего предмета. Ожидается 12 строк (несколько «лучших» по предметам 10, 43, 56, 94 и т.д.). Если для предмета одна оценка — она тоже «максимальна».
Если подзапрос после ALL пуст (нет оценок по предмету), условие для внешней строки не выполняется — такие строки не попадут в результат.
LEFT JOIN … WHERE em.STUDENT_ID IS NULL.IN vs EXISTS для §2.1 — кратко в комментарии.WHERE STIPEND > ANY (SELECT …) — чем отличается от > ALL?s1.UNIVERSITY_ID?скрипт lab10_FIO.sql (ФИО латиницей) + скриншоты результатов.
lab10_FIO.sql (ФИО латиницей).-- ЛР №10, IvanovII, группа ВО-ИСИТ-31.-- rows: N и пояснение корреляции или EXISTS.Имя файла отчёта: lab10_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab10_IvanovII.sql.
Ответы на контрольные вопросы.
Цель: соединять таблицы через INNER JOIN и LEFT JOIN; строить отчёты по связям FK; считать агрегаты после JOIN.
Связь с ЛР №9–10: подзапрос с IN можно заменить JOIN — на этой работе учитесь читать и писать явные соединения. Схема FK — в приложении.
Нарисуйте цепочку: UNIVERSITY ← STUDENT → EXAM_MARKS → SUBJECT; отдельно SUBJ_LECT связывает SUBJECT и LECTURER. Условие соединения — равенство ключей FK.
INNER JOIN оставляет только строки, для которых есть пара в обеих таблицах. У каждого студента в эталоне есть вуз — потерь строк не будет.
Ожидается 19 строк — по числу студентов.
Ожидается 13 строк (студенты вузов в Москве, СПб, Новосибирске и т.д.; вузы ВГУ и ВГМУ в Воронеже отсеяны).
Ожидается 24 строки — все строки EXAM_MARKS с подставленными фамилиями и названиями предметов.
Ожидается 12 строк — по таблице SUBJ_LECT в приложении.
К отчёту приложите свой скриншот вкладки Results для запроса §2.1 (ожидается 24 строки: фамилия, предмет, оценка, дата).
LEFT JOIN сохраняет все строки левой таблицы; если справа нет пары — столбцы справа NULL.
Ожидается 19 строк с фамилиями (у каждого вуза есть студенты; «пустых» вузов нет).
В эталоне — 0 строк. Запишите в отчёте: «все 8 вузов представлены студентами».
Ожидается 1 строка: Медведев (STUDENT_ID = 19) — тот же результат, что NOT EXISTS на ЛР №10.
Ожидается 8 строк. Используйте COUNT(s.STUDENT_ID), а не COUNT(*) — иначе вуз без студентов дал бы 1 вместо 0 (в эталоне все счётчики ≥ 1).
Только студенты с оценками; у Медведева строки не будет. Число строк — 18 (19 − 1 без ведомости).
IN (ЛР №9) — совпали ли строки?RIGHT JOIN отличается от LEFT JOIN (поменяли таблицы местами)?ON (декартово произведение).скрипт lab11_FIO.sql (ФИО латиницей) + скриншоты результатов.
lab11_FIO.sql или приложите схему отдельно в PDF.-- ЛР №11, IvanovII, группа ВО-ИСИТ-31.Имя файла отчёта: lab11_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab11_IvanovII.sql.
Ответы на контрольные вопросы.
Цель: объединять результаты нескольких SELECT; понять разницу UNION и UNION ALL; применить множественные операции к эталону UniversityDB.
Связь с ЛР №11: JOIN соединяет таблицы в одном запросе; UNION складывает результаты двух запросов с одинаковым числом столбцов.
В эталоне: 19 студентов, 10 преподавателей, 24 строки EXAM_MARKS; у Медведева (STUDENT_ID=19) нет оценок.
Средний балл по студенту с названием вуза — закрепление ЛР №11.
Ожидается 19 строк; у Медведева avg_mark = NULL.
Ожидается 29 строк (19 студентов + 10 преподавателей).
INTERSECT — 7 городов (Воронеж, Москва, Новосибирск, Санкт-Петербург, Белгород, Томск, Ростов-на-Дону). EXCEPT — 1 строка: Курск (есть у студентов, нет среди городов вузов).
Повторите §2 с UNION вместо UNION ALL. В эталоне фамилии студентов и преподавателей не пересекаются — снова 29 строк. Запишите в отчёте: UNION удаляет дубликаты между двумя наборами; UNION ALL — нет.
Только предметы с не менее двух оценок. Ожидается до 5 строк — зафиксируйте фактическое число и значения avg_mark в комментарии -- rows: N.
скрипт lab12_FIO.sql (ФИО латиницей) + скриншоты результатов.
lab12_FIO.sql.-- ЛР №12, IvanovII, группа ВО-ИСИТ-31.Имя файла отчёта: lab12_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab12_IvanovII.sql.
Ответы на контрольные вопросы.
Цель: строковые и дата-функции T-SQL, ROUND, CAST на UniversityDB.
Первый запрос — 19 строк. LEN(SURNAME)=6 — 8 студентов: Петров, Козлова, Новиков, Сидоров, Волков, Павлов, Белкин, Крылова.
Ожидается 16 экзаменов в январе 2026 (все даты EXAM_MARKS в эталоне — 2026 год).
По каждому курсу — одна строка агрегата (курсы 1–4 в эталоне).
Ожидается 8 строк — по числу вузов.
скрипт lab13_FIO.sql (ФИО латиницей) + скриншоты результатов.
lab13_FIO.sql.-- ЛР №13, IvanovII, группа ВО-ИСИТ-31.Имя файла отчёта: lab13_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab13_IvanovII.sql.
Ответы на контрольные вопросы.
Цель: условные выражения и обработка NULL в SELECT; студент STUDENT_ID=19 (Медведев) с CITY IS NULL.
Ожидается 1 строка: STUDENT_ID=19, Медведев, CITY = NULL.
Ожидается 24 строки — все записи ведомости.
Ожидается 19 строк — по каждому студенту.
У Медведева в обоих запросах — не указан вместо NULL.
Во втором запросе Медведев с NULL — в конце списка.
Ожидается 4 строки — по числу категорий стипендии.
скрипт lab14_FIO.sql (ФИО латиницей) + скриншоты результатов.
lab14_FIO.sql.-- ЛР №14, IvanovII, группа ВО-ИСИТ-31.Имя файла отчёта: lab14_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab14_IvanovII.sql.
Ответы на контрольные вопросы.
Цель: объявление переменных DECLARE/SET, ветвление IF/ELSE, проверка IF EXISTS в T-SQL.
При @kurs = 3 ожидается 4 студента.
Результат PRINT — на вкладке Messages в SSMS.
Ожидается сообщение «Есть студенты без экзаменов» (Медведев, STUDENT_ID=19).
скрипт lab15_FIO.sql (ФИО латиницей) + скриншоты результатов.
lab15_FIO.sql.-- ЛР №15, IvanovII, группа ВО-ИСИТ-31.Имя файла отчёта: lab15_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab15_IvanovII.sql.
Ответы на контрольные вопросы.
Цель: цикл WHILE, обработка ошибок TRY/CATCH, транзакция с откатом.
Ожидается 10 строк — числа от 1 до 10.
Ожидается строка с err_num (нарушение FK) — без изменения данных.
Оценка 6 вне диапазона CHECK — попадание в CATCH, строка не вставляется.
При успехе стипендии студентов 1 и 3 не меняются в сумме; при ошибке — ROLLBACK.
скрипт lab16_FIO.sql (ФИО латиницей) + скриншоты результатов.
lab16_FIO.sql.-- ЛР №16, IvanovII, группа ВО-ИСИТ-31.Имя файла отчёта: lab16_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab16_IvanovII.sql.
Ответы на контрольные вопросы.
Цель: тип XML, методы .value() и .query().
Ожидается 1 строка в UnivXml для univ_id=10 (ВГУ).
Ожидается название ВГУ и город Воронеж.
Во втором запросе — 2 строки (Иванов, Петров из XML).
Если права позволяют:
Иначе в отчёте опишите: индекс ускоряет XPath-запросы к большим документам.
скрипт lab17_FIO.sql (ФИО латиницей) + скриншоты результатов.
lab17_FIO.sql.-- ЛР №17, IvanovII, группа ВО-ИСИТ-31.Имя файла отчёта: lab17_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab17_IvanovII.sql.
Ответы на контрольные вопросы.
Цель: рекурсивный CTE по таблице ORG_UNIT в UniversityDB; сравнение adjacency list и nested sets.
В эталоне 10 строк в ORG_UNIT (иерархии ВГУ и МГУ).
От корня UNIT_ID=1 (ВГУ) ожидается 7 строк — всё поддерево вуза 10.
Столбец lvl — уровень вложенности (0 у ректората, 1 у факультетов и т.д.).
Кратко сравните adjacency list (PARENT_ID, как в ORG_UNIT) и nested sets (left/right): плюсы и минусы каждой модели.
скрипт lab18_FIO.sql (ФИО латиницей) + скриншоты результатов.
lab18_FIO.sql.-- ЛР №18, IvanovII, группа ВО-ИСИТ-31.Имя файла отчёта: lab18_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab18_IvanovII.sql.
Ответы на контрольные вопросы.
Цель: документная модель в MongoDB Compass; сравнение с реляционной строкой dbo.STUDENT.
Стенд: MongoDB Compass на учебном ПК (или MongoDB Atlas по указанию преподавателя). SQL Server для сравнения — UniversityDB.
University и коллекцию students.USE UniversityDB; — данные для документов возьмите из STUDENT + UNIVERSITY.Вставьте минимум пять документов с полями _id, surname, name, kurs, вложенный объект university: { name, city }:
Данные можно взять из:
Ожидается 5 документов в коллекции students.
Зафиксируйте число документов при фильтре kurs: 3 — в эталоне SQL при KURS=3 четыре студента.
После deleteOne документ 99 отсутствует — приложите скриншот.
lab19_FIO.pdf: скриншоты Compass, примеры запросов.STUDENT+JOIN UNIVERSITY.Имя файла отчёта: lab19_FIO.pdf (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab19_IvanovII.pdf.
скриншоты Compass + lab19_FIO.pdf (ФИО латиницей).
Ответы на контрольные вопросы.
Цель: создать представления VIEW на UniversityDB, упростить доступ к JOIN и проверить чтение через представление.
Напоминание: VIEW — сохранённый запрос с именем, а не копия таблицы.
VIEW содержит 19 строк — по числу студентов.
Во VIEW — 24 строки; фильтр MARK=5 — 9 пятёрок в эталоне.
Объясните в комментарии к скрипту: WITH SCHEMABINDING защищает определение VIEW от изменения базовых столбцов.
скрипт lab20_FIO.sql (ФИО латиницей) + скриншоты результатов.
lab20_FIO.sql.-- ЛР №20, IvanovII, группа ВО-ИСИТ-31.v_StudentUniv и v_StudentMarks WHERE MARK=5.Имя файла отчёта: lab20_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab20_IvanovII.sql.
Ответы на контрольные вопросы.
Цель: создать и вызвать хранимые процедуры на T-SQL, в том числе usp_StudentByKurs из материала о процедурах.
При @kurs = 3 ожидается 4 студента.
скрипт lab21_FIO.sql (ФИО латиницей) + скриншоты результатов.
lab21_FIO.sql.-- ЛР №21, IvanovII, группа ВО-ИСИТ-31.Имя файла отчёта: lab21_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab21_IvanovII.sql.
Ответы на контрольные вопросы.
Цель: создать AFTER-триггер аудита на EXAM_MARKS и INSTEAD OF INSERT на представление v_StudentUniv.
Измените оценку в транзакции с ROLLBACK и проверьте SELECT * FROM dbo.AuditLog; — после ROLLBACK записей аудита не останется.
Объясните в отчёте: VIEW с JOIN не всегда updatable — INSTEAD OF перенаправляет INSERT на базовые таблицы.
скрипт lab22_FIO.sql (ФИО латиницей) + скриншоты результатов.
lab22_FIO.sql.-- ЛР №22, IvanovII, группа ВО-ИСИТ-31.Имя файла отчёта: lab22_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab22_IvanovII.sql.
Ответы на контрольные вопросы.
Цель: login, user, database role; выдать минимальные права на UniversityDB.
Подключитесь вторым окном SSMS как reader_test и попробуйте:
Ожидается отказ — нет INSERT на STUDENT (только SELECT через role_read).
После GRANT EXECUTE пользователь reader_test может вызвать процедуру без прямого SELECT на LECTURER.
скрипт lab23_FIO.sql (ФИО латиницей) + скриншоты результатов.
lab23_FIO.sql.-- ЛР №23, IvanovII, группа ВО-ИСИТ-31.Имя файла отчёта: lab23_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab23_IvanovII.sql.
Ответы на контрольные вопросы.
Цель: резервное копирование и восстановление + комплексный практикум по материалам семестра на UniversityDB.
UniversityDB в эталонном состоянии: 19 студентов, 24 оценки..bak на учебном сервере.Если нет прав — приложите скриншоты SSMS и текстовый план RESTORE.
Опишите цепочку FULL / DIFF / LOG backup и когда нужен STOPAT.
Обязательно четыре пункта: (1) JOIN + фильтр, (2) GROUP BY + HAVING, (3) подзапрос или EXISTS, (4) SELECT из VIEW или вызов процедуры. Остальные пункты списка — по желанию. Раньше требовалось «8 из 10»; минимум снижен, см. раздел «Отчёт» ниже.
Выполните как минимум четыре обязательных пункта ниже; каждый — отдельный блок в lab24_FIO.sql с комментарием.
GROUP BY + HAVING (средний балл по предметам).EXISTS (студенты без оценок — ожидается Медведев).CREATE VIEW + SELECT из VIEW.usp_StudentByKurs с @kurs=3 — 4 строки.DROP TRIGGER в конце скрипта).CITY.GRANT/REVOKE или описание, если нет прав.ORG_UNIT от UNIT_ID=1 — 7 строк.dbo.UnivXml (если таблица ещё есть с ЛР №17).UniversityDB_restore, а не поверх боевой базы?lab24_FIO.sql.-- ЛР №24, IvanovII, группа ВО-ИСИТ-31.Имя файла отчёта: lab24_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab24_IvanovII.sql.
lab24_FIO.sql (ФИО латиницей) + защита.
Ответы на контрольные вопросы.
| № | Тема | Вид | Часы | Материал курса |
|---|---|---|---|---|
| Раздел 1. Основы баз данных и проектирование (нед. 1–3) | ||||
| 1 | Основные понятия баз данных и СУБД | Лек | 2 | Л.1 |
| 2 | SSMS: системные и учебные БД | Лаб | 2 | ЛР №1 |
| 3 | Реляционная модель. Функциональные зависимости | Лек | 2 | Л.2 |
| 4 | Таблицы и первый SELECT | Лаб | 2 | ЛР №2 |
| 5 | Нормализация. Аномалии обновления | Лек | 2 | Л.3 |
| 6 | Новые таблицы, ключи и ограничения | Лаб | 2 | ЛР №3 |
| 7 | FK, ALTER TABLE, индексы | Лаб | 2 | ЛР №4 |
| Раздел 2. SQL: выборка и изменение данных (нед. 4) | ||||
| 8 | Многопользовательские и распределённые БД | Лек | 2 | Л.4 |
| 9 | INSERT, SELECT, WHERE | Лаб | 2 | ЛР №5 |
| 10 | UPDATE, DELETE, ORDER BY | Лаб | 2 | ЛР №6 |
| Раздел 3. Транзакции и многопользовательский доступ (нед. 5–8) | ||||
| 11 | Транзакции. Свойства ACID | Лек | 2 | Л.5 |
| 12 | Агрегатные функции | Лаб | 2 | ЛР №7 |
| 13 | GROUP BY, HAVING, ROLLUP | Лаб | 2 | ЛР №8 |
| 14 | Аномалии параллельного доступа | Лек | 2 | Л.6 |
| 15 | Вложенные подзапросы | Лаб | 2 | ЛР №9 |
| 16 | Коррелированные подзапросы и EXISTS | Лаб | 2 | ЛР №10 |
| 17 | Уровни изоляции транзакций | Лек | 2 | Л.7 |
| 18 | INNER и OUTER JOIN | Лаб | 2 | ЛР №11 |
| 19 | UNION, EXCEPT, INTERSECT | Лаб | 2 | ЛР №12 |
| 20 | Блокировки, тупики, репликация | Лек | 2 | Л.8 |
| 21 | Функции строк, чисел, дат | Лаб | 2 | ЛР №13 |
| 22 | CASE, ISNULL, COALESCE | Лаб | 2 | ЛР №14 |
| Раздел 4. XML, иерархии и нереляционные модели (нед. 9–10) | ||||
| 23 | Структурированные и неструктурированные данные | Лек | 2 | Л.9 |
| 24 | Переменные и IF | Лаб | 2 | ЛР №15 |
| 25 | Циклы WHILE и TRY/CATCH | Лаб | 2 | ЛР №16 |
| 26 | Язык XML | Лек | 2 | Л.10 |
| 27 | XML в SQL Server | Лаб | 2 | ЛР №17 |
| 28 | Иерархические данные | Лаб | 2 | ЛР №18 |
| Раздел 5. Администрирование и программирование в СУБД (нед. 11–12) | ||||
| 29 | Администрирование и мониторинг СУБД | Лек | 2 | Л.11 |
| 30 | MongoDB — документная БД | Лаб | 2 | ЛР №19 |
| 31 | Представления VIEW | Лаб | 2 | ЛР №20 |
| 32 | Программирование в БД: процедуры, триггеры | Лек | 2 | Л.12 |
| 33 | Хранимые процедуры | Лаб | 2 | ЛР №21 |
| 34 | Триггеры DML и INSTEAD OF | Лаб | 2 | ЛР №22 |
| Раздел 6. Резервное копирование и защита данных (нед. 13–14) | ||||
| 35 | Резервное копирование | Лек | 2 | Л.13 |
| 36 | GRANT, REVOKE, роли | Лаб | 2 | ЛР №23 |
| 37 | Восстановление данных и защита | Лек | 2 | Л.14 |
| 38 | Восстановление данных и итоговый практикум | Лаб | 2 | ЛР №24 |
| Раздел 7. Распределённые БД и хранилища данных (нед. 15–16) | ||||
| 39 | Распределённые БД и двухфазная фиксация | Лек | 2 | Л.15 · курсовые №6, 21 |
| 40 | Хранилища данных и подготовка к экзамену | Лек | 2 | Л.16 · билеты |
| Раздел 8. Итоговая аттестация | ||||
| 41 | Экзамен по дисциплине «Управление данными» | ИКР | 2,3 | Экзамен · вопросы |
| Лекция | Тема | ЛР | На практике |
|---|---|---|---|
| Л.1 | Понятия БД, СУБД, SSMS | №1 | CREATE DATABASE, подключение |
| Л.2 | Реляционная модель, ФЗ | №2 | таблицы, INSERT, SELECT |
| Л.3 | Нормализация, ключи | №3–4 | DDL, FK, ALTER, индексы |
| Л.4 | Многопользовательский доступ | №5–6 | DML, WHERE, UPDATE, DELETE |
| Л.5 | ACID, транзакции | №7–8 | агрегаты, GROUP BY |
| Л.6 | Аномалии параллельного доступа | №9–10 | подзапросы, EXISTS |
| Л.7 | Уровни изоляции | №11–12 | JOIN, UNION |
| Л.8 | Блокировки, тупики, репликация | №13–14 | функции, CASE |
| Л.9 | Структурированные / неструктурированные данные | №15–16 | переменные, TRY/CATCH |
| Л.10 | XML, XSD | №17–18 | XML в SQL Server, CTE-иерархии |
| Л.11 | Администрирование, мониторинг | №19–20 | MongoDB, VIEW |
| Л.12 | Процедуры, триггеры, планы | №21–22 | процедуры, триггеры |
| Л.13 | Резервное копирование | №23 | GRANT, роли |
| Л.14 | Восстановление, защита данных | №24 | BACKUP/RESTORE + практикум |
| Л.15 | Распределённые БД, 2PC | — | теория · курсовые №6, 21 |
| Л.16 | OLAP, подготовка к экзамену | — | вопросы · билеты |
| Вид | Количество | Академ. часы |
|---|---|---|
| Лекции | 16 пар | 32 |
| Лабораторные | 24 пары | 48 |
| Итого контакт | 40 пар | 80 |
| Экзамен (ИКР) | 1 | 2,3 |
Kursovaya_FIO (или согласованное имя); не менее 5 таблиц с PRIMARY KEY, FOREIGN KEY, минимум два ограничения CHECK или UNIQUE; осмысленное наполнение (не «пустые таблицы»).SELECT с WHERE, JOIN, агрегаты с GROUP BY/HAVING, подзапрос или EXISTS; плюс один из элементов серверного программирования: VIEW, хранимая процедура или AFTER-триггер (аудит или бизнес-правило).BEGIN TRAN … COMMIT/ROLLBACK (операция из нескольких шагов) или демонстрация резервного копирования своей базы (BACKUP / описание RESTORE).kursovaya_FIO.sql (ФИО латиницей) + пояснительная записка со скриншотами SSMS (схема, примеры запросов, при наличии — план выполнения или права доступа).Свою тему (не из списка) можно предложить преподавателю, если она укладывается в минимум выше и не дублирует UniversityDB «одной таблицей Excel».
| № | Тема и содержание проекта |
|---|---|
| 1 | Интернет-магазин. Спроектировать БД: товары, категории, клиенты, заказы, строки заказа. Реализовать оформление заказа в транзакции; отчёты — топ товаров, сумма по клиентам; VIEW «активные заказы». |
| 2 | Частная клиника. Пациенты, врачи, приёмы, диагнозы, назначения. Связи M:N «врач — специализация»; CHECK на дату приёма; процедура «расписание врача на неделю». |
| 3 | Автосервис. Клиенты, автомобили, заказ-наряды, работы, запчасти. FK «авто → владелец»; агрегат «выручка по месяцам»; триггер аудита изменения стоимости наряда. |
| 4 | Гостиница. Номера, типы номеров, бронирования, гости, оплаты. Запрет пересечения броней (CHECK или триггер); JOIN «загрузка номеров»; резервная копия перед тестовым наполнением. |
| 5 | Публичная библиотека. Книги, авторы, экземпляры, читатели, выдачи. Нормализация «автор не дублируется в каждой выдаче»; EXISTS «книги на руках у читателя»; процедура выдачи/возврата. |
| 6 | Фитнес-клуб. Абонементы, типы, посещения, тренеры, групповые занятия. GROUP BY «популярность занятий»; транзакция продления абонемента; VIEW для ресепшена. |
| 7 | Ресторан / доставка. Меню, блюда, ингредиенты, заказы, курьеры. M:N «блюдо — ингредиент»; HAVING «блюда дороже среднего»; XML-описание акции (столбец XML, извлечение поля). |
| 8 | Агентство недвижимости. Объекты, типы, районы, клиенты, сделки, агенты. Иерархия районов (рекурсивный CTE); подзапрос «объекты без сделок»; индекс по цене + комментарий к плану запроса. |
| 9 | Ветеринарная клиника. Владельцы, питомцы, породы, приёмы, вакцинации. CHECK на вид животного; LEFT JOIN «питомцы без приёмов за год»; роли «ветеринар / регистратор» (GRANT на уровне учебного login). |
| 10 | Музыкальная школа. Ученики, преподаватели, инструменты, уроки, абонементы. Расписание без двойного бронирования кабинета; GROUP BY «часы по преподавателям»; процедура usp_LessonsByTeacher. |
| 11 | Фото-студия. Клиенты, пакеты услуг, брони слотов, фотографы, оборудование. Транзакция «бронь + предоплата»; VIEW «загрузка студии по дням»; миграция прайса из Excel (описать шаги загрузки). |
| 12 | Прокат велосипедов. Пункты проката, велосипеды, клиенты, аренды, штрафы. FK и CASCADE при списании велосипеда; отчёт «простой парка»; BACKUP после наполнения эталоном. |
| 13 | Кафе настольных игр. Игры, жанры, столы, брони, участники турниров. M:N «турнир — игрок»; EXISTS «игроки без турниров»; триггер запрета удаления игры с активными бронями. |
| 14 | Центр репетиторства. Предметы, репетиторы, ученики, занятия, оплаты. Нормализация «не хранить ФИО репетитора в каждой оплате»; JOIN «долги учеников»; процедура отчёта за период. |
| 15 | Цветочный магазин. Букеты, компоненты, поставщики, заказы, доставки. CHECK на сезонность/остаток; UNION «все контактные лица (клиенты + поставщики)»; VIEW для витрины заказов. |
| 16 | IT-Helpdesk. Пользователи, категории заявок, тикеты, комментарии, исполнители. Статусы и история (таблица аудита или триггер); GROUP BY «среднее время закрытия»; демонстрация блокировки при параллельном UPDATE статуса. |
| 17 | Садовое товарищество. Участки, владельцы, взносы, показания счётчиков, обращения. Иерархия «улица — участок»; агрегаты по задолженности; сравнение «плохая одна таблица» vs нормализованная схема в записке. |
| 18 | Приют для животных. Питомцы, породы, поступления, усыновления, волонтёры, пожертвования. NOT EXISTS «давно не усыновлённые»; транзакция «усыновление + закрытие карточки»; этичные тестовые данные без реальных ФИО. |
| 19 | Коворкинг. Помещения, рабочие места, тарифы, брони, резиденты. Рекурсивный CTE по зонам этажа; процедура поиска свободного места; RESTORE на копию Kursovaya_FIO_restore после ошибочного DELETE. |
| 20 | Кинотеатр. Залы, сеансы, фильмы, места, билеты, кассиры. Уникальность «место + сеанс»; JOIN «заполняемость сеансов»; VIEW для онлайн-расписания; индекс по дате сеанса. |
| 21 | Прачечная / химчистка. Клиенты, изделия, услуги, приёмы в работу, статусы, оплаты. CHECK на допустимый статус; GROUP BY «выручка по видам услуг»; сценарий ROLLBACK при ошибочном массовом UPDATE. |
| 22 | Каршеринг (локальный парк). Автомобили, тарифы, поездки, клиенты, штрафы, ТО. FK и даты; подзапрос «клиенты с поездками > N»; описание RPO/RTO для такой БД в записке. |
| 23 | Музей. Экспонаты, залы, эпохи, экскурсии, гиды, билеты. M:N «экскурсия — экспонат»; агрегат «посещаемость по залам»; хранение текста экспозиции в XML с выборкой XPath. |
| 24 | Спортивная секция. Секции, тренеры, спортсмены, соревнования, результаты, медосмотры. GROUP BY «медали по секциям»; процедура зачисления в секцию; GRANT «тренер видит только свою секцию» через VIEW и права. |
| 25 | Своя тема (по согласованию). Любая предметная область студента: от онлайн-курсов до складского учёта — при условии выполнения минимума из списка выше и защиты ER-схемы на консультации до сдачи. |
UniversityDB — единая учебная база курса: вузы, студенты, преподаватели, предметы, оценки.
SQL-скрипт — это обычный текст с командами T-SQL: создание таблиц, вставка строк, запросы. В SSMS его набирают или вставляют в окно New Query и выполняют клавишей F5 (или кнопкой Execute). Сервер выполняет команды и сохраняет результат в файлах базы на диске — не в окне SSMS.
Эталонный скрипт UniversityDB собран для этого курса и лежит на этой странице — отдельного файла скачивать не нужно. Ниже он разбит на блоки с пояснениями. На ЛР №2 вы копируете блоки по порядку в SSMS и сохраняете свою копию в файл lab02_FIO.sql (ФИО латиницей).
UniversityDB.CREATE TABLE. Блок 6 — INSERT. Между частями с GO можно выполнять по очереди.UNIVERSITY 1—∞ STUDENT, UNIVERSITY 1—∞ LECTURER, UNIVERSITY 1—∞ ORG_UNIT.
SUBJECT 1—∞ EXAM_MARKS, STUDENT 1—∞ EXAM_MARKS.
LECTURER ∞—∞ SUBJECT через SUBJ_LECT.
ORG_UNIT.PARENT_ID ссылается на ORG_UNIT.UNIT_ID (иерархия).
Выполняйте блоки по порядку. Если база пустая после ЛР №1, блок 2 можно пропустить.
Создаёт базу UniversityDB, если её ещё нет, и переключает контекст на неё. На ЛР №1 вы уже делали то же командой CREATE DATABASE — здесь повтор для полного эталона.
Нужен только если таблицы уже создавали и хотите пересобрать схему с нуля. Удаление идёт от зависимых таблиц к независимым — иначе СУБД не даст удалить родительскую таблицу.
Таблицы, на которые ссылаются другие: список вузов и список предметов. Создаются первыми.
У каждой строки — ссылка UNIVERSITY_ID на справочник вузов (внешний ключ). Именно так устроена схема с внешними ключами.
EXAM_MARKS — оценка студента по предмету. SUBJ_LECT — кто какой предмет ведёт. ORG_UNIT — иерархия кафедр (нужна на ЛР №18).
Строки вставляются в порядке зависимостей: сначала родители (UNIVERSITY, SUBJECT), потом дети. Иначе внешний ключ не найдёт ссылку и INSERT завершится ошибкой.
6.1. Вузы:
6.2. Предметы:
6.3. Студенты (19 строк; у id=19 город NULL — для заданий с IS NULL):
6.4. Преподаватели:
6.5. Оценки (24 строки; у студента 19 оценок нет — для NOT EXISTS и LEFT JOIN):
6.6. Кто какой предмет ведёт:
6.7. Подразделения вузов:
Проверка после блока 6: SELECT COUNT(*) FROM STUDENT; — должно быть 19. У студента с STUDENT_ID = 19 нет строк в EXAM_MARKS.
Те же строки, что в блоке 6, в удобном виде — можно сверить результат после INSERT.
На телефоне широкие таблицы прокручиваются пальцем влево и вправо.
| UNIVERSITY_ID | UNIVERSITY_NAME | RATING | CITY |
|---|---|---|---|
| 10 | ВГУ | 450 | Воронеж |
| 11 | НГУ | 580 | Новосибирск |
| 12 | СПбГУ | 650 | Санкт-Петербург |
| 14 | БГУ | 320 | Белгород |
| 15 | ТГУ | 390 | Томск |
| 18 | ВГМУ | 410 | Воронеж |
| 22 | МГУ | 700 | Москва |
| 32 | ЮФУ | 470 | Ростов-на-Дону |
| ID | Фамилия | Имя | Стип. | Курс | Город | Рождение | Вуз |
|---|---|---|---|---|---|---|---|
| 1 | Иванов | Иван | 150 | 1 | Воронеж | 2007-03-12 | 10 |
| 2 | Сидорова | Анна | 200 | 1 | Москва | 2007-07-01 | 22 |
| 3 | Петров | Пётр | 0 | 3 | Курск | 2005-11-20 | 10 |
| 4 | Козлова | Мария | 180 | 2 | Санкт-Петербург | 2006-04-15 | 12 |
| 5 | Новиков | Дмитрий | 120 | 2 | Новосибирск | 2006-09-03 | 11 |
| 6 | Сидоров | Вадим | 0 | 4 | Москва | 2004-01-28 | 22 |
| 7 | Морозова | Елена | 250 | 1 | Белгород | 2007-12-05 | 14 |
| 8 | Волков | Алексей | 140 | 3 | Томск | 2005-06-17 | 15 |
| 9 | Соколова | Ирина | 160 | 2 | Воронеж | 2006-02-22 | 18 |
| 10 | Кузнецов | Борис | 0 | 5 | Москва | 2003-08-09 | 22 |
| 11 | Орлов | Никита | 130 | 1 | Ростов-на-Дону | 2007-05-14 | 32 |
| 12 | Зайцева | Ольга | 170 | 4 | Воронеж | 2004-10-30 | 10 |
| 13 | Павлов | Андрей | 90 | 3 | Новосибирск | 2005-03-08 | 11 |
| 14 | Лебедева | Татьяна | 210 | 2 | Москва | 2006-12-19 | 22 |
| 15 | Котов | Павел | 0 | 1 | Курск | 2008-01-11 | 10 |
| 16 | Лукин | Артём | 110 | 5 | Белгород | 2003-04-25 | 14 |
| 17 | Белкин | Вадим | 155 | 3 | Воронеж | 2005-09-16 | 10 |
| 18 | Крылова | Светлана | 190 | 4 | Санкт-Петербург | 2004-07-07 | 12 |
| 19 | Медведев | Олег | 80 | 1 | NULL | 2007-08-21 | 32 |
| ID | Фамилия | Имя | Город | Вуз |
|---|---|---|---|---|
| 24 | Колесников | Борис | Воронеж | 10 |
| 46 | Никонов | Иван | Воронеж | 10 |
| 74 | Лагутин | Павел | Москва | 22 |
| 108 | Струков | Николай | Москва | 22 |
| 276 | Николаев | Виктор | Воронеж | 10 |
| 328 | Сорокин | Андрей | Орёл | 10 |
| 401 | Смирнова | Ольга | Санкт-Петербург | 12 |
| 512 | Гусев | Игорь | Новосибирск | 11 |
| 620 | Фролов | Сергей | Томск | 15 |
| 705 | Макарова | Анна | Белгород | 14 |
| SUBJ_ID | Название | Часы | Семестр |
|---|---|---|---|
| 10 | Информатика | 56 | 1 |
| 18 | Химия | 40 | 2 |
| 22 | Физика | 34 | 1 |
| 31 | Базы данных | 72 | 5 |
| 43 | Математика | 56 | 2 |
| 56 | История | 34 | 4 |
| 73 | Физкультура | 34 | 5 |
| 94 | Английский | 56 | 3 |
| EXAM_ID | STUDENT_ID | SUBJ_ID | MARK | EXAM_DATE |
|---|---|---|---|---|
| 1 | 1 | 10 | 5 | 2026-01-15 |
| 2 | 1 | 22 | 4 | 2026-01-18 |
| 3 | 3 | 10 | 3 | 2026-01-15 |
| 4 | 3 | 22 | 4 | 2026-01-18 |
| 5 | 2 | 10 | 5 | 2026-01-16 |
| 6 | 4 | 43 | 5 | 2026-06-10 |
| 7 | 5 | 10 | 4 | 2026-01-15 |
| 8 | 6 | 56 | 3 | 2026-06-12 |
| 9 | 8 | 94 | 5 | 2026-01-20 |
| 10 | 9 | 18 | 4 | 2026-06-08 |
| 11 | 10 | 31 | 5 | 2026-01-22 |
| 12 | 12 | 56 | 4 | 2026-06-12 |
| 13 | 13 | 10 | 2 | 2026-01-15 |
| 14 | 14 | 94 | 5 | 2026-01-20 |
| 15 | 17 | 22 | 3 | 2026-01-18 |
| 16 | 7 | 10 | 5 | 2026-01-16 |
| 17 | 11 | 10 | 4 | 2026-01-16 |
| 18 | 15 | 22 | 3 | 2026-01-18 |
| 19 | 18 | 56 | 5 | 2026-06-12 |
| 20 | 16 | 31 | 4 | 2026-01-22 |
| 21 | 1 | 43 | 5 | 2026-06-10 |
| 22 | 12 | 31 | 3 | 2026-01-22 |
| 23 | 6 | 31 | 4 | 2026-01-22 |
| 24 | 4 | 10 | 4 | 2026-01-16 |
Студент 19 (Медведев) специально без строк в EXAM_MARKS и с CITY NULL: на нём проверяют IS NULL, NOT EXISTS и LEFT JOIN … IS NULL.
| LECTURER_ID | SUBJ_ID |
|---|---|
| 24 | 10 |
| 24 | 31 |
| 46 | 22 |
| 46 | 18 |
| 74 | 43 |
| 108 | 56 |
| 276 | 73 |
| 328 | 10 |
| 401 | 94 |
| 512 | 10 |
| 620 | 18 |
| 705 | 56 |
| UNIT_ID | PARENT_ID | UNIT_NAME | UNIVERSITY_ID |
|---|---|---|---|
| 1 | NULL | Ректорат | 10 |
| 2 | 1 | Учебное управление | 10 |
| 3 | 1 | Факультет КНиИТ | 10 |
| 4 | 3 | Кафедра информационных технологий | 10 |
| 5 | 3 | Кафедра математики | 10 |
| 6 | 1 | Факультет ПММ | 10 |
| 7 | 6 | Кафедра механики | 10 |
| 20 | NULL | Ректорат | 22 |
| 21 | 20 | Факультет ВМК | 22 |
| 22 | 21 | Кафедра алгоритмических языков | 22 |
| Задача | SQL Server | SQLite |
|---|---|---|
| Первые N строк | TOP (N) … ORDER BY | LIMIT N |
| Пагинация | OFFSET FETCH | LIMIT … OFFSET |
| Строка сейчас | GETDATE(), SYSDATETIME() | datetime('now') |
| Конкатенация | + или CONCAT | || |
| Авточисло | INT IDENTITY | INTEGER PRIMARY KEY |
| Юникод-литерал | N'текст' | 'текст' UTF-8 |
| Удаление дубликатов строк запроса | DISTINCT | DISTINCT |
| FULL JOIN | есть | эмуляция UNION |
| Процедуры | CREATE PROC | нет |
| Бэкап | BACKUP DATABASE | VACUUM INTO / копия файла |
На экзамене из этого списка задают два вопроса (см. билеты ниже).
На экзамене выдаётся один билет из списка ниже: два теоретических вопроса + одна SQL-задача по UniversityDB. Нажмите на номер билета, чтобы открыть.
NOT EXISTS или LEFT JOIN … IS NULL).GROUP BY, HAVING).SUBJ_LECT).CITY IS NULL (ожидается Медведев, STUDENT_ID=19).UNIVERSITY_ID=10 от UNIT_ID=1.NOT EXISTS или LEFT JOIN … IS NULL).GROUP BY, HAVING).SUBJ_LECT).CITY IS NULL (ожидается Медведев, STUDENT_ID=19).UNIVERSITY_ID=10 от UNIT_ID=1.NOT EXISTS или LEFT JOIN … IS NULL).GROUP BY, HAVING).SUBJ_LECT).CITY IS NULL (ожидается Медведев, STUDENT_ID=19).UNIVERSITY_ID=10 от UNIT_ID=1.