Навигация по курсу

На телефоне широкие таблицы и схемы прокручивайте влево и вправо.

УПРАВЛЕНИЕ ДАННЫМИ

Группа ВО-ИСИТ-31 · преподаватель Абрамов М.А.

3 курс · осенний семестр 2026/27

16 лекций · 32 ак. ч.24 лабораторные · 48 ак. ч.
Неделя 1 · 8–13 сентября 2026
ДатаДеньВремяТипТемаОткрыть
08.09Вт16:00–17:35ЛекцияЛ.1. Основные понятия баз данных и СУБД
Неделя 2 · 14–20 сентября 2026
ДатаДеньВремяТипТемаОткрыть
15.09Вт12:30–14:05Лаб.ЛР №1. SSMS: системные и учебные БД
16.09Ср14:15–15:50ЛекцияЛ.2. Реляционная модель. Функциональные зависимости
16.09Ср16:00–17:35Лаб.ЛР №2. Таблицы и первый SELECT
Неделя 3 · 21–27 сентября 2026
ДатаДеньВремяТипТемаОткрыть
22.09Вт14:15–15:50ЛекцияЛ.3. Нормализация. Аномалии обновления
22.09Вт16:00–17:35Лаб.ЛР №3. DDL: CREATE, типы, ограничения
23.09Ср12:30–14:05Лаб.ЛР №4. FK, ALTER TABLE, GO
Неделя 4 · 28 сентября – 4 октября 2026
ДатаДеньВремяТипТемаОткрыть
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
Неделя 5 · 5–11 октября 2026
ДатаДеньВремяТипТемаОткрыть
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
Неделя 6 · 12–18 октября 2026 прогноз
ДатаДеньВремяТипТемаОткрыть
13.10Вт12:30–14:05ЛекцияЛ.6. Аномалии параллельного доступа
13.10Вт14:15–15:50Лаб.ЛР №9. Вложенные подзапросы
14.10Ср12:30–14:05Лаб.ЛР №10. Коррелированные подзапросы и EXISTS
Неделя 7 · 19–25 октября 2026 прогноз
ДатаДеньВремяТипТемаОткрыть
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
Неделя 8 · 26 октября – 1 ноября 2026 прогноз
ДатаДеньВремяТипТемаОткрыть
27.10Вт12:30–14:05ЛекцияЛ.8. Блокировки, тупики, репликация
27.10Вт14:15–15:50Лаб.ЛР №13. Функции строк, чисел, дат
28.10Ср12:30–14:05Лаб.ЛР №14. CASE, ISNULL, COALESCE
Неделя 9 · 2–8 ноября 2026 прогноз
ДатаДеньВремяТипТемаОткрыть
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
04.11 — День народного единства
Неделя 10 · 9–15 ноября 2026 прогноз
ДатаДеньВремяТипТемаОткрыть
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. Иерархические данные
Неделя 11 · 16–22 ноября 2026 прогноз
ДатаДеньВремяТипТемаОткрыть
17.11Вт12:30–14:05ЛекцияЛ.11. Администрирование и мониторинг СУБД
17.11Вт14:15–15:50Лаб.ЛР №19. MongoDB — документная БД
18.11Ср12:30–14:05Лаб.ЛР №20. Представления VIEW
Неделя 12 · 23–29 ноября 2026 прогноз
ДатаДеньВремяТипТемаОткрыть
24.11Вт12:30–14:05ЛекцияЛ.12. Программирование в БД: процедуры, триггеры
24.11Вт14:15–15:50Лаб.ЛР №21. Хранимые процедуры
01.12Вт12:30–14:05Лаб.ЛР №22. Триггеры DML и INSTEAD OF
Неделя 13 · 30 ноября – 6 декабря 2026 прогноз
ДатаДеньВремяТипТемаОткрыть
01.12Вт14:15–15:50ЛекцияЛ.13. Резервное копирование
02.12Ср12:30–14:05Лаб.ЛР №23. GRANT, REVOKE, роли
Неделя 14 · 7–13 декабря 2026 прогноз
ДатаДеньВремяТипТемаОткрыть
08.12Вт12:30–14:05ЛекцияЛ.14. Восстановление данных и защита
08.12Вт14:15–15:50Лаб.ЛР №24. Восстановление данных и итоговый практикум
Неделя 15 · 14–20 декабря 2026 прогноз
ДатаДеньВремяТипТемаОткрыть
15.12Вт12:30–14:05ЛекцияЛ.15. Распределённые БД и двухфазная фиксация
Неделя 16 · 21–27 декабря 2026 прогноз
ДатаДеньВремяТипТемаОткрыть
15.12Вт14:15–15:50ЛекцияЛ.16. Хранилища данных и подготовка к экзамену

Лекция 1. Основные понятия баз данных и СУБД

Дата: 08.09.2026, вт, 16:00–17:35, ауд. 210

О чём эта лекция. Перед SQL и таблицами — базовые слова: данные, база данных, СУБД, клиент. Без этого на лабораторных легко превратиться в «копировальщика кода».

Главная мысль одной фразой: база — это упорядоченные связанные данные; СУБД — программа, которая ими управляет; SSMS — окно, через которое вы отправляете запросы на сервер.

После прочтения вы сможете:

  • отличить данные от информации и объяснить пирамиду DIKW;
  • назвать роли клиента, СУБД и базы на схеме «студент → SSMS → SQL Server → UniversityDB»;
  • объяснить, почему Excel не заменяет СУБД при росте задачи;
  • подготовиться к ЛР №1: подключение к серверу и создание пустой UniversityDB.

План занятия

Тема
Организация курса
Данные, база данных, СУБД — на примерах
От данных к информации (пирамида DIKW)
Почему не хватает Excel и Word
Три «этажа» одной базы (ANSI/SPARC) — коротко
Демо SQL Server Management Studio (SSMS) и подготовка к ЛР №1

1. Организация курса

2. Основные понятия

2.1. Данные

Данные — это то, что уже записано: число, слово, дата. Сами по себе они часто мало о чём говорят.

СитуацияЧто видимЭто данные?
На термометре38.5Да — просто число
В списке группыИвановДа — просто фамилия
В календаре08.09.2026Да — просто дата
В SMS банка-500Да — пока неясно, списание это или пополнение

Чтобы число стало понятным, нужен контекст: кто, что, когда, в каких единицах. Об этом — в разделе про пирамиду.

2.2. База данных

База данных (БД) — это большой упорядоченный набор связанных данных по одной теме. Не одна таблица на листочке, а система хранения.

Пример из вуза: в одной базе UniversityDB лежат студенты, вузы, предметы, оценки — и они связаны: у каждого студента есть вуз, у каждой оценки — студент и предмет.

Пример из жизни: каталог интернет-магазина — товары, цены, заказы, покупатели. Это тоже база, только тема другая.

Аналогия: база данных — как картотека в библиотеке: не одна книга, а весь фонд с правилами, где что лежит.

2.3. СУБД

СУБД — программа, которая хранит базу, принимает запросы, следит, чтобы данные не потерялись и не испортились.

Примеры СУБД в курсе:

Аналогия: если база — картотека, то СУБД — библиотекарь и правила работы с картотекой: выдаёт книги, не даёт двум людям одновременно испортить одну карточку, следит за порядком.

2.4. Что часто путают

НазваниеЧто это на самом делеПример
База данныхДанные + структура (таблицы, связи)UniversityDB
СУБДПрограмма, которая базой управляетSQL Server, SQLite
КлиентОкно, через которое мы пишем SQLSQL Server Management Studio (SSMS), DB Browser for SQLite
Файл ExcelФайл с таблицей, но это не полноценная СУБДгруппа31.xlsx
Фраза «я установил базу данных», когда установили только SQL Server Management Studio (SSMS), — неверна. SQL Server Management Studio (SSMS) — это клиент. Базу создают отдельно внутри SQL Server.
Кто есть кто Слева направо: от человека к хранилищу данных Студент пишет SQL- запрос Клиент SQL Server Management Studio (SSMS) или DB Browser for SQLite SQL Server программа- СУБД UniversityDB база данных файлы на диске сервера

Рисунок 1. Вы работаете в клиенте. Клиент обращается к СУБД. СУБД хранит базу.

Спросите группу:

  • «Где вы каждый день видите базы данных?» — банк, расписание, соцсети, маркетплейсы, госуслуги.
  • «Excel-файл со списком группы — это СУБД?» — нет, это файл. Удобно для одного человека, плохо для большой системы.

3. От данных к информации — пирамида DIKW

Мы уже выучили три слова: данные, база, СУБД. Теперь логичный вопрос: зачем всё это нужно, если можно записать оценки в тетрадь? Организации хотят не просто цифры, а понимание и решения — для этого данные проходят несколько шагов. Их часто рисуют пирамидой DIKW.

Пирамида DIKW Data — Information — Knowledge — Wisdom к решению W Мудрость решение — что делать K Знания вывод, закономерность I Информация понятно, о чём речь D Данные просто записи, факты СУБД помогает на этих уровнях

Рисунок 2. Снизу вверх: от «голых» цифр к решению. СУБД помогает на нижних двух уровнях.

Разберём три разные ситуации — так проще запомнить, чем одной длинной таблицей.

ПримерУровеньКак это звучит
1. Оценка в вузеДанные5
ИнформацияИванов получил 5 по информатике 15.01.2026
ЗнанияСредний балл Иванова 4.5 — стипендию, скорее всего, сохранит
МудростьДеканат решает: предложить пересдачу или оставить как есть
2. ПогодаДанные−5
ИнформацияСегодня в Воронеже −5 °C
ЗнанияТакая температура опасна для длительной прогулки без перчаток
МудростьЛучше перенести outdoor-мероприятие в помещение
3. БанкДанные1500
ИнформацияНа счёте осталось 1500 ₽ после оплаты общежития
ЗнанияДо зарплаты 10 дней — денег может не хватить
МудростьОтложить крупную покупку или взять часть из резерва

Где здесь СУБД?

4. Почему одного Excel мало

Если данные — это фундамент, то Excel часто даёт «кривой фундамент»: удобно на первый день, больно через месяц. Представьте: староста ведёт список группы, кафедра — оценки, методист — нагрузку. В каждом файле есть Иванов и телефон деканата.

База данных решает это так:

Много файлов группа.xlsx оценки.xlsx вуз.docx Одна база STUDENT · UNIVERSITY SUBJECT · EXAM_MARKS связаны, не копируются

Рисунок 3. Вместо разрозненных файлов — одна база с правилами.

5. Три «этажа» одной базы

Это не пирамида DIKW из раздела 3. Здесь другая мысль: одни и те же данные в СУБД можно описать на трёх этажах — от «что видит человек» до «как всё записано на диске». Это трёхуровневая архитектура ANSI/SPARC — три взгляда на одну базу.

Три этажа одной базы сверху вниз: пользователь, схема, диск 1. Внешний уровень что видит конкретный человек Студент: только свои оценки Деканат: все студенты группы VIEW, права 2. Концептуальный уровень общая схема базы — таблицы и связи STUDENT · UNIVERSITY · SUBJECT · EXAM_MARKS здесь вы пишете SQL на лабораторных SELECT СУБД сама 3. Внутренний уровень как данные лежат на диске сервера файлы .mdf / .ldf · индексы · журнал транзакций вы этот этаж не настраиваете — этим занимается администратор

Рисунок 4. Один запрос студента «проходит» через схему таблиц; СУБД сама обращается к файлам на диске.

ЭтажЧто этоПример
1. Внешний Каждому пользователю показывают свою часть данных Студент видит только свои оценки; деканат — всю группу
2. Концептуальный Общая схема базы: таблицы, столбцы, связи — здесь пишете SQL STUDENT, UNIVERSITY, EXAM_MARKS
3. Внутренний Физическое хранение на диске сервера — настраивает администратор Файлы базы, индексы, журнал транзакций
Главное для курса: на лабораторных вы работаете на 2-м этаже — пишете SQL к таблицам. СУБД переводит запрос на 3-й этаж сама. 1-й этаж — когда кому-то показывают не всю таблицу, а часть (позже: представления VIEW и права GRANT на ЛР №17 и №23).

Зачем это знать? Чтобы не путать «таблицу в Object Explorer» и «файл на диске». Таблица STUDENT для вас — логическая. Если администратор добавит индекс для ускорения, столбцы таблицы не меняются — меняется только устройство на 3-м этаже.

6. Какие бывают СУБД и кто с ними работает

Кратко — «карта» на весь семестр, без деталей.

Кто работает с базой:

7. Подготовка к лабораторной №1 — что сделаете в SQL Server Management Studio (SSMS)

На учебных ПК кафедры SQL Server и SQL Server Management Studio (SSMS) уже установлены. Логин и имя сервера сообщит преподаватель (часто (local), .\SQLEXPRESS или имя учебного сервера).

7.1. Пошаговая инструкция

  1. Запустить SQL Server Management Studio (SSMS).
  2. Окно подключения: тип Database Engine, имя сервера — как скажет преподаватель, проверка Windows или SQL-логина.
  3. Слева откройте Object Explorer, затем узел Databases.
  4. Развернуть System Databases: master, model, msdb, tempdb — их не трогаем, только смотрим.
  5. Посмотреть список пользовательских баз (если есть чужие от прошлых групп — не удалять без спроса).
  6. Создать свою базу: правый клик Databases, New Database…, имя UniversityDB, OK.
    Или в окне запроса: CREATE DATABASE UniversityDB;
  7. Открыть New Query, выбрать в списке базу UniversityDB, выполнить:
SELECT DB_NAME() AS current_db; SELECT @@VERSION AS sql_version;

Проверьте для себя: вы в клиенте SSMS; запрос выполняется на сервере SQL Server; база UniversityDB создана или открыта для работы.

Connect to Server в SSMS

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

SQL Server в Management Studio

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

Системные базы данных

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

Создание базы данных

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

Первый запрос SELECT

Рисунок 5. Основные окна SSMS на ЛР №1. Иллюстрации: скриншоты с сайта metanit.com.

7.2. Слова, которые встретятся на ЛР №2 (кратко)

8. Вопросы для закрепления

  1. Что такое данные? Приведите свой пример.
  2. Чем база данных отличается от СУБД?
  3. SQL Server Management Studio (SSMS) — это база, СУБД или клиент?
  4. Чем информация отличается от данных? Пример из вуза или из жизни.
  5. Назовите два недостатка хранения всего в Excel.
  6. Зачем нужен PRIMARY KEY?

Итог лекции:

  • Данные — записи. База — упорядоченный набор данных. СУБД — программа, которая базой управляет.
  • Из данных получают информацию, потом выводы и решения — пирамида DIKW.
  • Для серьёзной работы файлов мало — нужна база с правилами и SQL.
  • На ЛР №1 откроете SQL Server Management Studio (SSMS) и создадите базу; на ЛР №2 — таблицы и первые запросы.

Лекция 2. Реляционная модель. Функциональные зависимости

Дата: 15.09.2026, вт, 17:45–19:20, ауд. 102

О чём эта лекция. На ЛР №1 вы создали базу UniversityDB. Сейчас важно понять не «как нажать кнопки в SSMS», а почему данные хранят в нескольких таблицах и откуда берутся столбцы STUDENT_ID, UNIVERSITY_ID, ограничения PRIMARY KEY и FOREIGN KEY.

Главная мысль одной фразой: в реляционной модели мы формулируем правила между столбцами: «зная значение одного столбца (или пары столбцов), однозначно определяется значение другого». Пример: по STUDENT_ID однозначно известна SURNAME — по номеру студента всегда одна и та же фамилия. Такое правило называется функциональной зависимостью. Из неё следуют ключи и нормализация (лекция 3).

После прочтения вы сможете:

  • объяснить, чем таблица в SQL Server отличается от «одного листа Excel»;
  • назначить первичный и внешний ключ на примере STUDENT и UNIVERSITY;
  • сформулировать правило «STUDENT_ID определяет SURNAME» и привести свой пример;
  • проверить по зависимостям, может ли столбец быть ключом таблицы.

План занятия

Тема
Зачем не одна большая таблица
Таблица = отношение: строка, столбец, правила
Первичный и внешний ключ
Функциональная зависимость
Замыкание X⁺ — проверка ключа
Связь с ЛР №2 и лекцией 3

1. Зачем не один файл Excel

Успеваемость группы часто ведут в Excel: файл Университет.xlsx, лист Группа. В столбце A — фамилии (со 2-й строки), в первой строке начиная с B — названия предметов, в ячейках — оценки. У каждого студента одна строка, фамилия не повторяется — для журнала это удобно и логично.

База данных решает другие задачи: связать студентов с вузами, преподавателями, множеством предметов и оценок; отвечать на запросы без переделки листа; не дублировать справочную информацию. Поэтому сравнение «Excel vs SQL» — не «фамилия три раза на листе», а ограничения такой схемы при росте данных.

СитуацияЧто не так (или чем неудобно)
Новый предмет в семестреНужен новый столбец; меняются формулы, сводные таблицы, шаблон отчёта
К журналу добавили «Название вуза» и «Город вуза»Оба поля копируются в каждой строке студента — переименовали вуз, правите весь лист
Другой формат: каждая оценка — отдельная строка (студент + предмет + балл)Фамилия и курс повторяются в каждой строке с оценкой
Несколько групп, курсов, преподавателейМного листов или файлов; сводный отчёт по кафедре собирается вручную
Запрос «все пятёрки по «Базам данных» по всем группам»Поиск по разным столбцам и листам; в SQL — один SELECT по таблице оценок

Решение в UniversityDB: разделить данные по смыслу и связать таблицы числовыми ключами:

Журнал на одном листе Excel Три таблицы в UniversityDB Лист «Группа» · файл Университет.xlsx Фамилия Базы данных Физика История Иванов 5 4 5 Петров 4 5 Фамилия не дублируется — одна строка на студента Но: новый предмет — новый столбец; вуз/город — повтор в каждой строке Оценки по многим группам — много листов, нет общих правил UNIVERSITY UNIVERSITY_ID PK UNIVERSITY_NAME CITY 10 · МГУ · Москва 12 · ВГУ · Воронеж STUDENT STUDENT_ID PK SURNAME, KURS UNIVERSITY_ID FK 1 · Иванов · 2 · 10 2 · Петров · 3 · 10 1 N один вуз — много студентов EXAM_MARKS STUDENT_ID, SUBJECT_ID MARK 1 · 31 · 5 N Справочник вуза — один раз; студент ссылается числом; оценки — отдельные строки

Рисунок 1. Слева — привычный журнал (фамилия в строке, предметы в столбцах). Справа — как те же смыслы разложены в UniversityDB.

2. Таблица в теории (и в SQL)

В учебниках таблицу называют отношением, строку — кортежем, столбец — атрибутом. В SSMS вы по-прежнему видите обычную таблицу — термины нужны для экзамена и курсовой, когда описываете модель.

2.1. Три правила реляционной таблицы

  1. Атомарность. В ячейке одно значение. Нельзя писать «Москва, Санкт-Петербург» в поле «город» — для нескольких городов нужна отдельная таблица или отдельные строки.
  2. Нет дубликатов строк. Две полностью одинаковые строки не имеют смысла; первичный ключ как раз не даёт «слить» двух людей в одну запись.
  3. Порядок не важен. Строки можно вывести в любом порядке (ORDER BY — отдельная команда). Столбцы тоже можно переставить в SELECT, смысл данных не меняется.

2.2. Мини-пример таблицы STUDENT

STUDENT_IDSURNAMEKURSUNIVERSITY_ID
1Иванов210
2Петров310
19Сидоров112

Здесь одна строка — один студент. Номер STUDENT_ID не повторяется. По UNIVERSITY_ID видно, что Иванов и Петров из одного вуза (10), но это не ключ студента: у одного вуза много студентов.

3. Ключи

Ключ — это столбец или набор столбцов, по которым строку можно однозначно найти или связать с другой таблицей.

3.1. Первичный ключ (PRIMARY KEY)

У каждой строки свой уникальный идентификатор. В STUDENT это STUDENT_ID.

3.2. Внешний ключ (FOREIGN KEY)

Столбец в одной таблице ссылается на первичный ключ другой. STUDENT.UNIVERSITY_ID ссылается на UNIVERSITY.UNIVERSITY_ID.

Смысл: «студент ссылается на существующий вуз». Если в справочнике нет вуза с номером 999, вставить студента с UNIVERSITY_ID = 999 нельзя — СУБД вернёт ошибку. Так сохраняется целостность данных.

Первичный ключ и внешний ключ UNIVERSITY UNIVERSITY_ID PK UNIVERSITY_NAME CITY 10 | МГУ | Москва STUDENT STUDENT_ID PK SURNAME, KURS UNIVERSITY_ID FK 1 | Иванов | 2 | 10 ссылка

Рисунок 2. PK — «имя строки внутри таблицы». FK — «ссылка на строку другой таблицы».

-- Фрагмент из ЛР №2 CREATE TABLE dbo.UNIVERSITY ( UNIVERSITY_ID INT PRIMARY KEY, UNIVERSITY_NAME NVARCHAR(80) NOT NULL, CITY NVARCHAR(40) ); CREATE TABLE dbo.STUDENT ( STUDENT_ID INT PRIMARY KEY, SURNAME NVARCHAR(40) NOT NULL, KURS INT, UNIVERSITY_ID INT NOT NULL, FOREIGN KEY (UNIVERSITY_ID) REFERENCES dbo.UNIVERSITY(UNIVERSITY_ID) );

4. Функциональная зависимость

Правило: STUDENT_ID определяет SURNAME. Оно читается так: если в двух строках таблицы совпадает номер студента, совпадает и фамилия. Ещё проще: по номеру студента фамилия определяется однозначно — не «может быть Иванов, а может Петров».

Если правило задают два столбца сразу: «STUDENT_ID и SUBJECT_ID вместе определяют MARK» — у одного студента по одному предмету одна оценка.

Когда зависимости нет: по UNIVERSITY_ID нельзя однозначно узнать фамилию студента — в одном вузе учатся и Иванов, и Петров. Правила «UNIVERSITY_ID определяет SURNAME» для таблицы STUDENT нет.

STUDENT_ID определяет SURNAME STUDENT_ID опред. SURNAME ID=5 всегда один и тот же Иванов

Рисунок 3. Номер студента определяет фамилию (в рамках нашей базы).

4.1. Примеры зависимостей в UniversityDB

ЗаписьСмыслГде живёт
STUDENT_ID определяет SURNAME, KURS, UNIVERSITY_IDПо номеру студента известны фамилия, курс и вузТаблица STUDENT
UNIVERSITY_ID определяет UNIVERSITY_NAME, CITYПо номеру вуза известны название и городТаблица UNIVERSITY
STUDENT_ID и SUBJ_ID вместе определяют MARKОдна оценка студента по предмету (составной ключ)Таблица EXAM_MARKS

4.2. Типичная ошибка проектирования

Если добавить в STUDENT столбец UNIVERSITY_NAME «для удобства», возникает зависимость UNIVERSITY_ID определяет UNIVERSITY_NAME, но название вуза будет копироваться у каждого студента.

STUDENT_IDSURNAMEUNIVERSITY_IDUNIVERSITY_NAME
Плохо1Иванов10МГУ
Плохо2Петров10МГУ

Переименовали вуз — нужно обновить все строки студентов. Правильно: имя вуза только в UNIVERSITY, у студента — только UNIVERSITY_ID.

Важно: функциональная зависимость — это правило предметной области («один человек — одна фамилия»), а не команда SQL. Сначала формулируем правила, потом создаём таблицы на ЛР.

5. Замыкание — как проверить, «хватает ли» столбец на роль ключа

Иногда ключ составной (из нескольких столбцов). Чтобы проверить, может ли один столбец (или набор столбцов) быть ключом всей таблицы, строят замыкание — список всех столбцов, которые из него однозначно следуют по вашим правилам зависимостей.

На экзамене задачу часто дают в «абстрактном» виде — столбцы A, B, C, D и зависимости A определяет B. Это то же самое, что STUDENT_ID определяет SURNAME, только без имён из базы. Ниже — такой учебный пример; в работе с UniversityDB мысленно подставляйте свои столбцы.

5.1. Алгоритм словами

  1. Взять стартовый набор столбцов (например, только STUDENT_ID или, в абстрактной задаче, только {A}).
  2. Для каждой зависимости «если известны левые столбцы, однозначно известны правые»: если все левые уже в наборе, добавить правые.
  3. Повторять шаг 2, пока набор растёт.
  4. Если в конце получились все столбцы таблицы — стартовый набор суперключ (подходит в качестве первичного ключа).

5.2. Разобранный пример (с буквами A, B, C, D)

Таблица с столбцами 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 — ключ (суперключ) этой таблицы.

Рост замыкания A⁺ {A} {A,B} {A,B,C} {A,B,C,D} ✓ ключ

Рисунок 4. Каждый шаг — применение одного правила «столбец определяет столбец».

Формальные правила вывода (аксиомы Армстронга) в программе экзамена упоминаются; для практики достаточно уметь пройти один пример, как выше, и понимать смысл «X определяет Y».

6. ЛР №2

На ЛР №2 вы создаёте таблицы UNIVERSITY, STUDENT, SUBJECT и другие: команды SQL берутся из приложения, раздел «Сборка базы по шагам». Затем выполняете первые SELECT.

Вопросы для самопроверки:

  1. Чем таблица в SQL Server отличается от одного листа Excel с «всём подряд»?
  2. Зачем STUDENT_ID, если есть фамилия?
  3. Зачем UNIVERSITY_ID, если можно хранить название вуза текстом в строке студента?
  4. Что произойдёт при INSERT студента с UNIVERSITY_ID, которого нет в UNIVERSITY?
  5. Что означает запись STUDENT_ID определяет SURNAME?

Краткие ответы:

Итог. Реляционная модель — это язык правил между столбцами. Ключи находят строки и связывают таблицы. Функциональные зависимости описывают, кто из кого следует. Без этого SQL превращается в набор скриптов «по образцу», а на курсовой и экзамене нужно объяснять почему схема устроена так.

Лекция 3. Нормализация. Аномалии обновления

Дата: 22.09.2026, вт, 19:30–21:05, ауд. 307

О чём эта лекция. На ЛР №2 вы собрали UniversityDB из нескольких таблиц. Здесь — зачем так делают: что ломается в одной «широкой» таблице и как формальные нормальные формы помогают проектировать схему без лишних дублей.

Главная мысль одной фразой: каждый факт хранится в одном месте; если одно и то же имя вуза или старосты повторяется в десятках строк, обновление превращается в риск ошибки.

После прочтения вы сможете:

  • назвать три аномалии обновления и показать их на примере;
  • объяснить 1НФ, 2НФ и 3НФ простыми словами;
  • разложить «плохую» таблицу на две-три нормализованные;
  • связать нормализацию с тем, как устроены таблицы в UniversityDB.

План занятия

Тема
Три аномалии: обновления, вставки, удаления
От сущностей к таблицам
1НФ, 2НФ, 3НФ и НФБК — кратко
Декомпозиция: плохая и хорошая схема
Разбор на примере и мини-задача

1. Зачем не одна большая таблица

Представьте одну таблицу ОЦЕНКИ со столбцами: студент, группа, староста группы, предмет, преподаватель, оценка. На первый взгляд всё на виду — как в Excel. Но при изменении данных возникают проблемы:

АномалияЧто происходитПример
ОбновленияОдин факт записан во многих строках — править приходится вездеСменили старосту — нужно обновить все строки группы
ВставкиНельзя добавить справочные данные без «лишней» строкиНовый предмет не завести, пока никто его не сдал
УдаленияУдаляя последнюю строку, теряем сопутствующий фактУшёл последний студент группы — пропало имя старосты

Из жизни: если адрес магазина продублирован в каждой строке заказа, переезд магазина — это массовое редактирование и риск, что в одной строке адрес останется старым.

Одна таблица и три таблицы после нормализации ОЦЕНКИ — всё в одной таблице Иванов · 31 · Петрова · SQL · 5 Петров · 31 · Петрова · БД · 4 Сидорова · 32 · Козлов · SQL · 3 «Петрова» повторяется — смена старосты = правка всех строк GROUP 31 · Петрова STUDENT Иванов · 31 EXAM Иванов · SQL · 5 Справочник группы — один раз; оценка — отдельная строка; связь по номеру группы

Рисунок 1. Слева — дублирование «старосты» в каждой строке. Справа — те же смыслы в отдельных таблицах.

2. От сущностей к таблицам

При проектировании сначала выделяют сущности (Студент, Вуз, Предмет) и связи между ними. Связь «многие ко многим» (студент сдаёт много предметов, предмет сдают многие студенты) обычно даёт отдельную таблицу — у вас это EXAM_MARKS.

UniversityDB после ЛР №2 — уже нормализованный пример: вузы в UNIVERSITY, студенты в STUDENT, оценки отдельно, название вуза не копируется в каждую строку студента.

3. Нормальные формы

Нормальные формы — чек-лист при проектировании. Не нужно заучивать определения наизусть; важно понимать идею каждого шага.

3.1. Первая нормальная форма (1НФ)

В каждой ячейке одно значение, нет «списков через запятую» и повторяющихся столбцов «предмет1, предмет2, предмет3». Таблицы в SQL Server после CREATE TABLE обычно уже в 1НФ.

3.2. Вторая нормальная форма (2НФ)

1НФ + каждый неключевой столбец зависит от всего первичного ключа, а не от его части. Важно, когда ключ составной — например, пара (студент, предмет) в таблице оценок: оценка зависит от обоих столбцов сразу, а не только от студента.

3.3. Третья нормальная форма (3НФ)

2НФ + нет транзитивных зависимостей: неключевой столбец не должен зависеть от другого неключевого. Пример нарушения: в таблице студента хранить и UNIVERSITY_ID, и UNIVERSITY_NAME — имя вуза уже определяется номером вуза (это разбирали на лекции 2).

3.4. НФБК — коротко

НФБК строже 3НФ: в каждой нетривиальной записи «X определяет Y» набор X должен быть суперключом. Для учебной схемы достаточно понимать идею; UniversityDB спроектирована близко к 3НФ/НФБК.

4. Декомпозиция без потерь

Декомпозиция — разбиение одной таблицы на несколько так, чтобы по ключам можно было собрать те же данные через JOIN.

ПлохоХорошо
STUDENT_BAD(STUDENT_ID, SURNAME, UNIVERSITY_ID, UNIVERSITY_NAME)STUDENT(STUDENT_ID, SURNAME, UNIVERSITY_ID) и UNIVERSITY(UNIVERSITY_ID, UNIVERSITY_NAME)

Здесь UNIVERSITY_ID определяет UNIVERSITY_NAME — имя вуза хранится один раз. Цена нормализации — в запросах чаще нужен JOIN; выигрыш — при переименовании вуза правится одна строка в UNIVERSITY.

5. Мини-задача

Интернет-магазин в одной таблице: (order_id, customer_name, customer_city, product_name, price, qty).

  1. Какие сущности выделите?
  2. Какие таблицы получатся?

Ожидаемый ответ: CUSTOMER, PRODUCT, ORDERS (шапка заказа), ORDER_ITEM (строки заказа: товар, количество, цена на момент покупки).

6. Вопросы для самопроверки

  1. Чем аномалия обновления отличается от аномалии удаления?
  2. Почему EXAM_MARKS в UniversityDB — отдельная таблица, а не столбцы «математика», «физика» в STUDENT?
  3. Нарушает ли 3НФ таблица STUDENT(UNIVERSITY_ID, UNIVERSITY_NAME) без отдельного справочника вузов?
  4. Приведите свой пример дублирования данных «в одной таблице» из жизни или другого предмета.

Итог. Нормализация убирает лишние повторы и аномалии при INSERT, UPDATE и DELETE. UniversityDB — пример разумного разбиения; на ЛР №3 вы спроектируете отдельную схему «Библиотека» с ограничениями PK, FK, UNIQUE и CHECK.

Лекция 4. Многопользовательские и распределённые БД

Дата: 23.09.2026, ср, 16:00–17:35, ауд. 307

О чём эта лекция. До сих пор вы работали с базой в одиночку. В реальности к одному SQL Server подключаются десятки пользователей, а данные крупных организаций могут лежать на нескольких серверах. Разберём, чем отличается многопользовательский режим от «одного файла на диске» и что такое распределённая база данных.

Главная мысль одной фразой: многопользовательская СУБД — это общий сервер с отдельными сеансами; распределённая БД — логически одна база на нескольких узлах, где приложение не должно знать физическое размещение каждой строки.

После прочтения вы сможете:

  • объяснить схему «клиент — сервер» на примере SSMS и SQL Server;
  • отличить распределённую БД от двух несвязанных файлов Excel;
  • назвать причины фрагментации данных по узлам;
  • сформулировать, зачем курсу нужны транзакции (лекции 5–7).

План занятия

Тема
Многопользовательский режим, клиент–сервер, файлы базы
Распределённая БД, фрагментация, сравнение с «двумя Excel»
Конфликты одновременного доступа — введение
Мини-задачи, частые ошибки в понимании
Самопроверка, связь с ЛР №4 и лекцией 5

1. Многопользовательская СУБД

На ЛР №1–2 вы, скорее всего, работали с UniversityDB в одиночку. В учебном классе к одному экземпляру SQL Server одновременно подключены десятки окон SSMS — у каждого студента свой сеанс (session): свой текст запроса, свой результат, свои права.

Тот же принцип в вузе: деканат, бухгалтерия, электронная библиотека могут обращаться к одной серверной базе через разные программы — не через ваш SSMS, а через учётные системы. SQL Server изначально рассчитан на такой режим.

1.1. Аналогия и контраст с SQLite

СитуацияМногопользовательский сервер (SQL Server)Файл SQLite
Кто хранит данныеСлужба SQL Server на диске сервераОдин файл .db на диске
Кто подключаетсяМного клиентов по сетиОбычно одно приложение рядом с файлом
Запись одновременноСУБД координирует блокировки и транзакцииЧасто один писатель, остальные ждут
Наш курсОсновной стенд в классеУпоминаем как «база в одном файле» для сравнения

Аналогия: банк — не один кассир с тетрадкой, а общая система учёта, к которой обращаются многие операторы; SQLite ближе к личной записной книжке на одном столе.

1.2. Клиент, сервер и где лежат байты

Вы пишете запрос в SQL Server Management Studio — это клиент. Сервер SQL Server принимает текст T-SQL, выполняет его и возвращает таблицу результата или сообщение об ошибке. Каждое окно подключения — отдельный сеанс с номером session_id.

Важно: данные UniversityDB физически лежат на диске сервера в паре файлов:

Окно SSMS — не «контейнер базы», а окно отправки команд. Закрыли SSMS — база на сервере осталась.

Один сервер — много сеансов SSMS SSMS сеанс 52 SSMS сеанс 61 SQL Server UniversityDB 19 строк STUDENT UniversityDB.mdf данные таблиц UniversityDB_log.ldf журнал транзакций Оба сеанса читают одни и те же таблицы; конфликт — если оба пишут одну строку

Рисунок 1. Два окна SSMS — два сеанса; данные — в файлах на диске сервера.

Object Explorer с базой UniversityDB

Object Explorer: база видна в списке, но физически хранится в файлах сервера (см. свойства базы).

Свойства базы данных — путь к mdf и ldf

Свойства базы: путь к .mdf и .ldf. SSMS — не «файл Excel с базой внутри».

1.3. Мини-задача

Откройте SSMS (если есть доступ к серверу) и выполните:

SELECT @@SPID AS my_session_id, DB_NAME() AS current_db, SYSTEM_USER AS login_name;

Запишите свой my_session_id. Откройте второе окно запроса к той же базе — номер сеанса будет другим. Оба сеанса видят одни и те же 19 студентов в STUDENT.

2. Распределённая база данных

Распределённая БД — логически одна база для приложения, физически данные на нескольких узлах (серверах, городах, дата-центрах). Идеал — прозрачность размещения: разработчик пишет обычный SELECT * FROM STUDENT, а система сама обращается к нужному узлу.

2.1. Три ситуации — не путать

СитуацияЭто распределённая БД?Почему
Деканат — Excel, кафедра — Access, без связиНетНет общих FK, нет единой транзакции, дубли и расхождения
Две копии UniversityDB на разных флешкахНетЭто две независимые базы, не один каталог
Студенты Воронежа на сервере A, Москвы — на B, запрос «как к одной STUDENT»Да (идея)Единая схема, согласованность, общий SQL

2.2. Зачем распределять

2.3. Фрагментация

Горизонтальная — строки таблицы делят по правилу. Пример для UniversityDB: студенты с CITY = N'Воронеж' на узле 1, остальные — на узле 2. Для пользователя запрос SELECT COUNT(*) FROM STUDENT может прозрачно собрать сумму с обоих узлов.

Вертикальная — редкие или «тяжёлые» столбцы выносят на отдельный узел. Пример: в STUDENT оставить STUDENT_ID, SURNAME, KURS на основном сервере, а BIRTHDAY — на узле архива. На курсе вертикальную фрагментацию достаточно понимать на уровне идеи.

Горизонтальная фрагментация таблицы STUDENT Узел 1 (Воронеж) строки WHERE CITY = N'Воронеж' Узел 2 (остальные) все прочие CITY Логически: одна таблица STUDENT · SQL: SELECT … без указания узла СУБД / middleware маршрутизирует запрос

Рисунок 2. Одна таблица «логически», физически — части на разных серверах.

3. Проблема одновременного доступа

Когда два сеанса меняют одни и те же строки, без правил координации возможны сбои. На лекциях 5–7 разберём транзакции, ACID и уровни изоляции; здесь — только картина целиком.

3.1. Пример «два UPDATE одной стипендии»

Студенту STUDENT_ID = 1 стипендия 150. Сеанс A и сеанс B одновременно делают разные изменения:

ШагСеанс AСеанс BSTIPEND в базе (если нет блокировок)
1Читает 150Читает 150150
2Пишет 150 + 50 = 200200
3Пишет 150 + 30 = 180 (от старого 150!)180

Оба изменения «имели право» быть учтёнными (+50 и +30), но в базе осталось 180 — приращение A потерялось. Это потерянное обновление (лекция 6). Решение — транзакции и блокировки.

3.2. Что уже защищает UniversityDB

Но FK не мешает двум корректным UPDATE «перезаписать» друг друга — для этого нужны транзакции.

4. Мини-задачи для разбора (§4–5)

  1. Клиент или сервер? «Программа SSMS на моём ПК» — клиент. «Служба SQL Server на кафедральном сервере» — сервер. «Файл UniversityDB.mdf на диске сервера» — хранилище данных.
  2. Распределённость. У вуза сайт с расписанием в JSON и отдельная SQL-база с оценками без обмена — это две системы, не распределённая БД. Почему?
  3. Сеансы. Может ли один студент в SSMS случайно «удалить базу соседа»? Нет — у каждого свой сеанс; опасны только общие команды вроде DROP DATABASE, если есть права (на учебном сервере так не делаем).

Ответы: (2) нет единой схемы и транзакций между JSON и SQL; (3) сосед работает с тем же сервером, но не «внутри» вашего окна — права ограничивает администратор.

5. Частые ошибки в понимании

ОшибкаКак правильно
«База хранится в SSMS»SSMS только отправляет SQL; файлы — на сервере
«SQLite и SQL Server — одно и то же для курса»Идеи SQL общие; многопользовательская модель — на SQL Server
«Распределённая = две копии на флешках»Нужна согласованность и единый логический каталог
«FK защищает от всех конфликтов двух пользователей»FK про ссылки между таблицами; параллельные UPDATE — про транзакции

6. Вопросы для самопроверки

  1. Где физически хранятся данные UniversityDB — в окне SSMS или на диске сервера?
  2. Чем распределённая БД отличается от «Excel у кафедры + Access у деканата»?
  3. Чем горизонтальная фрагментация отличается от вертикальной — своими словами на примере STUDENT.
  4. Что такое сеанс (session) и почему у соседа по парте другой @@SPID?
  5. Назовите одну аномалию, которую разберут на лекции 6, и одно средство защиты с лекции 5.
  6. Какая лабораторная сегодня вечером закрепит изменение схемы через ALTER TABLE?

Итог. Многопользовательский режим — норма: один SQL Server, много сеансов, данные в .mdf/.ldf. Распределённая БД — один логический каталог на нескольких узлах; это не два несвязанных файла. Конфликты при одновременной записи решают транзакции (лекция 5). На ЛР №4ALTER TABLE, индексы, пакеты GO.

Лекция 5. Транзакции. Свойства ACID

Дата: 06.10.2026, вт, 12:30–14:05, ауд. 107

О чём эта лекция. Когда несколько пользователей меняют одни таблицы, операции нельзя выполнять «как попало»: перевод стипендии — это два UPDATE, и оба должны сохраниться вместе или отмениться вместе. Такие группы операций называются транзакциями.

Главная мысль одной фразой: транзакция с свойствами ACID — договор между приложением и СУБД: после COMMIT изменения надёжны и согласованы с ограничениями, после ROLLBACK — как будто их не было.

После прочтения вы сможете:

  • расшифровать буквы A, C, I, D на примере UniversityDB;
  • написать каркас BEGIN TRAN … COMMIT / ROLLBACK;
  • объяснить, что СУБД гарантирует FK/CHECK, но не «бизнес-правила в голове»;
  • использовать SAVE TRAN для частичного отката.

План занятия

Тема
Зачем транзакция; пример перевода стипендии
ACID на примерах UniversityDB
BEGIN, COMMIT, ROLLBACK, SAVE TRAN — разбор в SSMS
Мини-задачи, что СУБД не гарантирует
Самопроверка, связь с ЛР №6

1. Зачем нужна транзакция

На лекции 4 вы видели потерянное обновление: два сеанса читают одну стипендию и пишут разные суммы — одно изменение пропадает. Транзакция — способ сказать серверу: «эти команды — одно целое».

Транзакция — группа операций, которые выполняются как одно целое: либо все изменения сохраняются (COMMIT), либо ни одно (ROLLBACK).

1.1. Пример из UniversityDB

Перевод 1000 рублей стипендии от студента STUDENT_ID = 1 студенту STUDENT_ID = 3:

BEGIN TRANSACTION; UPDATE dbo.STUDENT SET STIPEND = STIPEND - 1000 WHERE STUDENT_ID = 1; UPDATE dbo.STUDENT SET STIPEND = STIPEND + 1000 WHERE STUDENT_ID = 3; -- проверка: сумма стипендий двух студентов не изменилась SELECT STUDENT_ID, SURNAME, STIPEND FROM dbo.STUDENT WHERE STUDENT_ID IN (1, 3); COMMIT;

Если второй UPDATE упадёт (например, нарушится CHECK на отрицательную стипендию), первый тоже должен откатиться — иначе деньги «исчезнут» из системы.

Транзакция: все шаги или ни одного BEGIN TRAN UPDATE … UPDATE … COMMIT всё сохранено ROLLBACK как не было При ошибке на втором UPDATE выбирают ROLLBACK — отменяется и первый

Рисунок 1. Два UPDATE в одной транзакции — атомарность (A).

2. Свойства ACID

СвойствоСмыслПример на UniversityDB
A — AtomicityВсё или ничегоОба UPDATE стипендии зафиксированы или оба отменены
C — ConsistencyБД остаётся в согласованном состоянииПосле COMMIT выполняются FK, CHECK, NOT NULL
I — IsolationПараллельные транзакции не мешают друг другуУровни изоляции — лекции 6–7
D — DurabilityПосле COMMIT данные переживут сбойЗапись в журнал .ldf до ответа клиенту

2.1. Consistency — что гарантирует СУБД, а что нет

Гарантирует: ограничения, объявленные в схеме — STIPEND >= 0, оценка 2–5, существующий UNIVERSITY_ID.

Не гарантирует автоматически: «суммарная стипендия группы не больше N», «число отличников не меньше 50%» — такие правила программируют в процедурах или проверяют в приложении.

2.2. Durability и файл журнала

После успешного COMMIT SQL Server сначала записывает изменения в журнал транзакций (.ldf), затем подтверждает клиенту. При сбое питания восстановление идёт по журналу (подробнее — лекции 13–14).

3. Команды в SQL Server — разбор по шагам

На ЛР №6 вы будете выполнять опасные UPDATE и DELETE внутри транзакции с ROLLBACK, чтобы не испортить эталон. Сейчас — та же техника на простом примере.

3.1. Успешная транзакция с откатом для учебы

USE UniversityDB; BEGIN TRAN; UPDATE dbo.STUDENT SET STIPEND = STIPEND + 200 WHERE KURS = 1; SELECT STUDENT_ID, SURNAME, STIPEND FROM dbo.STUDENT WHERE KURS = 1; ROLLBACK TRAN; SELECT STUDENT_ID, SURNAME, STIPEND FROM dbo.STUDENT WHERE KURS = 1;

После ROLLBACK стипендии должны совпасть с тем, что было до BEGIN TRAN. Вкладка Results — два одинаковых набора строк; на Messages — «Rollback Tran».

Окно запроса с BEGIN TRAN и ROLLBACK

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

Результат SELECT до и после ROLLBACK

Два одинаковых результата SELECT — признак успешного отката.

3.2. Точка сохранения SAVE TRAN

BEGIN TRAN; UPDATE dbo.STUDENT SET STIPEND = STIPEND + 200 WHERE KURS = 1; SAVE TRAN step1; UPDATE dbo.STUDENT SET STIPEND = STIPEND + 50 WHERE CITY = N'Москва'; ROLLBACK TRAN step1; -- отменили только второе обновление COMMIT; -- первое (+200 первокурсникам) сохранится

SAVE TRAN — промежуточная «закладка». ROLLBACK TRAN step1 откатывает до неё, но транзакция продолжается до COMMIT или полного ROLLBACK.

3.3. Ошибка CHECK внутри транзакции

BEGIN TRY BEGIN TRAN; UPDATE dbo.EXAM_MARKS SET MARK = 6 WHERE EXAM_ID = 1; -- нарушит CHECK COMMIT; END TRY BEGIN CATCH IF @@TRANCOUNT > 0 ROLLBACK TRAN; SELECT ERROR_NUMBER() AS err, ERROR_MESSAGE() AS msg; END CATCH;

На ЛР №16 разберёте TRY/CATCH подробнее. Здесь важно: при ошибке нужен ROLLBACK, иначе транзакция «висит» открытой.

4. Мини-задачи и границы ACID

  1. Atomicity: в переводе стипендии между двумя студентами сколько UPDATE должно войти в одну транзакцию?
  2. Consistency: можно ли закоммитить студента с UNIVERSITY_ID = 999? Почему?
  3. Isolation: пока ваш BEGIN TRAN не завершён, видят ли соседи ваши незафиксированные строки? (Зависит от уровня изоляции — по умолчанию частично защищены.)

ACID не обещает: высокую скорость, отсутствие тупиков, защиту от удаления диска без резервной копии.

5. Частые ошибки

ОшибкаКак правильно
Забыли COMMITТранзакция держит блокировки; закройте окно или выполните ROLLBACK
UPDATE без WHERE в транзакции и случайный COMMITСначала SELECT с тем же WHERE, на ЛР — только ROLLBACK
Путают ROLLBACK и DELETEROLLBACK отменяет незафиксированные изменения; DELETE — DML-команда

6. Вопросы для самопроверки

  1. Что произойдёт со вторым UPDATE, если первый уже закоммичен отдельно и второй упал с ошибкой?
  2. Какое свойство ACID гарантирует сохранность данных после сбоя питания?
  3. Почему CHECK на STIPEND >= 0 — про Consistency, а «фонд группы ≤ N» — уже нет?
  4. Когда на лабораторной нужен ROLLBACK вместо COMMIT?
  5. Чем SAVE TRAN отличается от полного ROLLBACK?
  6. Какая лабораторная закрепит BEGIN TRAN … ROLLBACK на практике?

Итог. Транзакция группирует операции; ACID описывает гарантии СУБД. На практике в SSMS освоите BEGIN TRAN, COMMIT, ROLLBACK и SAVE TRAN. Перед опасными изменениями на общем сервере — откат, а не коммит.

Лекция 6. Аномалии параллельного доступа

Дата: 13.10.2026, пн

О чём эта лекция. Если две транзакции работают параллельно без изоляции, результат может отличаться от любого последовательного выполнения. У каждой такой ситуации есть имя — аномалия.

Главная мысль одной фразой: потерянное обновление, грязное, неповторяемое и фантомное чтение — четыре классических конфликта; зная их, на следующей лекции вы выберете подходящий уровень изоляции.

После прочтения вы сможете:

  • привести бытовой пример каждой из четырёх аномалий;
  • нарисовать расписание двух транзакций в две колонки;
  • отличить неповторяемое чтение от фантомного;
  • связать аномалии с лабораторными по подзапросам (ЛР №9–10).

План занятия

Тема
Четыре аномалии на примерах UniversityDB
Расписания операций T1 / T2
Шпаргалка, отличия похожих случаев
Мини-задачи, частые ошибки
Самопроверка, связь с лекцией 7 и ЛР №6

1. Четыре классические аномалии

На лекции 5 вы группировали команды в транзакции. Если две транзакции идут параллельно, а изоляция недостаточна, результат может не совпасть ни с одним «честным» последовательным порядком. Такие эффекты имеют имена — их нужно узнавать на слух.

1.1. Потерянное обновление (lost update)

Два сеанса читают одно значение, оба считают от него, оба пишут — одно изменение затирается.

Пример со складом: 40 учебников. T1 продаёт 10 → пишет 30. T2 продаёт 5, но считала от 40 → пишет 35. Продано 15, в базе 35 — продажа T1 потеряна.

Пример из UniversityDB: два сеанса одновременно меняют STIPEND одного студента — как на лекции 4 и 5.

1.2. Грязное чтение (dirty read)

T1 изменила строку, но ещё не сделала COMMIT. T2 прочитала «новое» значение. T1 откатилась — T2 опиралась на данные, которых «не было».

Пример: T1 в транзакции начислила стипендию +500 и напечатала ведомость для проверки; T2 по этой сумме выдала справку; T1 сделала ROLLBACK — справка ложная.

1.3. Неповторяемое чтение (non-repeatable read)

T1 дважды читает одну и ту же строку — между чтениями T2 изменила и зафиксировала её.

Пример: T1 дважды читает RATING вуза ВГУ (UNIVERSITY_ID = 10): сначала 450, потом 470 — между чтениями другой сеанс обновил строку и сделал COMMIT.

1.4. Фантомное чтение (phantom read)

T1 дважды выполняет один и тот же запрос с условием — второй раз набор строк другой: появились или исчезли строки, подходящие под условие.

Пример: T1: SELECT COUNT(*) FROM dbo.STUDENT WHERE KURS = 1 → 4. T2 вставила нового первокурсника и сделала COMMIT. T1 повторяет COUNT → 5. «Лишняя» строка — фантом.

Потерянное обновление — две колонки T1 и T2 T1 T2 R(40) R(40) W(30) W(35) COMMIT COMMIT Итог на складе: 35, хотя списали 15 — потеряли −10 от T1

Рисунок 1. Нарисуйте такую схему на листе для любой аномалии — так проще объяснить конфликт.

2. Сводная таблица на UniversityDB

АномалияЧто ломаетсяПример в нашей БД
Потерянное обновлениеДва WRITE одного поляДва UPDATE STIPEND одного STUDENT_ID
Грязное чтениеЧтение до COMMITSELECT стипендии до отката чужой транзакции
Неповторяемое чтениеОдна строка измениласьДва SELECT RATING одного вуза
ФантомИзменился набор по условиюДва COUNT первокурсников

3. Расписание в текстовом виде

-- потерянное обновление (остаток на складе): T1: R(остаток=40) T2: R(остаток=40) T1: W(остаток=30) T2: W(остаток=35) T1: COMMIT T2: COMMIT -- грязное чтение: T1: UPDATE STIPEND … (без COMMIT) T2: SELECT STIPEND … -- видит незафиксированное T1: ROLLBACK

4. Как отличить похожие случаи

Вопрос для разбора: отчёт дважды посчитал средний балл по предмету: 4.1 и 3.9, потому что между расчётами исправили одну оценку. Это неповторяемое чтение (изменилась конкретная строка в EXAM_MARKS).

Если между двумя COUNT добавили новую ведомость (новую строку) — это фантом.

Если справку напечатали по стипендии до чужого COMMIT, а потом транзакция откатилась — грязное чтение.

5. Мини-задачи

  1. Классифицируйте: «два кассира одновременно списали товар с одного остатка» — какая аномалия?
  2. Деканат дважды запросил число студентов на 1 курсе за минуту — между запросами зачислили нового. Фантом или неповторяемое чтение?
  3. Почему на ЛР №6 все UPDATE/DELETE делают с ROLLBACK — связь с грязным чтением для соседей?

Ответы: (1) потерянное обновление; (2) фантом; (3) незафиксированные изменения не должны остаться в общей базе — откат убирает «мусор» для других сеансов.

6. Частые ошибки в понимании

ПутаютКак запомнить
Неповторяемое и фантомНеповторяемое — одна строка; фантом — другой набор строк
Грязное и неповторяемоеГрязное — читали до COMMIT; неповторяемое — после чужого COMMIT
«Транзакция = нет аномалий»Нужен ещё подходящий уровень изоляции (лекция 7)

7. Вопросы для самопроверки

  1. Нарисуйте расписание двух транзакций с потерянным обновлением.
  2. Чем грязное чтение отличается от неповторяемого?
  3. Приведите пример фантома на таблице STUDENT.
  4. Какая аномалия опаснее для печати справки о стипендии?
  5. Какую таблицу на лекции 7 заполняют уровни изоляции?
  6. Как на ЛР №6 избегают порчи эталона при UPDATE?

Итог. Четыре аномалии — словарь для обсуждения параллельного доступа. Зная названия и примеры на UniversityDB, на следующей лекции сопоставите их с уровнями изоляции SQL Server.

Лекция 7. Уровни изоляции транзакций

Дата: 13.10.2026, вт, 14:15–15:50

О чём эта лекция. Полная сериализуемость — идеал, но дорогой: транзакции будут долго ждать друг друга. SQL Server предлагает несколько уровней изоляции — осознанный компромисс между скоростью и точностью чтения.

Главная мысль одной фразой: уровень изоляции задаёт, какие аномалии допустимы; умолчание SQL Server — READ COMMITTED, для жёстких инвариантов берут REPEATABLE READ или SERIALIZABLE.

После прочтения вы сможете:

  • заполнить таблицу «уровень — какие аномалии возможны»;
  • объяснить разницу блокировок S и X на пальцах;
  • выполнить SET TRANSACTION ISOLATION LEVEL … в SSMS;
  • обосновать выбор уровня для отчёта деканата и для кассовой операции.

План занятия

Тема
Компромисс «скорость / точность»; связь с лекцией 6
Четыре уровня SQL-92 и таблица аномалий
Блокировки S и X; как уровень влияет на ожидание
SET TRANSACTION ISOLATION LEVEL в SSMS
Снимки (snapshot), SQLite, выбор уровня на практике
Мини-задачи, самопроверка, связь с ЛР №7–8

1. Зачем ослаблять полную изоляцию

На лекции 6 вы разобрали четыре аномалии параллельного доступа. Идеальный вариант — когда транзакции ведут себя так, будто выполняются строго по очереди (сериализуемость). На практике полная сериализуемость дорога: сеансы долго ждут блокировок друг друга.

Уровень изоляции — явный договор: «я согласен на часть аномалий ради скорости». Вы выбираете, какие из четырёх эффектов лекции 6 допустимы в вашем сценарии.

1.1. Пример на UniversityDB

Деканат строит отчёт «средний балл по предметам» — ему не нужны незафиксированные оценки (грязное чтение), но допустимо, что между двумя SELECT кто-то добавит новую ведомость (фантом). Кассовая операция «списать стипендию и зачислить на другой счёт» — наоборот, нужна жёсткая атомарность и минимум параллельных изменений одних строк.

2. Таблица уровней изоляции SQL-92

Стандарт SQL-92 задаёт четыре уровня. В SQL Server по умолчанию — READ COMMITTED. Столбец «потерянное обновление» — для связи с лекцией 6 (конфликт двух UPDATE одной строки).

УровеньГрязноеНеповтор.ФантомПотерянное обновление*Где применяют
READ UNCOMMITTEDдадададаГрубая оценка «на сейчас», мониторинг
READ COMMITTEDнетдадаредко**Умолчание SQL Server; обычные формы
REPEATABLE READнетнетданетДва чтения одной строки должны совпасть
SERIALIZABLEнетнетнетнетКороткие критичные операции

* Упрощённо для курса. ** При обычных блокировках строк SQL Server на READ COMMITTED два одновременных UPDATE одной строки сериализуются — второй сеанс ждёт первый.

2.1. Сопоставление с аномалиями лекции 6

Аномалия (лекция 6)Какой уровень запрещает первым
Грязное чтениеREAD COMMITTED и выше
Неповторяемое чтениеREPEATABLE READ и выше
ФантомSERIALIZABLE (или snapshot с подходящими настройками)
Потерянное обновлениеБлокировки на запись; часто достаточно READ COMMITTED
Чем выше уровень — тем меньше допустимых аномалий READ UNCOMMITTED READ COMMITTED REPEATABLE READ SERIALIZABLE все 4 аномалии − грязное − неповтор. − фантом Стрелка вправо — больше ожиданий, меньше сюрпризов в данных

Рисунок 1. Запомните порядок уровней слева направо — его часто спрашивают на самопроверке.

3. Блокировки S и X — упрощённо

СУБД реализует уровни через блокировки на строках, страницах или таблицах.

Если T1 держит X на строке STUDENT_ID = 1, T2 не сможет ни прочитать её «для изменения», ни обновить, пока T1 не сделает COMMIT или ROLLBACK.

3.1. Мини-пример: два SELECT и один UPDATE

-- сеанс 1 BEGIN TRAN; UPDATE dbo.STUDENT SET STIPEND = STIPEND + 50 WHERE STUDENT_ID = 1; -- сеанс 2 (параллельно): SELECT STIPEND FROM dbo.STUDENT WHERE STUDENT_ID = 1; -- ждёт, пока сеанс 1 не завершит транзакцию ROLLBACK TRAN; -- для учебы — откат

На READ COMMITTED второй сеанс не увидит «грязную» стипендию до COMMIT первого — но может подождать, если первый ещё держит X.

4. Команда в SQL Server

Уровень задаётся для текущего сеанса до следующего изменения:

USE UniversityDB; SET TRANSACTION ISOLATION LEVEL READ COMMITTED; -- умолчание BEGIN TRAN; SELECT AVG(CAST(MARK AS FLOAT)) AS avg_mark FROM dbo.EXAM_MARKS WHERE MARK IS NOT NULL; -- повторный SELECT в той же транзакции может дать другой результат — неповторяемое чтение COMMIT; SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; BEGIN TRAN; SELECT RATING FROM dbo.UNIVERSITY WHERE UNIVERSITY_ID = 10; SELECT RATING FROM dbo.UNIVERSITY WHERE UNIVERSITY_ID = 10; -- та же строка, тот же результат COMMIT;
Окно запроса с SET TRANSACTION ISOLATION LEVEL

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

Результат SELECT в транзакции

Результат агрегирующего SELECT — на следующей лабораторной (№7) вы считаете такие же средние без смены уровня изоляции.

4.1. Снимки (snapshot) в SQL Server

Начиная с SQL Server 2005, есть версионность строк: читатели могут видеть согласованный «снимок» на момент начала транзакции, не блокируя писателей так жёстко, как при SERIALIZABLE. Режим включают на уровне базы (ALLOW_SNAPSHOT_ISOLATION) и задают SET TRANSACTION ISOLATION LEVEL SNAPSHOT. Для длинных отчётов по UniversityDB это часто удобнее, чем максимальная блокировка.

4.2. SQLite (кратко)

В SQLite нет полного набора четырёх уровней. BEGIN DEFERRED / IMMEDIATE / EXCLUSIVE задают, когда сеанс получает право записи. Для курса основной стенд — SQL Server; SQLite упоминаем только для сравнения.

5. Как выбирать уровень на практике

СценарийРазумный выборПочему
Онлайн-форма «показать баланс стипендии»READ COMMITTEDНе показывать незафиксированные суммы
Отчёт «средний балл» на 50 страницSnapshot или READ COMMITTEDДолгое чтение не должно блокировать приём оценок
Перевод стипендии между двумя студентамиКороткая транзакция + проверкиАтомарность важнее «мягкой» изоляции чтения
Инвентаризация: два COUNT подряд должны совпастьREPEATABLE READ или вышеЗапрет неповторяемого чтения

6. Мини-задачи и частые ошибки

  1. Какой минимальный уровень запрещает грязное чтение справки о стипендии до чужого COMMIT?
  2. Два раза подряд SELECT COUNT(*) FROM dbo.STUDENT WHERE KURS = 1 дали 4 и 5. Какая аномалия и какой уровень её убирает?
  3. Зачем не ставить SERIALIZABLE «везде по умолчанию»?

Ответы: (1) READ COMMITTED; (2) фантом, SERIALIZABLE; (3) лишние ожидания и риск тупиков — тема лекции 8.

ОшибкаКак запомнить
Путают уровень изоляции и BEGIN TRANТранзакция группирует команды; уровень — правила для параллельных транзакций
Ждут, что READ COMMITTED убирает фантомыФантомы уходит только на SERIALIZABLE (или snapshot с нужной семантикой)
Меняют уровень в середине транзакцииВ SQL Server уровень лучше задавать до BEGIN TRAN

7. Вопросы для самопроверки

  1. Какой уровень изоляции по умолчанию в SQL Server?
  2. Какие аномалии допускает READ COMMITTED?
  3. Чем блокировка X несовместима с блокировкой S на одной строке?
  4. Когда отчёту достаточно snapshot, а не SERIALIZABLE?
  5. Как уровень изоляции связан с таблицей аномалий лекции 6?
  6. Зачем на ЛР №6 все изменения делали с ROLLBACK, хотя уровень по умолчанию уже READ COMMITTED?

Итог. Уровень изоляции — осознанный компромисс: вы отмечаете в таблице, какие аномалии лекции 6 допустимы. Умолчание SQL Server (READ COMMITTED) подходит для большинства учебных запросов; для жёстких инвариантов повышают уровень или используют snapshot.

Лекция 8. Блокировки, тупики, репликация

Дата: 20.10.2026, вт, 14:15–15:50

О чём эта лекция. Блокировки защищают данные, но могут привести к тупику, когда две транзакции вечно ждут друг друга. Отдельно — репликация: копирование данных на другой сервер для отчётов и резерва.

Главная мысль одной фразой: тупик — следствие конкуренции, а не «поломка СУБД»; SQL Server выбирает жертву (ошибка 1205), а репликация снимает нагрузку с основного сервера.

После прочтения вы сможете:

  • описать двухфазный протокол блокировок простыми словами;
  • назвать три правила профилактики тупиков;
  • отличить снимковую, транзакционную и merge-репликацию;
  • связать тему с ЛР №13–14 (функции, CASE, COALESCE).

План занятия

Тема
Связь блокировок с уровнями изоляции (лекция 7)
Двухфазный протокол блокировок (2PL)
Тупик на примере UniversityDB
Ошибка 1205, профилактика
Репликация — зачем и виды
Мини-задачи, самопроверка, связь с ЛР №9–14

1. От уровня изоляции к блокировкам

На лекции 7 вы выбирали уровень изоляции по таблице аномалий. Реализует это СУБД через блокировки: S на чтение, X на запись. Чем строже уровень, тем дольше блокировки держатся и тем чаще сеансы ждут друг друга.

Идея: блокировка — «бронь» на строку или страницу. Пока T1 держит X на строке STUDENT_ID = 1, T2 не может её изменить — это защита от потерянного обновления и грязного чтения.

1.1. Гранулярность

Блокировать можно строку, страницу, всю таблицу. Без индекса фильтр WHERE CITY = N'Воронеж' иногда блокирует больше строк, чем нужно — отсюда рекомендация «нужные индексы» при проектировании отчётов по STUDENT.

2. Двухфазный протокол (2PL)

Двухфазный протокол блокировок — правило, которому следуют многие СУБД:

  1. Фаза роста — транзакция только получает новые блокировки.
  2. Фаза спада — только освобождает блокировки; новых не берёт.

Строгий вариант (Strict 2PL): все X-блокировки снимаются только при COMMIT или ROLLBACK. Так гарантируется, что никто не прочитает незафиксированную запись.

2PL: сначала набираем блокировки, потом снимаем Фаза роста S, S, X — новые блокировки Фаза спада unlock, unlock → COMMIT После первого unlock новую блокировку брать нельзя

Рисунок 1. Схема 2PL — основа для понимания порядка конфликтов между транзакциями.

3. Тупик (deadlock)

Тупик — цикл ожидания: T1 держит ресурс A и ждёт B; T2 держит B и ждёт A. Без вмешательства обе транзакции зависнут навсегда.

3.1. Классический пример на UniversityDB

Два сеанса переводят стипендию между студентами, но в разном порядке блокируют строки:

-- сеанс 1 -- сеанс 2 BEGIN TRAN; BEGIN TRAN; UPDATE dbo.STUDENT UPDATE dbo.STUDENT SET STIPEND = STIPEND - 100 SET STIPEND = STIPEND - 50 WHERE STUDENT_ID = 1; WHERE STUDENT_ID = 3; -- блокировка строки 1 -- блокировка строки 3 UPDATE dbo.STUDENT UPDATE dbo.STUDENT SET STIPEND = STIPEND + 100 SET STIPEND = STIPEND + 50 WHERE STUDENT_ID = 3; -- ждёт T2 WHERE STUDENT_ID = 1; -- ждёт T1

Каждый сеанс держит «свою» строку и ждёт вторую — получается цикл. SQL Server строит граф ожидания, находит цикл и выбирает жертву.

Тупик: T1 → T2 → T1 T1 держит id=1 T2 держит id=3 ждёт строку 3 ждёт строку 1

Рисунок 2. Цикл в графе ожидания — признак тупика. СУБД откатывает одну из транзакций.

3.2. Сообщение SQL Server

Msg 1205, Level 13, State 51 Transaction (Process ID 54) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.

Код ошибки — 1205. Клиентское приложение может повторить транзакцию (обычно ограниченное число раз). На учебном сервере для демонстрации тупика нужны два окна SSMS — выполняйте только по указанию преподавателя.

Два окна запроса SSMS

Для демонстрации тупика открывают два окна New Query к одной базе — как на лекции 4 для сеансов.

4. Профилактика тупиков

ПравилоСмысл на UniversityDB
Одинаковый порядок таблицВезде сначала STUDENT, потом EXAM_MARKS — не наоборот в разных процедурах
Короткие транзакцииНе держать BEGIN TRAN, пока пользователь думает над формой
Индексы по фильтрамМеньше «широких» блокировок при WHERE UNIVERSITY_ID = …
Обработка 1205Повтор транзакции в коде приложения
Меньше лишней строгостиНе ставить SERIALIZABLE, если хватает READ COMMITTED (лекция 7)

5. Репликация

Репликация — копирование данных (или изменений) на другой сервер. Зачем: отчёты не нагружают основной сервер, резервная копия «живых» данных, филиал в другом городе.

ВидИдеяКогда уместна
СнимковаяПериодически полная копияРедко меняющиеся справочники
ТранзакционнаяПочти онлайн передача измененийАктуальная копия для чтения
Слиянием (merge)Изменения на нескольких узлах, потом сводятРаспределённые филиалы с локальной записью

Реплика не заменяет транзакции и блокировки на основном сервере — это отдельный механизм доставки данных. Связь с лекцией 4: распределённая БД может хранить студентов по регионам, репликация — один из способов синхронизации узлов.

6. Мини-задачи

  1. Две транзакции обновляют EXAM_MARKS, затем STUDENT — в разном порядке. Возможен тупик?
  2. Почему короткая транзакция с ROLLBACK на ЛР №6 снижает риск конфликтов на общем сервере?
  3. Чем транзакционная репликация отличается от снимковой по задержке данных?

Ответы: (1) да, если блокируют пересекающиеся ресурсы в разном порядке; (2) меньше времени держит X-блокировки; (3) транзакционная ближе к «онлайн», снимковая — с большим лагом между копиями.

7. Вопросы для самопроверки

  1. Опишите тупик «T1: STUDENT → EXAM_MARKS, T2: наоборот».
  2. Что означает ошибка 1205 и что должен сделать клиент?
  3. Зачем обращаться к таблицам в одном порядке во всём коде?
  4. Чем транзакционная репликация отличается от снимковой?
  5. Как блокировки связаны с уровнями изоляции лекции 7?
  6. Зачем отчёты иногда читают с реплики, а не с основного сервера?

Итог. Блокировки реализуют уровни изоляции; при неудачном порядке доступа возникает тупик — SQL Server выбирает жертву (1205). Репликация снимает нагрузку с основного узла, но не отменяет правила транзакций на master-базе.

Лекция 9. Структурированные и неструктурированные данные

Дата: 27.10.2026, вт, 14:15–15:50

О чём эта лекция. Не все данные удобно класть в таблицы с фиксированными столбцами. Разберём три «типа» данных и когда реляционная модель остаётся лучшим выбором, а когда — JSON, документы или файловое хранилище.

Главная мысль одной фразой: структурированные данные — основа курса (UniversityDB); полуструктурированные и неструктурированные требуют других моделей, но метаданные часто всё равно хранят в SQL Server.

После прочтения вы сможете:

  • привести по одному примеру каждого типа данных из жизни вуза;
  • сравнить реляционную, документную и key-value модели;
  • объяснить, зачем в БД хранят ссылку на PDF, а не сам файл;
  • назвать три «V» Big Data обзорно, без формул.

План занятия

Тема
Три типа данных на примерах вуза и UniversityDB
Модели хранения: реляционная, документная, key-value
Где хранят файлы и метаданные
Big Data — три «V» обзорно
Мини-задачи, самопроверка, связь с лекцией 10 и ЛР №17–19

1. Три типа данных

До сих пор курс опирался на структурированные данные — таблицы SQL с фиксированными столбцами. Реальная информационная система вуза смешивает и другие форматы.

1.1. Структурированные

Строки и столбцы с типами, ограничениями, связями FK. Весь эталон UniversityDB: STUDENT, EXAM_MARKS, UNIVERSITY. Запросы SELECT, GROUP BY (ЛР №7–8), подзапросы (ЛР №9–10) работают именно с такими данными.

1.2. Полуструктурированные

Есть именованные поля и вложенность, но схема гибче таблицы:

1.3. Неструктурированные

Нет фиксированной таблицы полей: PDF заявления, фото студбилета, видеолекция. В SQL Server обычно хранят метаданные (имя файла, дата, автор, ссылка), а сам файл — в файловом или объектном хранилище (S3, SharePoint, сетевой диск).

Спектр «структурированности» Структурированные таблицы SQL Полуструктурированные JSON, XML Неструктурированные PDF, видео, фото Курс начинается слева; XML и MongoDB — середина и правая часть семестра

Рисунок 1. UniversityDB — левый столбец; к концу семестра добавятся XML и документная MongoDB.

2. Модели хранения

МодельПример СУБДКак выглядитКогда уместна
РеляционнаяSQL ServerТаблицы, FK, JOINУчёт, отчёты, строгие связи (оценки ↔ студенты)
ДокументнаяMongoDBДокумент JSON/BSONГибкая схема, вложенные объекты (анкета с разным числом полей)
Иерархическая / XMLXML в SQL ServerДерево элементовОбмен между системами, XSD-контракт
Key-ValueRedisКлюч → значениеКэш сессий, счётчики, очереди

2.1. Почему не «всё в MongoDB»

Отчёт «средний балл по кафедрам с JOIN трёх таблиц» на нормализованной схеме проще и надёжнее в SQL. Документная модель хороша, когда структура записи часто меняется или глубоко вложена — например, черновик анкеты абитуриента с опциональными блоками.

Гибрид: основные учётные данные — SQL Server; кэш или лог — Redis; обмен — XML; прототип мобильного приложения — MongoDB (ЛР №19).

3. Файлы и метаданные в БД

Хранить большой PDF в столбце VARBINARY(MAX) можно, но на практике:

Типичная схема: таблица DocumentMeta(FileId, StudentId, FileName, StoredAt, StorageUrl) — структурированные метаданные; путь или URL — на неструктурированный файл снаружи.

3.1. Пример JSON рядом с SQL

-- гипотетический столбец NVARCHAR(MAX) с JSON (SQL Server 2016+): -- {"studentId": 19, "contacts": [{"type": "email", "value": "..."}]} -- извлечение: JSON_VALUE(col, '$.studentId')

На ЛР №17 вы загрузите настоящий XML в тип XML — это полуструктурированные данные внутри реляционной СУБД.

4. Big Data — обзорно

Когда данных слишком много для одного SQL Server на одном диске, говорят о Big Data. Три «V» (без формул на экзамене — только смысл):

«V»СмыслПример
Volume (объём)Терабайты и большеЛоги посещаемости LMS за годы
Velocity (скорость)Поток данных в реальном времениДатчики, клики на портале
Variety (разнообразие)Разные форматы одновременноТаблицы + JSON + видео

Для учебной UniversityDB (19 студентов, 24 оценки) достаточно одного SQL Server. Big Data — контекст, зачем в индустрии появляются Hadoop, Spark, озёра данных.

5. Мини-задачи

  1. Классифицируйте: строка в EXAM_MARKS, JSON расписания, скан диплома.
  2. Зачем оценки хранить в таблице, а не в JSON-файле на диске?
  3. Когда документная БД лучше новой таблицы «на каждый тип анкеты»?

Ответы: (1) структурированные, полуструктурированные, неструктурированные (+ метаданные в SQL); (2) целостность FK, транзакции, отчёты GROUP BY; (3) когда набор полей у записей сильно различается.

6. Вопросы для самопроверки

  1. Приведите пример структурированных данных из UniversityDB.
  2. Где в вузе встречаются полуструктурированные JSON или XML?
  3. Почему скан PDF хранят в файловом хранилище, а не в VARBINARY «на всякий случай»?
  4. Когда MongoDB уместнее, чем новая таблица в SQL Server?
  5. Чем полуструктурированные данные отличаются от структурированных в нашей таблице «три типа»?
  6. Как тема лекции связана с ЛР №9–10, если там снова SQL по таблицам?

Итог. Структурированные таблицы — основа курса и большинства учётных систем вуза. Полуструктурированные и неструктурированные данные требуют других инструментов, но метаданные о них часто всё равно лежат в SQL Server.

Лекция 10. Язык XML

Дата: 03.11.2026, вт, 14:15–15:50

О чём эта лекция. XML — стандарт обмена иерархическими данными между системами. Разберём синтаксис, отличие well-formed от valid документа и как SQL Server хранит XML в столбце типа XML.

Главная мысль одной фразой: XML описывает дерево элементов и атрибутов; XSD задаёт правила, а XPath и методы .value() / .query() извлекают нужные узлы прямо в T-SQL.

После прочтения вы сможете:

  • прочитать простой XML-документ и назвать корневой элемент;
  • объяснить, зачем нужна XSD-схема при обмене с банком или госсистемой;
  • написать фрагмент XPath для имени вуза;
  • сравнить XML и JSON для веб-API.

План занятия

Тема
Синтаксис XML: элементы, атрибуты, пролог
Well-formed и valid; роль XSD
XPath на примере вуза и студентов
Тип XML в SQL Server: .value(), .query()
XML vs JSON; мини-задачи, связь с ЛР №17

1. Зачем XML в курсе управления данными

На лекции 9 вы разделили данные на структурированные таблицы и полуструктурированные форматы. XML — один из стандартов обмена иерархическими данными между организациями: банк, деканат, госуслуги могут требовать файл по XSD-схеме, а не «произвольный Excel».

UniversityDB остаётся реляционной; XML понадобится, когда нужно передать фрагмент данных (список студентов вуза) в систему партнёра или сохранить документ в столбце XML рядом с ключами SQL.

2. Базовый синтаксис

<?xml version="1.0" encoding="UTF-8"?> <University id="22"> <Name>МГУ</Name> <City>Москва</City> <Student id="2" kurs="1"> <Surname>Сидорова</Surname> <Stipend>200</Stipend> </Student> </University>
XML — дерево элементов University Name City Student Атрибут id на элементе — не отдельная «ветка» дерева

Рисунок 1. Корень, дочерние элементы и атрибут — базовая модель для XPath.

3. Well-formed и valid

ПроверкаЧто смотритПример ошибки
Well-formedСинтаксис: закрытые теги, одна корневая вершина<Name>МГУ<City>… без закрытия
ValidСоответствие XSD/DTD: обязательные поля, типыНет атрибута id у University

Парсер SQL Server при вставке в XML сначала проверяет well-formed. Valid — ответственность обмена: партнёр отклонит файл, не прошедший XSD.

3.1. Фрагмент XSD

<xs:element name="University"> <xs:complexType> <xs:sequence> <xs:element name="Name" type="xs:string"/> <xs:element name="Student" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute name="id" type="xs:int" use="required"/> </xs:complexType> </xs:element>

maxOccurs="unbounded" — сколько угодно студентов; use="required" — атрибут id обязателен.

4. XPath — навигация по дереву

XPath — язык путей к узлам. Примеры для документа выше:

XPathРезультат
/University/NameЭлемент с названием вуза
/University/Student[@kurs='1']Студенты первого курса
//StudentВсе элементы Student на любой глубине
(/University/Name)[1]Первый Name (для .value() в SQL)

5. XML в SQL Server

Столбец типа XML хранит документ внутри таблицы. Основные методы T-SQL:

DECLARE @x XML = N'<University id="22"><Name>МГУ</Name></University>'; SELECT @x.value('(/University/Name)[1]', 'NVARCHAR(80)') AS univ_name; SELECT @x.query('/University/Name');

.value() — одно скалярное значение (как подзапрос с одной строкой). .query() — фрагмент XML (несколько узлов). На ЛР №17 вы создадите таблицу dbo.UnivXml и загрузите похожий документ.

Окно запроса с XML

Окно New Query: переменная типа XML и метод .value().

5.1. XML и JSON

КритерийXMLJSON
Типичное применениеБанки, госсистемы, старые интеграцииREST API, веб и мобильные клиенты
СхемаXSD, строгий контрактJSON Schema (реже в старых системах)
В SQL ServerТип XML, XPathOPENJSON, JSON_VALUE (2016+)

6. Мини-задачи

  1. Исправьте: <Student>Иванов<Stipend>150</Student> — что не так?
  2. Каким XPath прочитать атрибут id у University?
  3. Зачем хранить XML в типе XML, а не в NVARCHAR(MAX)?

Ответы: (1) не закрыт Stipend; (2) (/University/@id)[1]; (3) проверка well-formed, индексы, методы XPath.

7. Вопросы для самопроверки

  1. Чем элемент XML отличается от атрибута на примере <Student id="101">?
  2. Что проверяет well-formed парсер, а что — valid по XSD?
  3. Зачем в SQL Server столбец типа XML, если есть NVARCHAR?
  4. Почему в REST-API чаще JSON, а в банковском обмене — XML?
  5. Как XPath связан с методом .value() на ЛР №17?

Итог. XML описывает дерево данных; XSD задаёт контракт; SQL Server хранит документы в типе XML и извлекает поля через XPath. Это мост от реляционной UniversityDB к полуструктурированному обмену.

Лекция 11. Администрирование и мониторинг СУБД

Дата: 17.11.2026, вт, 12:30–14:05

О чём эта лекция. База данных живёт на сервере годами — нужен человек (или команда), который следит за доступностью, резервными копиями, правами и производительностью. Это задачи администратора БД.

Главная мысль одной фразой: экземпляр SQL Server содержит системные и пользовательские базы; мониторинг через SSMS и динамические представления показывает, чего ждут запросы и где узкое место.

После прочтения вы сможете:

  • перечислить системные базы и роль master, tempdb;
  • объяснить, зачем перестраивать индексы и запускать DBCC CHECKDB;
  • прочитать столбец wait_type в sys.dm_exec_requests;
  • связать администрирование с ЛР №19–20 и лекциями о резервном копировании.

План занятия

Тема
Роль DBA; что уже делали на ЛР №1
Экземпляр SQL Server, системные базы, файлы .mdf/.ldf
Модели восстановления SIMPLE / FULL
Мониторинг: Activity Monitor, sys.dm_exec_requests
Обслуживание, самопроверка, связь с лекциями 13–14

1. Зачем нужен администратор БД

На ЛР №1 вы подключались к SQL Server и создавали UniversityDB. База будет жить на сервере месяцами: её нужно копировать, защищать, наблюдать и чинить после сбоев.

Администратор баз данных (DBA) отвечает за:

Разработчик пишет запросы; DBA следит, чтобы сервер выдержал нагрузку и данные не пропали. На маленькой учебной базе роли часто совмещают — но различать их полезно.

2. Экземпляр и файлы базы

Экземпляр (instance) — одна установленная служба SQL Server на машине. В Object Explorer вы видите экземпляр → базы данных.

БазаНазначение
masterМетаданные сервера: логины, список баз
msdbЗадания SQL Server Agent, история бэкапов
tempdbВременные объекты; пересоздаётся при перезапуске
modelШаблон для новых баз
UniversityDBПользовательская учебная база
Системные базы данных в SSMS

Object Explorer → System Databases: master, model, msdb, tempdb. Пользовательские базы (в т.ч. UniversityDB) — в том же узле Databases.

У UniversityDB два основных файла: .mdf (данные) и .ldf (журнал транзакций). Журнал — тема лекций 5–8; без него нельзя надёжно восстанавливать базу в модели FULL.

2.1. Модель восстановления

SIMPLE — журнал усечён автоматически; point-in-time restore ограничен. FULL — нужен для цепочки BACKUP LOG и восстановления «на минуту». Подробно — лекция 13.

3. Мониторинг в SSMS

Activity Monitor (правый клик на экземпляре) показывает:

Для текстового отчёта — динамическое представление sys.dm_exec_requests:

SELECT r.session_id, r.status, r.wait_type, r.blocking_session_id, SUBSTRING(t.text, 1, 200) AS query_text FROM sys.dm_exec_requests r CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t WHERE r.session_id > 50;

wait_type — чего ждёт запрос: PAGEIOLATCH (диск), LCK_M_* (блокировка), NETWORKIO (сеть). Если отчёт по JOIN трёх таблиц «висит», здесь видна причина.

Activity Monitor открывают правым кликом по имени экземпляра в Object Explorer (тот же узел, что на рисунке в §2).

4. Плановое обслуживание

ДействиеЗачем
Перестроение / реорганизация индексовТочный план запроса, меньше Scan
Обновление статистикиОптимизатор правильно оценивает число строк
DBCC CHECKDBПроверка целостности страниц файлов
Резервное копирование по расписаниюSQL Server Agent (обзорно)

На учебном сервере не работайте под sa без необходимости и не запускайте CHECKDB в часы сдачи лабораторных без согласования.

5. Мини-задачи

  1. Какая системная база хранит расписание заданий Agent?
  2. Чем файл .ldf связан с транзакциями лекции 5?
  3. Почему DBA смотрит blocking_session_id вместе с wait_type?

Ответы: (1) msdb; (2) журнал фиксирует изменения до COMMIT; (3) блокировка — частая причина ожидания при параллельных UPDATE.

6. Вопросы для самопроверки

  1. Назовите четыре системные базы SQL Server и их роль.
  2. Что покажет wait_type = PAGEIOLATCH?
  3. Зачем запускать DBCC CHECKDB по расписанию?
  4. Чем модель FULL отличается от SIMPLE для резервного копирования?
  5. Как администрирование связано с ЛР №23–24?

Итог. SQL Server — не только «место для таблиц», а управляемый сервис с системными базами, журналом и инструментами мониторинга. Администрирование делает учебную UniversityDB пригодной для реальной эксплуатации.

Лекция 12. Программирование в БД: процедуры, триггеры

Дата: 24.11.2026, вт, 12:30–14:05

О чём эта лекция. Часть логики можно перенести на сервер: представления, хранимые процедуры и триггеры выполняются рядом с данными — меньше трафика и единые правила для всех клиентов.

Главная мысль одной фразой: VIEW прячет сложный JOIN; процедура параметризует запрос; триггер реагирует на INSERT/UPDATE/DELETE — AFTER после изменения, INSTEAD OF вместо него.

После прочтения вы сможете:

  • объяснить плюсы CREATE VIEW для пользователя отчётов;
  • прочитать процедуру usp_StudentByKurs и вызвать её в SSMS;
  • различить триггеры AFTER и INSTEAD OF;
  • понять разницу Index Seek и Index Scan на плане запроса.

План занятия

Тема
VIEW — зачем прятать JOIN
Хранимые процедуры и EXEC
Триггеры AFTER и INSTEAD OF
План запроса: Seek vs Scan
Индексы, самопроверка, связь с ЛР №20–22

1. Представление VIEW

На ЛР №11 вы писали длинный JOIN «студент + вуз + оценки». Пользователю отчётов неудобно каждый раз повторять связи — им нужна «виртуальная таблица» с понятными столбцами.

VIEW — сохранённый SELECT с именем. Данные не копируются: при SELECT * FROM v_StudentUniv сервер выполняет запрос из определения VIEW.

CREATE VIEW dbo.v_StudentUniv AS SELECT s.STUDENT_ID, s.SURNAME, s.KURS, u.UNIVERSITY_NAME, u.CITY FROM dbo.STUDENT s JOIN dbo.UNIVERSITY u ON s.UNIVERSITY_ID = u.UNIVERSITY_ID;

Не путать с таблицей: в Object Explorer VIEW лежит в папке Views; INSERT в простой VIEW с JOIN обычно невозможен — помогает триггер INSTEAD OF (ЛР №22).

2. Хранимая процедура

Процедура — программа T-SQL на сервере с параметрами. Один вызов EXEC вместо копирования текста запроса в каждое приложение.

CREATE PROC dbo.usp_StudentByKurs @kurs INT AS BEGIN SET NOCOUNT ON; SELECT STUDENT_ID, SURNAME, KURS FROM dbo.STUDENT WHERE KURS = @kurs; END;

Плюсы: меньше сетевого трафика; единая логика; можно выдать GRANT EXECUTE без права SELECT на таблицу (ЛР №23).

3. Триггеры DML

Триггер — код, который SQL Server запускает при INSERT, UPDATE или DELETE.

ТипКогдаПример
AFTERПосле изменения строкАудит в AuditLog
INSTEAD OFВместо операцииINSERT через VIEW с JOIN

Внутри триггера доступны псевдотаблицы inserted (новые значения) и deleted (старые). На ЛР №22 вы запишете изменения в EXAM_MARKS и запретите понижение оценки.

4. План выполнения и индексы

В 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 сделайте свой.

5. Мини-задачи

  1. Обновится ли VIEW, если изменить фамилию в STUDENT?
  2. Зачем SET NOCOUNT ON в процедуре?
  3. Чем триггер отличается от CHECK на столбце MARK?

Ответы: (1) да, VIEW показывает актуальные данные; (2) не слать клиенту «(N rows affected)» на каждый внутренний SELECT; (3) триггер может писать в другую таблицу и откатывать транзакцию.

6. Вопросы для самопроверки

  1. Чем VIEW отличается от копии таблицы?
  2. Зачем вызывать usp_StudentByKurs, если можно написать тот же SELECT?
  3. Когда нужен INSTEAD OF, а не AFTER?
  4. Почему функция в WHERE мешает Index Seek?
  5. Как программирование в БД связано с администрированием (лекция 11)?

Итог. VIEW, процедуры и триггеры переносят логику на сервер рядом с данными — меньше дублирования в приложениях и единые правила для всех клиентов SSMS.

Лекция 13. Резервное копирование

Дата: 01.12.2026, вт, 14:15–15:50

О чём эта лекция. Диск может выйти из строя, студент может ошибочно выполнить DELETE, ransomware шифрует файлы — без резервной копии данные не вернуть. Разберём виды backup в SQL Server и правило 3-2-1.

Главная мысль одной фразой: полная, разностная копия и журнал транзакций образуют цепочку восстановления; модель FULL позволяет восстановиться на минуту, SIMPLE — только до последней полной копии.

После прочтения вы сможете:

  • расшифровать RPO и RTO на примере деканата;
  • написать команду BACKUP DATABASE и BACKUP LOG;
  • объяснить правило 3-2-1 своими словами;
  • связать тему с ЛР №23–24.

План занятия

Тема
Зачем копировать: сценарии потери данных
RPO и RTO на примере деканата
FULL, DIFF, LOG backup
Модели SIMPLE и FULL
Правило 3-2-1, SQLite, связь с ЛР №24

1. Зачем резервные копии

На ЛР №6 вы делали UPDATE и DELETE. Одна ошибка в WHERE без транзакции может стереть половину EXAM_MARKS. Диск выходит из строя, ransomware шифрует .mdf — без копии восстановить нельзя.

Резервная копия — не «галочка для отчёта», а часть RPO/RTO: сколько данных можно потерять и как быстро поднять сервис.

2. RPO и RTO

МетрикаВопросПример
RPOСколько истории можно потерять?«Не больше 1 часа ведомости» → бэкап лога каждый час
RTOКак быстро снова работать?«Деканат открыт через 4 часа после сбоя»

3. Виды копий SQL Server

ТипСодержимоеФайл (пример)
FULLВся база целикомuniv_full.bak
DIFFERENTIALИзменения с последней FULLuniv_diff.bak
LOGЗаписи журнала транзакцийuniv_log.trn
BACKUP DATABASE UniversityDB TO DISK = N'D:\bak\univ_full.bak' WITH INIT, COMPRESSION, STATS = 10; BACKUP DATABASE UniversityDB TO DISK = N'D:\bak\univ_diff.bak' WITH DIFFERENTIAL; BACKUP LOG UniversityDB TO DISK = N'D:\bak\univ_log.trn';

Цепочка FULL → DIFF → LOG позволяет восстановиться на конкретную минуту — только в модели восстановления FULL (лекция 11).

4. SIMPLE vs FULL

SIMPLE — журнал усекается автоматически; point-in-time restore ограничен. FULL — нужен для регулярного BACKUP LOG и STOPAT на лекции 14.

4.1. Правило 3-2-1

Три копии данных, на двух носителях, одна копия вне площадки (облако, другой офис).

4.2. SQLite (если работаете локально)

Файл .db копируют, когда нет записи. «Горячая» копия — VACUUM INTO 'backup.db'. Копирование файла во время активной записи без WAL рискованно.

5. Вопросы для самопроверки

  1. Чем FULL backup отличается от DIFFERENTIAL?
  2. Зачем BACKUP LOG в модели FULL?
  3. Что означает RPO = 1 час для деканата?
  4. Почему копию пробуют восстанавливать на тестовом сервере?
  5. Как резервное копирование связано с журналом транзакций (лекция 5)?

Итог. Стратегия бэкапов выбирается от RPO/RTO; без проверенного восстановления копия не даёт уверенности.

Лекция 14. Восстановление данных и защита

Дата: 08.12.2026, вт, 12:30–14:05

О чём эта лекция. Резервная копия бесполезна, если вы ни разу не пробовали восстановление. Разберём порядок RESTORE, восстановление на момент времени и параллельно — права доступа: login, user, role, GRANT.

Главная мысль одной фразой: NORECOVERY накатывает цепочку файлов, RECOVERY открывает базу; при логической ошибке поднимают копию рядом и переносят нужные строки, а не откатывают всю боевую базу.

После прочтения вы сможете:

  • перечислить шаги RESTORE из full + diff + log;
  • объяснить параметр STOPAT;
  • различить login и user в SQL Server;
  • сформулировать принцип минимальных привилегий для ФИО в UniversityDB.

План занятия

Тема
Цепочка RESTORE: NORECOVERY / RECOVERY
STOPAT — откат ошибочного DELETE
Логическая ошибка: копия «рядом»
Login, user, role, GRANT/REVOKE
Персональные данные в UniversityDB

1. Порядок восстановления

Копия бесполезна, если вы ни разу не делали RESTORE. Общий порядок:

  1. Последняя полная копия — с NORECOVERY.
  2. Последняя разностная (если есть) — с NORECOVERY.
  3. Цепочка файлов журнала — последний шаг с RECOVERY.
RESTORE DATABASE UniversityDB FROM DISK = N'D:\bak\univ_full.bak' WITH NORECOVERY, REPLACE; RESTORE DATABASE UniversityDB FROM DISK = N'D:\bak\univ_diff.bak' WITH NORECOVERY; RESTORE LOG UniversityDB FROM DISK = N'D:\bak\univ_log.trn' WITH RECOVERY;

NORECOVERY оставляет базу в режиме «ещё накатываем файлы». RECOVERY открывает базу для работы.

2. Восстановление на момент времени

RESTORE LOG UniversityDB FROM DISK = N'univ_log.trn' WITH RECOVERY, STOPAT = '2026-12-08 10:14:00';

Если в 10:15 выполнили ошибочный DELETE FROM EXAM_MARKS WHERE …, а цепочка лога сохранена — можно откатиться на секунду до ошибки.

2.1. Логическая ошибка

Если после ошибки уже наработали новые данные, не откатывайте всю боевую базу на вчера. Поднимите копию рядом (UniversityDB_restore), вытащите нужные строки, вставьте в основную базу — так делают на ЛР №24.

3. Защита доступа

Login — учётная запись на уровне сервера. User — сопоставление login внутри базы. Role — набор прав для группы пользователей.

CREATE ROLE role_read; GRANT SELECT ON dbo.STUDENT TO role_read; GRANT SELECT ON dbo.UNIVERSITY TO role_read; REVOKE DELETE ON dbo.EXAM_MARKS FROM role_read;

Принцип минимальных привилегий: только то, что нужно для работы. В UniversityDB есть ФИО и даты рождения — персональные данные; в проекте нужна политика доступа и аудит (триггер на ЛР №22).

4. Вопросы для самопроверки

  1. Зачем первый RESTORE с NORECOVERY?
  2. Как STOPAT помогает после ошибочного DELETE?
  3. Чем login отличается от user внутри базы?
  4. Зачем REVOKE DELETE на EXAM_MARKS для роли «читатель»?
  5. Почему GRANT EXECUTE на процедуру безопаснее SELECT на всю таблицу?

Итог. Восстановление и права — две стороны надёжности: данные можно вернуть, а доступ — ограничить.

Лекция 15. Распределённые БД и двухфазная фиксация

Дата: 15.12.2026, вт, 12:30–14:05

О чём эта лекция. Возвращаемся к распределённым системам на уровне протоколов: как согласовать COMMIT на двух серверах с помощью двухфазной фиксации (2PC) и зачем фрагментировать таблицы по регионам.

Главная мысль одной фразой: 2PC — «сначала спроси всех, готовы ли зафиксировать, потом COMMIT или ROLLBACK всем»; это цена масштаба распределённой БД.

После прочтения вы сможете:

  • назвать три архитектуры доступа к данным (файл-сервер, клиент–сервер, трёхуровневая);
  • описать фазы prepare и commit в 2PC;
  • отличить горизонтальную и вертикальную фрагментацию;
  • сопоставить репликацию с темой лекции 8.

План занятия

Тема
Распределённая БД — повторение лекции 4
Архитектуры доступа к данным
Репликация (связь с лекцией 8)
Двухфазная фиксация 2PC
Фрагментация, компромиссы

1. Логически единая БД на нескольких узлах

Студенты ВГУ в Воронеже, филиал в другом городе — данные могут лежать на разных серверах, но приложение видит одну базу. Важна прозрачность: разработчик пишет обычный SQL, система направляет запрос на нужный узел.

2. Архитектуры

  1. Файл-сервер — клиент читает файл целиком (устарело, плохо масштабируется).
  2. Клиент–сервер — клиент шлёт SQL, сервер возвращает строки (наш SSMS + UniversityDB).
  3. Трёхуровневая — браузер → сервер приложений → СУБД.

3. Репликация

ВидКогда
СнимокРедко меняющиеся справочники вузов
ТранзакционнаяОтчёты с копии, минимальная задержка
СлияниемФилиалы с автономной работой офлайн

Связь с лекцией 8: реплика — способ масштабировать чтение и повышать доступность.

4. Двухфазная фиксация (2PC)

Одна бизнес-операция затрагивает два узла (списание и зачисление на разных серверах). Протокол:

  1. Prepare: координатор спрашивает участников «готовы зафиксировать?»
  2. Commit: если все «да» — COMMIT всем; иначе ROLLBACK всем.

Минус: при сбое координатора участники могут долго ждать. Для курса достаточно понимать идею согласованности vs доступности.

4.1. Фрагментация

Горизонтальная — строки по регионам (STUDENT Москвы на узле A). Вертикальная — редкие столбцы на отдельном узле. Цель — баланс нагрузки и близость к пользователю.

5. Вопросы для самопроверки

  1. Опишите две фазы 2PC своими словами.
  2. Когда merge-репликация уместнее транзакционной?
  3. Чем горизонтальная фрагментация отличается от вертикальной?
  4. Почему распределённость усложняет согласованность?
  5. Как тема связана с транзакциями ACID (лекция 5)?

Итог. Распределённые системы — продолжение многопользовательского режима и репликации; 2PC — цена согласованности на нескольких узлах.

Лекция 16. Хранилища данных и подготовка к экзамену

Дата: 15.12.2026, вт, 14:15–15:50

О чём эта лекция. Завершение курса: чем операционная база (OLTP) отличается от аналитической (OLAP), что такое хранилище данных и Data Mining — и как подготовиться к экзамену по материалам семестра.

Главная мысль одной фразой: UniversityDB учит оперативному учёту; хранилище и OLAP отвечают на вопросы «как менялось за годы», а экзамен проверяет связное понимание модели, SQL и надёжности.

После прочтения вы сможете:

  • сравнить OLTP и OLAP по цели, схеме и нагрузке;
  • объяснить схему «звезда» и роли фактов и измерений;
  • назвать три задачи Data Mining без формул;
  • составить план повторения перед экзаменом (лекции + ЛР №1–24).

План занятия

Тема
OLTP vs OLAP на примере UniversityDB
Хранилище данных, схема «звезда»
Data Mining — три задачи без формул
Итоги семестра
Формат экзамена и план повторения

1. OLTP и OLAP

OLTP (UniversityDB)OLAP / DWH
ЦельВыставить оценку, изменить стипендию«Как менялся средний балл по городам за 5 лет»
Схема3НФ, много JOIN«Звезда»: факты + измерения
НагрузкаКороткие INSERT/UPDATEТяжёлые отчёты, сканы
ИсторияТекущее состояниеСнимки за годы, ETL

Факт — измеримое событие (оценка, сумма). Измерение — контекст (время, предмет, вуз). Операции OLAP-куба: срез, детализация, свёртка.

2. Хранилище данных

DWH собирает данные из учётных систем (ETL). Схема «звезда»: центральная таблица фактов (FactExam), вокруг — справочники (DimStudent, DimSubject, DimDate). Витрины — готовые срезы для конкретного отдела.

3. Data Mining

4. Итоги курса

Цепочка семестра: модель и нормализацияSQL и JOINтранзакции и блокировкиXML, иерархии, MongoDBVIEW, процедуры, триггерыбэкап, права, аналитика.

UniversityDB — сквозной пример от CREATE TABLE до GRANT и RESTORE.

5. Экзамен

24 контрольных вопроса и билеты — на странице «Экзамен»; учебный план — на вкладке «Учебный план».

Типичные темы SQL: подзапросы, JOIN, GROUP BY, EXISTS, NULL, VIEW.

6. Вопросы для самопроверки

  1. Чем OLTP-нагрузка UniversityDB отличается от OLAP-отчёта?
  2. Что такое факт и измерение в схеме «звезда»?
  3. Назовите три типа задач Data Mining из лекции.
  4. Какие три темы SQL чаще встречаются на экзамене?
  5. Какой лабораторной работой завершается семестр?

Итог. Курс связал проектирование, SQL, надёжность и аналитику. Перед экзаменом пройдите учебный план, страницу экзамена (контрольные вопросы + билеты) и повторите ЛР №1–24 на UniversityDB.

Лабораторная работа №1. SSMS: системные и учебные БД

Дата: 15.09.2026, 19:30–21:05, ауд. 102 · Отчёт: скриншоты + скрипт lab01_FIO.sql (ФИО латиницей).

Цель: впервые открыть SQL Server Management Studio (SSMS), подключиться к серверу в классе, разобраться с системными и пользовательскими базами, создать UniversityDB.

0. Перед началом

  1. Запустите SQL Server Management Studio из меню Пуск (можно набрать в поиске «SSMS»).
Запуск SQL Server Management Studio из меню Пуск

SQL Server Management Studio (SSMS) в меню Пуск — Microsoft SQL Server Tools.

1. Подключение к серверу

  1. В окне Connect to Server: Server type = Database Engine.
  2. Server name — как указал преподаватель (примеры: (local), .\SQLEXPRESS, ИМЯ-ПК\SQLEXPRESS).
  3. Authentication — Windows или SQL Server Authentication (логин/пароль выдаёт преподаватель).
  4. Нажмите Connect. Если ошибка — не «переустанавливайте», а поднимите руку.
Connect to Server в SSMS

Рисунок 1. Окно Connect to Server в SSMS.

2. Обзор Object Explorer

  1. Слева найдите узел Databases.
  2. Разверните System Databases. Запишите в отчёт, что видите: master, model, msdb, tempdb.
  3. Своими словами (2–3 предложения): зачем нужны master и tempdb.
  4. Посмотрите список обычных (пользовательских) баз — есть ли уже UniversityDB или базы других групп.
Системные базы данных в SSMS

Рисунок 2. Узел System Databases в Object Explorer (скриншот SSMS).

Системные базы и чужие учебные базы не удаляйте без разрешения преподавателя.

3. Создание UniversityDB

Если база UniversityDB уже есть от прошлой попытки — согласуйте с преподавателем: использовать её или создать UniversityDB_Фамилия.

  1. Способ А: правый клик Databases, New Database…, имя UniversityDB, OK.
  2. Способ Б: New Query, выполнить:
CREATE DATABASE UniversityDB;
  1. Обновите список баз (F5). Убедитесь, что UniversityDB появилась.
  2. Правый клик на UniversityDBProperties — вкладка Files: запишите путь к файлам .mdf и .ldf.
Создание базы данных в SSMS

Создание базы: New Database… или CREATE DATABASE.

Свойства базы данных

Рисунок 3. Свойства базы — путь к файлам .mdf и .ldf (вкладка Files).

4. Первые запросы

  1. New Query. В выпадающем списке баз выберите UniversityDB.
  2. Выполните и сохраните результат в отчёт:
SELECT DB_NAME() AS current_database; SELECT @@VERSION AS sql_server_version;
  1. Ответьте: SQL Server Management Studio (SSMS) — это СУБД или клиент? Где физически лежат данные вашей базы — в SQL Server Management Studio (SSMS) или на диске сервера?
  2. Сохраните все команды в файл lab01_FIO.sql (ФИО латиницей).

На всех лабораторных имя файла: labNN_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab01_IvanovII.sql.

Окно запроса T-SQL

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

Результат выполнения запроса

Рисунок 4. Результат выполнения запроса в панели Results.

5. Дополнительно (если остаётся время)

  1. В Object Explorer откройте SecurityLogins: сколько учётных записей видно? Зачем администратору отдельные login и user в базе?
  2. Выполните SELECT name, database_id, create_date FROM sys.databases ORDER BY name; — найдите в списке свою UniversityDB.
  3. Создайте черновик ER-диаграммы на бумаге: три сущности «ВУЗ», «Студент», «Предмет» и связи между ними (без SQL — подготовка к ЛР №2).
  4. Кратко (3 предложения): чем ваш UniversityDB отличается от файла Excel с тем же списком студентов.

Контрольные вопросы

  1. Что произойдёт, если закрыть SQL Server Management Studio (SSMS) без сохранения файла lab01_FIO.sql (ФИО латиницей), но после CREATE DATABASE?

Лабораторная работа №2. Таблицы и первый SELECT

Дата: 16.09.2026, ср, 19:30–21:05, ауд. 104 · Отчёт: скрипт lab02_FIO.sql (ФИО латиницей) + скриншоты результатов запросов.

Цель: в уже созданной на ЛР №1 пустой базе UniversityDB создать таблицы учебного эталона, загрузить данные и выполнить первые запросы SELECT.

0. Перед началом

  1. Запустите SSMS и подключитесь к серверу (как на ЛР №1).
  2. В Object Explorer откройте UniversityDBTables. Список пользовательских таблиц должен быть пуст (или только системные).
  3. New Query, в списке баз выберите UniversityDB, выполните:
USE UniversityDB; SELECT DB_NAME() AS current_database;

Если базы нет — вернитесь к ЛР №1 или выполните CREATE DATABASE UniversityDB;.

1. Где взять команды SQL

Готовые команды CREATE TABLE и INSERT — на странице Приложение: БД и скрипты, раздел «Сборка базы по шагам». Там же объяснено, что такое SQL-скрипт и зачем он разбит на блоки.

На этой лабораторной вы не скачиваете файл — копируете блоки в окно запроса и сохраняете свою версию как lab02_FIO.sql (ФИО латиницей).

Блок в приложенииНужен на ЛР №2?Что делает
1. База данныхчастичноДостаточно USE UniversityDB; — база уже есть
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 заново.

2. Создание таблиц (блоки 3–5)

  1. Откройте New Query, убедитесь, что выбрана UniversityDB.
  2. Скопируйте из приложения блок 3 (UNIVERSITY и SUBJECT), выполните F5. Должно быть сообщение об успешном создании.
  3. То же с блоком 4 (STUDENT, LECTURER) и блоком 5 (EXAM_MARKS, SUBJ_LECT, ORG_UNIT).
  4. Обновите Object Explorer (F5). Под UniversityDBTables должны появиться семь таблиц.
  5. Проверьте: правый клик на dbo.STUDENTDesign — видны столбцы STUDENT_ID, UNIVERSITY_ID, значок ключа у PK и FK.
Если CREATE TABLE завершился ошибкой «foreign key» — вы, скорее всего, перепутали порядок блоков. Сначала родитель (UNIVERSITY), потом дочерние таблицы.

3. Загрузка данных (блок 6)

Вставляйте блоки 6.1 → 6.7 по порядку из приложения (сначала вузы и предметы, в конце — подразделения). Можно выполнить весь блок 6 целиком или по частям — главное не нарушать порядок таблиц.

Контрольная проверка:

SELECT COUNT(*) AS student_count FROM dbo.STUDENT; SELECT COUNT(*) AS university_count FROM dbo.UNIVERSITY;

В ответе должно быть 19 студентов и 8 вузов. Сохраните скриншот результата для отчёта.

4. Первые запросы SELECT

SELECT читает данные из таблиц; он ничего не меняет. Выполните запросы ниже по очереди, результаты — в отчёт.

4.1. Все столбцы справочника вузов

Звёздочка * означает «все столбцы строки»:

SELECT * FROM dbo.UNIVERSITY;

В результате — 8 строк, столбцы UNIVERSITY_ID, UNIVERSITY_NAME, RATING, CITY.

4.2. Только название и город

Список столбцов через запятую — это проекция (выбор нужных полей):

SELECT UNIVERSITY_NAME, CITY FROM dbo.UNIVERSITY;

4.3. Студенты одного вуза

Условие WHERE отбирает строки. Номер 10 — это ВГУ в эталонных данных:

SELECT NAME, SURNAME, KURS FROM dbo.STUDENT WHERE UNIVERSITY_ID = 10 ORDER BY SURNAME;

В списке столбцов сначала NAME (имя), затем SURNAME (фамилия) — как требуется в задании.

4.4. Сколько строк в таблице

SELECT COUNT(*) AS cnt FROM dbo.STUDENT;

Агрегатная функция COUNT(*) считает строки. Для эталона ответ снова 19.

Окно запроса T-SQL

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

Результат выполнения запроса

Результат SELECT — на вкладке Results.

5. Файл отчёта

  1. Сохраните в один файл lab02_FIO.sql (ФИО латиницей): команды USE, все CREATE TABLE, все INSERT и все SELECT из этой работы.
  2. Добавьте в начало файла комментарий: -- ЛР №2, IvanovII, группа ВО-ИСИТ-31 (подставьте свои фамилию и инициалы латиницей).
  3. К отчёту приложите скриншоты: список таблиц в Object Explorer, результат COUNT(*), один из запросов из §4.

6. Дополнительно

  1. Найдите в блоках 3–5 ограничения CHECK (стипендия ≥ 0, курс 1–6, оценка 2–5). Выполните заведомо неверный INSERT, например студента с KURS = 9, и прочитайте текст ошибки.
  2. Попробуйте вставить студента с UNIVERSITY_ID = 999. СУБД должна отклонить строку — нет такого вуза, сработал внешний ключ.
  3. Откройте dbo.EXAM_MARKS и найдите студента без оценок (STUDENT_ID = 19). Эта строка специально нужна для заданий с IS NULL на следующих лабораторных.

Контрольные вопросы

  1. Чем пустая UniversityDB после ЛР №1 отличается от той же базы после этой работы?
  2. Почему таблицу UNIVERSITY создают раньше, чем STUDENT?
  3. Что делает SELECT * FROM UNIVERSITY и чем он отличается от SELECT UNIVERSITY_NAME, CITY FROM UNIVERSITY?
  4. Что произойдёт при INSERT студента с несуществующим UNIVERSITY_ID?
  5. Зачем в отчёте хранить файл lab02_FIO.sql (ФИО латиницей), если база уже создана на сервере?

Лабораторная работа №3. DDL: CREATE, типы, ограничения

Дата: 22.09.2026, вт, 16:00–17:35, ауд. 112 · Отчёт: скрипт lab03_FIO.sql (ФИО латиницей) + скриншоты ошибок ограничений.

Цель: спроектировать отдельную базу «Библиотека», создать таблицы с ограничениями PRIMARY KEY, UNIQUE, CHECK, FOREIGN KEY, загрузить данные и убедиться, что СУБД отклоняет неверные строки.

Связь с лекцией 3: три таблицы — три сущности без лишних повторов (автор, книга, экземпляр). После работы ответьте, какие нормальные формы выполняет схема.

0. Перед началом

  1. Запустите SSMS и подключитесь к серверу.
  2. База UniversityDB с ЛР №2 должна остаться нетронутой — на этой работе создаётся новая база Lab03_Library.
  3. Откройте New Query. Весь SQL ниже выполняйте в этой базе после шага 1.
Не выполняйте DROP DATABASE UniversityDB и не пересоздавайте таблицы учебного эталона — они понадобятся на следующих лабораторных.

1. Создание базы данных

Команда CREATE DATABASE создаёт пустой контейнер для таблиц. Пакет GO завершает пакет команд (как на ЛР №1).

CREATE DATABASE Lab03_Library; GO USE Lab03_Library; GO SELECT DB_NAME() AS current_database;

В результате последнего запроса должно быть Lab03_Library. Обновите Object Explorer (F5) — база появится в списке.

2. Схема «Библиотека»

Три таблицы связаны цепочкой: у книги один автор, у экземпляра одна книга. Создавайте таблицы в этом порядке — иначе внешний ключ не найдёт родительскую таблицу.

ТаблицаНазначениеКлючевые ограничения
AUTHORАвторыauthor_id — PK; name — NOT NULL
BOOKКниги (издания)book_id — PK; isbn — UNIQUE; год издания — CHECK; author_id — FK
COPYЭкземпляры на полкеcopy_id — PK; inventory_no — UNIQUE; status — CHECK и DEFAULT; book_id — FK с CASCADE

2.1. Таблица AUTHOR

CREATE TABLE dbo.AUTHOR ( author_id INT NOT NULL PRIMARY KEY, surname NVARCHAR(100) NOT NULL, name NVARCHAR(100) NOT NULL );

2.2. Таблица BOOK

CREATE TABLE dbo.BOOK ( book_id INT NOT NULL PRIMARY KEY, isbn CHAR(13) NOT NULL UNIQUE, title NVARCHAR(200) NOT NULL, pub_year INT NOT NULL CHECK (pub_year BETWEEN 1500 AND YEAR(GETDATE())), author_id INT NOT NULL, CONSTRAINT FK_BOOK_AUTHOR FOREIGN KEY (author_id) REFERENCES dbo.AUTHOR(author_id) );

Столбец pub_year — год издания; CHECK не допускает «1300» и будущие годы.

2.3. Таблица COPY

CREATE TABLE dbo.COPY ( copy_id INT NOT NULL PRIMARY KEY, book_id INT NOT NULL, inventory_no VARCHAR(20) NOT NULL UNIQUE, status CHAR(3) NOT NULL DEFAULT 'in' CHECK (status IN ('in', 'out')), CONSTRAINT FK_COPY_BOOK FOREIGN KEY (book_id) REFERENCES dbo.BOOK(book_id) ON DELETE CASCADE );

ON DELETE CASCADE: при удалении книги СУБД удалит все её экземпляры. status: in — на полке, out — выдан читателю.

После выполнения проверьте Object Explorer: под Lab03_LibraryTables — три таблицы.

3. Загрузка данных

Сначала авторы, затем книги, затем экземпляры — как при загрузке UniversityDB на ЛР №2.

INSERT INTO dbo.AUTHOR (author_id, surname, name) VALUES (1, N'Пушкин', N'Александр'), (2, N'Толстой', N'Лев'), (3, N'Достоевский', N'Фёдор'); INSERT INTO dbo.BOOK (book_id, isbn, title, pub_year, author_id) VALUES (10, '9785170901234', N'Евгений Онегин', 1833, 1), (11, '9785170905678', N'Война и мир', 1869, 2), (12, '9785170909012', N'Преступление и наказание', 1866, 3); INSERT INTO dbo.COPY (copy_id, book_id, inventory_no, status) VALUES (100, 10, 'INV-001', 'in'), (101, 10, 'INV-002', 'out'), (102, 11, 'INV-003', 'in'), (103, 12, 'INV-004', 'in');

Можете добавить свои строки (минимум 3–5 в каждой таблице). Проверка:

SELECT COUNT(*) AS author_cnt FROM dbo.AUTHOR; SELECT COUNT(*) AS book_cnt FROM dbo.BOOK; SELECT COUNT(*) AS copy_cnt FROM dbo.COPY;

4. Проверка ограничений

Выполните команды ниже по одной. Каждая должна завершиться ошибкой — это ожидаемый результат. Сохраните текст ошибки или скриншот для отчёта.

4.1. Дубликат ISBN

INSERT INTO dbo.BOOK (book_id, isbn, title, pub_year, author_id) VALUES (99, '9785170901234', N'Дубликат', 2000, 1);

Нарушение UNIQUE на isbn.

4.2. Недопустимый год

INSERT INTO dbo.BOOK (book_id, isbn, title, pub_year, author_id) VALUES (98, '9785170999999', N'Старое издание', 1300, 1);

Нарушение CHECK на pub_year.

4.3. Недопустимый статус

INSERT INTO dbo.COPY (copy_id, book_id, inventory_no, status) VALUES (199, 10, 'INV-BAD', 'broken');

Нарушение CHECK на status — допустимы только in и out.

4.4. Дополнительно (по желанию)

INSERT INTO dbo.BOOK (book_id, isbn, title, pub_year, author_id) VALUES (97, '9785170888888', N'Без автора', 2020, 999);

Нарушение внешнего ключа — автора с author_id = 999 нет.

5. Нормальные формы (письменный ответ в отчёте)

Кратко ответьте в комментарии в lab03_FIO.sql или в сопроводительном тексте:

  1. Выполняется ли 1НФ? (атомарные ячейки, нет «списков авторов» в одной строке книги)
  2. Выполняется ли 3НФ? (фамилия автора хранится в AUTHOR, а не копируется в каждую строку COPY)
  3. Что было бы плохого в одной таблице «всё сразу»: автор + ISBN + инвентарный номер + статус?

Ожидаемый вывод: схема из трёх таблиц в 1НФ и 3НФ; разделение убирает аномалии обновления (смена имени автора — одна строка в AUTHOR).

6. Файл отчёта

  1. Сохраните в один файл lab03_FIO.sql (ФИО латиницей): CREATE DATABASE, USE, все CREATE TABLE, все успешные INSERT, контрольные SELECT COUNT.
  2. Неверные INSERT из §4 можно оставить в файле закомментированными (-- в начале строки) с пометкой «ожидаемая ошибка».
  3. В начале файла: -- ЛР №3, IvanovII, группа ВО-ИСИТ-31.
  4. К отчёту приложите скриншоты: список таблиц в Object Explorer, одна успешная вставка, одна ошибка CHECK или UNIQUE.

Контрольные вопросы

  1. Зачем на этой работе отдельная база Lab03_Library, а не изменения в UniversityDB?
  2. Почему BOOK создают после AUTHOR, а COPY — после BOOK?
  3. Чем PRIMARY KEY отличается от UNIQUE на примере isbn и book_id?
  4. Что делает ON DELETE CASCADE при удалении строки из BOOK?
  5. Какая аномалия обновления исчезает, когда имя автора хранится только в AUTHOR?

Лабораторная работа №4. FK, ALTER TABLE, GO

Дата: 23.09.2026, ср, 12:30–14:05, ауд. 205 · Отчёт: скрипт lab04_FIO.sql (ФИО латиницей) + скриншоты из §1–5.

Цель: изменить существующую схему UniversityDB командами ALTER TABLE, добавить индексы, поработать с пакетами GO и убедиться, что ограничения FK и UNIQUE работают.

Связь с лекцией 4: схема живёт на общем сервере; ваш ALTER TABLE видят все сеансы. Внешние ключи с ЛР №2 защищают ссылки; сегодня добавляете столбец и индексы без пересоздания таблиц.

0. Перед началом

  1. Запустите SSMS, подключитесь к учебному серверу (как на ЛР №1).
  2. В Object Explorer откройте UniversityDBTables — должны быть семь таблиц после ЛР №2.
  3. New Query, в списке баз выберите UniversityDB, выполните контроль:
USE UniversityDB; SELECT COUNT(*) AS student_cnt FROM dbo.STUDENT; SELECT COUNT(*) AS mark_cnt FROM dbo.EXAM_MARKS;

Ожидается: 19 студентов и непустая таблица оценок. Если база пуста — повторите ЛР №2 (блоки приложения 3–6).

Не выполняйте DROP DATABASE и не трогайте чужие базы на общем сервере.
Object Explorer — таблицы UniversityDB

Object Explorer: под UniversityDBTablesSTUDENT, UNIVERSITY, …

1. ALTER TABLE — новый столбец EMAIL

На ЛР №2 таблицы создавали через CREATE TABLE. В живой системе схему чаще дополняют — так деканат добавляет поле «email» без пересоздания таблицы и без потери 19 строк.

ALTER TABLE dbo.STUDENT ADD EMAIL VARCHAR(100) NULL;
  1. Выполните команду (F5). Сообщение: Commands completed successfully.
  2. Обновите Object Explorer (F5). Правый клик dbo.STUDENTDesign — в списке столбцов появился EMAIL, тип varchar(100), Allow Nulls = да.
  3. Заполните адреса по шаблону student<STUDENT_ID>@edu.local:
UPDATE dbo.STUDENT SET EMAIL = 'student' + CAST(STUDENT_ID AS VARCHAR(10)) + '@edu.local' WHERE EMAIL IS NULL;

Конкретный запрос SELECT и ожидаемый фрагмент результата:

SELECT TOP 5 STUDENT_ID, SURNAME, EMAIL FROM dbo.STUDENT ORDER BY STUDENT_ID;
STUDENT_IDSURNAMEEMAIL
1student1@edu.local
2student2@edu.local

Фамилии возьмутся из вашего эталона; важны столбец EMAIL и шаблон адреса. Сделайте скриншот вкладки Results.

Окно запроса ALTER и UPDATE

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

Результат SELECT с EMAIL

Результат SELECT TOP 5 … EMAIL — приложите к отчёту.

2. Ограничение UNIQUE на EMAIL

UNIQUE запрещает два одинаковых значения в столбце (кроме NULL — в SQL Server несколько NULL в UNIQUE допустимы, но у вас все EMAIL заполнены).

ALTER TABLE dbo.STUDENT ADD CONSTRAINT UQ_STUDENT_EMAIL UNIQUE (EMAIL);

Теперь намеренно нарушите правило — скопируйте адрес студента 1 студенту 2:

UPDATE dbo.STUDENT SET EMAIL = 'student1@edu.local' WHERE STUDENT_ID = 2;

Ожидаемо: выполнение прервётся, на вкладке Messages текст вроде:

Msg 2627, Level 14, State 1 Violation of UNIQUE KEY constraint 'UQ_STUDENT_EMAIL'. Cannot insert duplicate key …

Сохраните скриншот вкладки Messages — это доказательство работы ограничения. Верните уникальные значения:

UPDATE dbo.STUDENT SET EMAIL = 'student' + CAST(STUDENT_ID AS VARCHAR(10)) + '@edu.local';

2.1. Напоминание про FK (с ЛР №2)

Если бы вы добавляли столбец UNIVERSITY_ID вместо EMAIL, FK не дал бы записать несуществующий вуз. Проверка (ожидается ошибка):

-- ожидаемая ошибка FK — выполните и прочитайте Messages: UPDATE dbo.STUDENT SET UNIVERSITY_ID = 999 WHERE STUDENT_ID = 1;

3. Индексы для ускорения поиска

Индекс — отдельная структура для быстрого поиска по столбцу. На ЛР №5–6 вы часто будете писать WHERE CITY = … и WHERE UNIVERSITY_ID = … AND KURS = … — под такие фильтры индексы уместны.

CREATE NONCLUSTERED INDEX IX_STUDENT_CITY ON dbo.STUDENT (CITY); CREATE NONCLUSTERED INDEX IX_STUDENT_UNIV_KURS ON dbo.STUDENT (UNIVERSITY_ID, KURS);

Clustered индекс один на таблицу (обычно PK); nonclustered — дополнительные «указатели» к строкам.

4. Просмотр индексов через sys.indexes

SELECT t.name AS table_name, i.name AS index_name, i.type_desc, i.is_unique FROM sys.indexes i JOIN sys.tables t ON i.object_id = t.object_id WHERE t.name = N'STUDENT' AND i.name IS NOT NULL ORDER BY i.index_id;

В результате должны быть как минимум:

index_nametype_descis_uniqueКомментарий
PK__STUDENT…CLUSTERED1первичный ключ
UQ_STUDENT_EMAILNONCLUSTERED1ваше UNIQUE
IX_STUDENT_CITYNONCLUSTERED0создали в §3
IX_STUDENT_UNIV_KURSNONCLUSTERED0составной индекс

Точное имя PK может отличаться — смотрите столбец index_name.

5. Пакеты GO

GO — не команда T-SQL, а разделитель пакетов в SSMS. Переменная, объявленная в одном пакете, не видна в следующем.

DECLARE @db SYSNAME = DB_NAME(); SELECT @db AS current_db; GO DECLARE @cnt INT; SELECT @cnt = COUNT(*) FROM dbo.STUDENT; SELECT @cnt AS students; GO

Ожидаемый результат второго пакета: students = 19.

Эксперимент: уберите оба GO и выполните скрипт целиком. Вторая строка DECLARE @cnt в том же пакете даст ошибку «имя переменной уже объявлено» или конфликт с первым пакетом — зафиксируйте текст ошибки в отчёте.

Если видите Cannot find object STUDENT — выполните USE UniversityDB;. Если столбец EMAIL уже добавлен — пропустите §1 или согласуйтесь с преподавателем. Повторный CREATE INDEX даст ошибку — индекс уже есть.

6. Файл отчёта

  1. Сохраните в один файл lab04_FIO.sql (ФИО латиницей): USE, все ALTER, UPDATE, CREATE INDEX, SELECT из sys.indexes, скрипт с GO.
  2. В начале: -- ЛР №4, IvanovII, группа ВО-ИСИТ-31 (подставьте свои фамилию и инициалы латиницей).
  3. К отчёту приложите скриншоты: Object Explorer с таблицами; результат §1; ошибка UNIQUE §2; список индексов §4.
  4. Согласуйте с преподавателем: оставить EMAIL и индексы для ЛР №5+ или удалить в конце скрипта:
-- по договорённости — откат схемы: -- ALTER TABLE dbo.STUDENT DROP CONSTRAINT UQ_STUDENT_EMAIL; -- DROP INDEX IX_STUDENT_CITY ON dbo.STUDENT; -- DROP INDEX IX_STUDENT_UNIV_KURS ON dbo.STUDENT; -- ALTER TABLE dbo.STUDENT DROP COLUMN EMAIL;

Имя файла отчёта: lab04_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab04_IvanovII.sql.

7. Дополнительно (если осталось время)

  1. Выполните EXEC sp_helpindex 'dbo.STUDENT'; — сравните вывод с sys.indexes.
  2. Добавьте индекс только если его ещё нет — обсудите, зачем в production проверяют IF NOT EXISTS (на курсе достаточно комментария).
  3. Объясните соседу, чем ALTER TABLE ADD безопаснее, чем «удалить STUDENT и создать заново».

Контрольные вопросы

  1. Зачем на ЛР №2 создавали FK на родительские таблицы раньше дочерних?
  2. Чем ALTER TABLE ADD отличается от повторного CREATE TABLE STUDENT?
  3. Почему UNIQUE на EMAIL отклонил второй одинаковый адрес?
  4. Зачем в одном скрипте несколько пакетов GO?
  5. Как по sys.indexes отличить clustered и nonclustered индекс?

Лабораторная работа №5. INSERT, SELECT, WHERE

Дата: 29.09.2026, вт, 14:15–15:50, ауд. 210 · Отчёт: скрипт lab05_FIO.sql (ФИО латиницей) + скриншоты результатов.

Цель: выполнить выборку с проекцией (список столбцов) и селекцией (WHERE): сравнение, AND/OR/NOT, IN, BETWEEN, LIKE, IS NULL на UniversityDB.

Связь с лекцией 2: вы уже делали простые SELECT на ЛР №2; здесь — систематическая работа с фильтрами. Справочник таблиц и эталонные данные — в приложении.

0. Перед началом

  1. SSMS → подключение к учебному серверу → база UniversityDB.
  2. Если на ЛР №4 добавляли столбец EMAIL — он не мешает; все запросы ниже работают и без него.
  3. Контроль эталона:
USE UniversityDB; SELECT COUNT(*) AS students FROM dbo.STUDENT; SELECT COUNT(*) AS marks FROM dbo.EXAM_MARKS; SELECT COUNT(*) AS subjects FROM dbo.SUBJECT;

Ожидается: 19 студентов, 24 строки в EXAM_MARKS, 8 предметов в SUBJECT (см. приложение).

Окно запроса SELECT

Перед работой убедитесь, что в списке баз выбрана UniversityDB.

1. Проекция — выбор столбцов

Проекция — какие столбцы показать. Селекция — какие строки отобрать (WHERE, §2–4).

1.1. Все предметы

SELECT * FROM dbo.SUBJECT;

Ожидается 8 строк, столбцы SUBJ_ID, SUBJ_NAME, HOUR, SEMESTER.

1.2. Оценки по предмету «Информатика» (SUBJ_ID = 10)

SELECT STUDENT_ID, SUBJ_ID, MARK, EXAM_DATE FROM dbo.EXAM_MARKS WHERE SUBJ_ID = 10 ORDER BY STUDENT_ID;

В эталоне — несколько строк (оценки разных студентов). В комментарии к скрипту укажите -- rows: N.

1.3. Список студентов — только нужные поля

SELECT STUDENT_ID, SURNAME, NAME, KURS, UNIVERSITY_ID, STIPEND, CITY FROM dbo.STUDENT ORDER BY SURNAME;

Ожидается 19 строк. Звёздочка * здесь не нужна — вы явно перечисляете столбцы отчёта.

2. Простые фильтры WHERE

Выполняйте запросы по одному. После каждого — запишите число строк (rows в углу Results или SELECT COUNT(*) … с тем же WHERE).

2.1. Предметы 4-го семестра

SELECT SUBJ_ID, SUBJ_NAME, SEMESTER, HOUR FROM dbo.SUBJECT WHERE SEMESTER = 4;

Ожидается 1 строка — «История» (SUBJ_ID = 56).

2.2. Студенты 3 курса и старше

SELECT SURNAME, NAME, KURS FROM dbo.STUDENT WHERE KURS >= 3 ORDER BY KURS, SURNAME;

2.3. Стипендия больше 140

SELECT SURNAME, STIPEND FROM dbo.STUDENT WHERE STIPEND > 140 ORDER BY STIPEND DESC;

2.4. Предметы длиннее 40 академических часов

SELECT SUBJ_NAME, HOUR FROM dbo.SUBJECT WHERE HOUR > 40 ORDER BY HOUR DESC;

Ожидается 4 строки (56, 72, 56, 56 часов в эталоне).

2.5. Вузы с рейтингом выше 400

SELECT UNIVERSITY_NAME, RATING, CITY FROM dbo.UNIVERSITY WHERE RATING > 400 ORDER BY RATING DESC;

Ожидается 6 вузов (рейтинг 410, 450, 470, 580, 650, 700).

Результат SELECT с WHERE

Пример результата с фильтром — приложите один такой скриншот к отчёту.

3. Сложные условия — AND, OR, IN, BETWEEN

3.1. Студенты из Воронежа со стипендией

SELECT SURNAME, CITY, STIPEND FROM dbo.STUDENT WHERE CITY = N'Воронеж' AND STIPEND > 0 ORDER BY STIPEND DESC;

Буква N перед строкой — Unicode для кириллицы.

3.2. Преподаватели из Воронежа

SELECT LECTURER_ID, SURNAME, NAME, CITY FROM dbo.LECTURER WHERE CITY = N'Воронеж';

3.3. Скобки и OR

SELECT SURNAME, KURS, STIPEND FROM dbo.STUDENT WHERE (KURS = 1 OR KURS = 2) AND STIPEND >= 100 ORDER BY KURS, SURNAME;

Без скобок AND связывал бы только KURS = 2 со стипендией — логика изменилась бы.

3.4. IN и BETWEEN

SELECT SURNAME, KURS FROM dbo.STUDENT WHERE KURS IN (2, 4, 5); SELECT SURNAME, STIPEND FROM dbo.STUDENT WHERE STIPEND BETWEEN 100 AND 180;

4. LIKE и IS NULL

4.1. Фамилии на «С»

SELECT SURNAME, NAME FROM dbo.STUDENT WHERE SURNAME LIKE N'С%' ORDER BY SURNAME;

% — любое продолжение. Укажите в комментарии, сколько строк вернулось.

4.2. Студенты без города

SELECT STUDENT_ID, SURNAME, NAME, CITY FROM dbo.STUDENT WHERE CITY IS NULL;

Ожидается 1 строкаSTUDENT_ID = 19 (специально для этой проверки).

4.3. Ошибка: = NULL

-- НЕПРАВИЛЬНО — вернёт 0 строк: SELECT STUDENT_ID FROM dbo.STUDENT WHERE CITY = NULL; -- ПРАВИЛЬНО: SELECT STUDENT_ID FROM dbo.STUDENT WHERE CITY IS NULL;

Сохраните скриншот: сравнение «0 строк» и «1 строка» — хороший фрагмент отчёта.

5. Частые ошибки

ОшибкаЧто проверить
0 строк там, где ждали данныеВыбрана ли UniversityDB; нет ли опечатки в N'Воронеж'
CITY = NULLТолько IS NULL / IS NOT NULL
Фильтр по SEMESTER в STUDENTСеместр — столбец таблицы SUBJECT, не студента
Забыли dbo.На учебном сервере лучше явно: dbo.STUDENT

6. Файл отчёта

  1. Сохраните все запросы из §1–4 в один файл lab05_FIO.sql (ФИО латиницей).
  2. В начале файла: -- ЛР №5, IvanovII, группа ВО-ИСИТ-31 (подставьте свои фамилию и инициалы латиницей).
  3. К каждому блоку §2–4 добавьте комментарий -- rows: N с числом строк результата.
  4. К отчёту приложите скриншоты: контроль §0; один запрос из §2; сравнение = NULL и IS NULL из §4.3.

Имя файла отчёта: lab05_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab05_IvanovII.sql.

7. Дополнительно (если осталось время)

  1. SELECT * FROM dbo.STUDENT WHERE NOT (KURS < 3); — сравните с KURS >= 3.
  2. Запрос: студенты вуза ВГУ (UNIVERSITY_ID = 10) с стипендией выше средней по этому вузу (подсказка: подзапрос — ЛР №9).
  3. Объясните, почему SELECT не меняет данные и не требует ROLLBACK (в отличие от ЛР №6).

Контрольные вопросы

  1. Чем проекция отличается от селекции в одном SELECT?
  2. Почему условие на SEMESTER относится к таблице SUBJECT, а не STUDENT?
  3. Что вернёт LIKE N'С%' и зачем буква N?
  4. Чем IS NULL отличается от = NULL?
  5. Зачем в отчёте хранить файл lab05_FIO.sql (ФИО латиницей), если результат виден на экране?

Лабораторная работа №6. UPDATE, DELETE, ORDER BY

Дата: 30.09.2026, ср, 12:30–14:05, ауд. 210 · Отчёт: скрипт lab06_FIO.sql (ФИО латиницей) + скриншоты результатов.

Цель: изменять данные (DML), сортировать выборку, использовать TOP и DISTINCT; безопасно экспериментировать в транзакции с ROLLBACK (лекция 5).

Связь с лекцией 5–6: на общем сервере незафиксированные UPDATE/DELETE видят другие сеансы — поэтому учебные изменения только с откатом.

Все демонстрации UPDATE, INSERT и DELETE ниже выполняйте внутри BEGIN TRAN … ROLLBACK. Не нажимайте COMMIT, пока не согласовали с преподавателем.

0. Перед началом

USE UniversityDB; SELECT COUNT(*) AS student_cnt FROM dbo.STUDENT; SELECT COUNT(*) AS mark_cnt FROM dbo.EXAM_MARKS;

Ожидается 19 студентов. Запишите число оценок — после всех ROLLBACK оно должно совпасть.

1. ORDER BY, TOP, DISTINCT

ORDER BY сортирует результат; TOP n ограничивает число строк (аналог LIMIT в других СУБД). DISTINCT убирает дубликаты в выборке.

1.1. Сортировка по стипендии

SELECT SURNAME, STIPEND FROM dbo.STUDENT ORDER BY STIPEND DESC;

Вверху списка — студенты с наибольшей стипендией. Скриншот для отчёта.

1.2. TOP 5

SELECT TOP 5 SURNAME, STIPEND FROM dbo.STUDENT ORDER BY STIPEND DESC;

Ровно 5 строк (если в таблице ≥ 5 студентов).

1.3. DISTINCT

SELECT DISTINCT MARK FROM dbo.EXAM_MARKS WHERE MARK IS NOT NULL ORDER BY MARK; SELECT DISTINCT KURS, CITY FROM dbo.STUDENT ORDER BY KURS, CITY;

В первом запросе — уникальные оценки (2–5); во втором — уникальные пары «курс + город».

Результат ORDER BY и TOP

Результат TOP 5 … ORDER BY STIPEND DESC — приложите к отчёту.

2. INSERT в транзакции

Сначала «пробные» строки — затем откат. Порядок: родитель UNIVERSITY, потом дочерний STUDENT (FK).

BEGIN TRAN; INSERT INTO dbo.UNIVERSITY (UNIVERSITY_ID, UNIVERSITY_NAME, RATING, CITY) VALUES (99, N'Тестовый вуз', 100, N'Тестград'); INSERT INTO dbo.STUDENT (STUDENT_ID, NAME, SURNAME, KURS, UNIVERSITY_ID, STIPEND, CITY, BIRTHDAY) VALUES (99, N'Тест', N'Тестов', 1, 99, 0, N'Тестград', '2005-01-01'); SELECT COUNT(*) AS cnt FROM dbo.STUDENT WHERE UNIVERSITY_ID = 99; -- 1 INSERT INTO dbo.UNIVERSITY (UNIVERSITY_ID, UNIVERSITY_NAME, RATING, CITY) SELECT 98, N'Высокий рейтинг', MAX(RATING) + 10, N'Москва' FROM dbo.UNIVERSITY; ROLLBACK TRAN; SELECT COUNT(*) AS student_cnt FROM dbo.STUDENT; -- снова 19

INSERT … SELECT вставляет строку, вычисленную запросом (здесь — рейтинг выше текущего максимума).

3. UPDATE в транзакции

Перед изменением — SELECT с тем же WHERE; после UPDATE — повторный SELECT; в конце — ROLLBACK.

BEGIN TRAN; UPDATE dbo.STUDENT SET STIPEND = STIPEND * 1.10 WHERE KURS = 1; SELECT STUDENT_ID, SURNAME, STIPEND FROM dbo.STUDENT WHERE KURS = 1; UPDATE dbo.STUDENT SET UNIVERSITY_ID = 14 WHERE STUDENT_ID = 15; SELECT STUDENT_ID, SURNAME, UNIVERSITY_ID FROM dbo.STUDENT WHERE STUDENT_ID = 15; ROLLBACK TRAN; SELECT STUDENT_ID, UNIVERSITY_ID FROM dbo.STUDENT WHERE STUDENT_ID = 15;

После ROLLBACK у студента 15 снова должен быть исходный UNIVERSITY_ID из эталона.

4. DELETE с проверкой

BEGIN TRAN; SELECT COUNT(*) AS bad_marks FROM dbo.EXAM_MARKS WHERE MARK < 3; DELETE FROM dbo.EXAM_MARKS WHERE MARK < 3; SELECT COUNT(*) AS after_delete FROM dbo.EXAM_MARKS WHERE MARK < 3; ROLLBACK TRAN; SELECT COUNT(*) AS bad_marks_again FROM dbo.EXAM_MARKS WHERE MARK < 3;

После отката последний COUNT совпадает с первым — двойки (если были) на месте.

5. Удаление и внешний ключ

Нельзя удалить вуз, пока на него ссылаются студенты. Сначала проверьте ошибку:

BEGIN TRAN; INSERT INTO dbo.UNIVERSITY (UNIVERSITY_ID, UNIVERSITY_NAME, RATING, CITY) VALUES (99, N'Тест', 100, N'Тест'); INSERT INTO dbo.STUDENT (STUDENT_ID, NAME, SURNAME, KURS, UNIVERSITY_ID, STIPEND, CITY, BIRTHDAY) VALUES (99, N'Т', N'Тестов', 1, 99, 0, N'Т', '2005-01-01'); DELETE FROM dbo.UNIVERSITY WHERE UNIVERSITY_ID = 99; -- ожидается ошибка FK ROLLBACK TRAN;

Правильный порядок внутри транзакции: сначала DELETE студентов, потом вуза.

BEGIN TRAN; -- … те же INSERT … DELETE FROM dbo.STUDENT WHERE UNIVERSITY_ID = 99; DELETE FROM dbo.UNIVERSITY WHERE UNIVERSITY_ID = 99; ROLLBACK TRAN;

6. Частые ошибки

ОшибкаЧто делать
Случайный COMMITНа учебном сервере — только ROLLBACK; пересоздайте эталон с преподавателем
UPDATE без WHEREСначала SELECT с тем же условием — убедитесь, что трогаете нужные строки
DELETE родителя раньше ребёнкаСначала дочерние строки или CASCADE (если задан)
Забыли ROLLBACKSELECT @@TRANCOUNT; — если > 0, выполните ROLLBACK

7. Файл отчёта

  1. Сохраните все команды §1–5 в lab06_FIO.sql (ФИО латиницей).
  2. В начале: -- ЛР №6, IvanovII, группа ВО-ИСИТ-31.
  3. К каждому блоку с UPDATE/DELETE добавьте комментарий «до / после / после ROLLBACK».
  4. Скриншоты: TOP 5; один UPDATE до ROLLBACK и после; ошибка FK при DELETE вуза.
  5. Финальная проверка: SELECT COUNT(*) FROM dbo.STUDENT; = 19.

Имя файла отчёта: lab06_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab06_IvanovII.sql.

8. Дополнительно

  1. SELECT TOP 5 PERCENT STIPEND, … ORDER BY STIPEND DESC; — чем отличается от TOP 5?
  2. Попробуйте UPDATE с заведомо неверным CHECK (KURS = 9) внутри TRY/CATCH (ЛР №16).

Контрольные вопросы

  1. Почему ORDER BY пишут после WHERE?
  2. Зачем ROLLBACK после демонстрационного UPDATE на общем сервере?
  3. Чем INSERT … SELECT отличается от INSERT … VALUES?
  4. Почему DELETE вуза без удаления студентов вызывает ошибку FK?
  5. Какая аномалия из лекции 6 связана с незафиксированными изменениями соседа?

Лабораторная работа №7. Агрегатные функции

Дата: 06.10.2026, вт, 12:30–14:05, ауд. 220 · Отчёт: скрипт lab07_FIO.sql (ФИО латиницей) + скриншоты результатов.

Цель: использовать COUNT, SUM, AVG, MIN, MAX; понять, как NULL влияет на агрегаты; сверить ответы с эталоном из приложения.

Связь с курсом: на лекции 2 вы делали простые SELECT; здесь одна строка результата суммирует много строк таблицы. На ЛР №8 добавится GROUP BY — группы вместо «всей таблицы сразу».

Напоминание: все агрегаты, кроме COUNT(*), игнорируют строки, где аргумент равен NULL.

0. Перед началом

USE UniversityDB; SELECT COUNT(*) AS student_cnt FROM dbo.STUDENT; SELECT COUNT(*) AS mark_cnt FROM dbo.EXAM_MARKS; SELECT COUNT(*) AS subject_cnt FROM dbo.SUBJECT;

Ожидается: 19 студентов, 24 оценки, 8 предметов. Если числа другие — восстановите эталон (ЛР №2, блок 6 приложения).

1. COUNT — три варианта

COUNT(*) считает строки. COUNT(столбец) не учитывает NULL в этом столбце. COUNT(DISTINCT …) — число различных значений (NULL не входит).

1.1. Студенты и города

SELECT COUNT(*) AS all_rows FROM dbo.STUDENT; SELECT COUNT(CITY) AS with_city FROM dbo.STUDENT; SELECT COUNT(DISTINCT CITY) AS distinct_cities FROM dbo.STUDENT;

Ожидается: 19, 18, 8. У студента STUDENT_ID = 19 поле CITY специально NULL — поэтому COUNT(CITY) на 1 меньше, чем COUNT(*).

В комментарии к скрипту запишите: -- all_rows: 19; with_city: 18; distinct_cities: 8.

2. MIN, MAX, AVG по стипендии

SELECT MIN(STIPEND) AS min_st, MAX(STIPEND) AS max_st, AVG(STIPEND) AS avg_st FROM dbo.STUDENT; SELECT AVG(STIPEND) AS avg_positive FROM dbo.STUDENT WHERE STIPEND > 0;

Ожидается: min_st = 0, max_st = 250, avg_st122.89 (среднее по всем 19, включая нулевые стипендии). Во втором запросе среднее только по студентам с STIPEND > 0 — ≈ 155.67 (15 строк).

Обратите внимание: нули в данных — не NULL; они участвуют в AVG первого запроса и занижают среднее.

3. Агрегаты по предметам, вузам и оценкам

Выполняйте запросы по одному; после каждого сверяйте результат с эталоном.

3.1. Часы и рейтинги

SELECT SUM(HOUR) AS total_hours FROM dbo.SUBJECT; SELECT MIN(RATING) AS min_rating, MAX(RATING) AS max_rating FROM dbo.UNIVERSITY;

Ожидается: total_hours = 382 (сумма часов восьми предметов); min_rating = 320 (БГУ), max_rating = 700 (МГУ).

3.2. Оценки

SELECT AVG(CAST(MARK AS FLOAT)) AS avg_mark FROM dbo.EXAM_MARKS; SELECT COUNT(*) AS fives FROM dbo.EXAM_MARKS WHERE MARK = 5; SELECT COUNT(*) AS twos FROM dbo.EXAM_MARKS WHERE MARK = 2; SELECT MIN(EXAM_DATE) AS first_exam, MAX(EXAM_DATE) AS last_exam FROM dbo.EXAM_MARKS;

Ожидается: avg_mark4.08; 9 пятёрок; 1 двойка; первая дата 2026-01-15, последняя 2026-06-12.

CAST(MARK AS FLOAT) нужен, чтобы среднее было дробным, а не целым от деления типа INT.

Результат агрегирующего запроса

Пример вкладки Results для блока §3 — одна строка с несколькими агрегатами. Сделайте скриншот для отчёта.

4. NULL в аргументе агрегата

SELECT COUNT(*) AS all_exams, COUNT(MARK) AS with_mark FROM dbo.EXAM_MARKS;

В эталоне у всех 24 строк поле MARK заполнено — оба счётчика дают 24, разница 0. Это нормально: NULL в оценках зарезервирован для других заданий; здесь вы фиксируете, что COUNT(MARK) и COUNT(*) совпали.

Для строк с NULL смотрите §1: COUNT(CITY) vs COUNT(*) у STUDENT.

5. Файл отчёта

  1. Сохраните все запросы §0–4 в lab07_FIO.sql (ФИО латиницей).
  2. В начале: -- ЛР №7, IvanovII, группа ВО-ИСИТ-31.
  3. К каждому блоку добавьте комментарий с ожидаемым значением (как в §1).
  4. Скриншоты: результат §1 (три COUNT); результат §3.2 (оценки); один запрос с AVG и CAST.

Имя файла отчёта: lab07_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab07_IvanovII.sql.

6. Дополнительно

  1. SELECT COUNT(*), COUNT(STIPEND) FROM dbo.STUDENT; — совпадут ли счётчики? Почему?
  2. SELECT AVG(CAST(STIPEND AS FLOAT)) FROM dbo.STUDENT WHERE KURS = 1; — посчитайте вручную для первого курса (подготовка к GROUP BY на ЛР №8).
  3. Чем опасно путать AVG(STIPEND) по всей таблице и среднее «только по получающим стипендию»?

Контрольные вопросы

  1. Почему COUNT(CITY) меньше COUNT(*) у STUDENT?
  2. Чем AVG(STIPEND) по всей таблице отличается от AVG при STIPEND > 0?
  3. Зачем CAST(MARK AS FLOAT) перед AVG?
  4. Что считает COUNT(MARK), если в столбце есть NULL?
  5. Какие MIN/MAX по EXAM_DATE вы получили и что это означает для учебного семестра?

Лабораторная работа №8. GROUP BY, HAVING, ROLLUP

Дата: 06.10.2026, вт, 14:15–15:50, ауд. 220 · Отчёт: скрипт lab08_FIO.sql (ФИО латиницей) + скриншоты результатов.

Цель: группировать строки (GROUP BY), отбирать группы через HAVING, строить итоги GROUP BY ROLLUP в SQL Server.

Связь с ЛР №7: там агрегаты считали по всей таблице; здесь — отдельно по каждому курсу, городу, предмету. Справочник эталона — в приложении.

Правило SQL: каждый столбец в SELECT должен быть либо в GROUP BY, либо внутри агрегатной функции (COUNT, AVG, …).

0. Перед началом

USE UniversityDB; SELECT COUNT(*) AS student_cnt FROM dbo.STUDENT;

Ожидается 19 студентов. Если база пуста — повторите ЛР №2.

1. GROUP BY — одно измерение

GROUP BY делит строки на группы с одинаковым значением столбца; агрегат считается внутри каждой группы.

1.1. По курсу

SELECT KURS, COUNT(*) AS cnt, AVG(STIPEND) AS avg_st FROM dbo.STUDENT GROUP BY KURS ORDER BY KURS;

Ожидается 5 строк (курсы 1–5). Пример значений: курс 1 — 6 студентов, средняя стипендия 135.00; курс 2 — 4 студента, 167.50; курс 3 — 4, 96.25; курс 4 — 3, 120.00; курс 5 — 2, 55.00.

1.2. По городу

SELECT CITY, COUNT(*) AS cnt FROM dbo.STUDENT GROUP BY CITY ORDER BY cnt DESC, CITY;

Групп с заполненным городом — 8; отдельная группа с CITY IS NULL (студент 19) — 1 строка. Чаще всего встречаются Воронеж и Москва (по 4 студента).

1.3. По вузу

SELECT UNIVERSITY_ID, COUNT(*) AS cnt, AVG(CAST(STIPEND AS FLOAT)) AS avg_st FROM dbo.STUDENT GROUP BY UNIVERSITY_ID ORDER BY UNIVERSITY_ID;

Ожидается 8 групп (вузы 10, 11, 12, 14, 15, 18, 22, 32). Например: UNIVERSITY_ID = 105 студентов, средняя стипендия ≈ 95.00; 22 (МГУ) — 4 студента, ≈ 102.50.

Результат GROUP BY KURS

Результат GROUP BY KURS — несколько строк вместо одной сводки с ЛР №7.

2. GROUP BY по оценкам

SELECT SUBJ_ID, COUNT(*) AS exam_cnt, AVG(CAST(MARK AS FLOAT)) AS avg_mark, MIN(MARK) AS min_mark, MAX(MARK) AS max_mark FROM dbo.EXAM_MARKS WHERE MARK IS NOT NULL GROUP BY SUBJ_ID ORDER BY SUBJ_ID;

Ожидается 7 предметов с оценками. Примеры: SUBJ_ID = 108 экзаменов, средний ≈ 4.00; 432 экзамена, средний 5.00; 224 экзамена, средний 3.50.

3. HAVING — фильтр групп

WHERE отбирает строки до группировки; HAVING — группы после агрегации (можно использовать условие на COUNT(*), AVG, …).

3.1. Курсы с более чем тремя студентами

SELECT KURS, COUNT(*) AS cnt FROM dbo.STUDENT GROUP BY KURS HAVING COUNT(*) > 3 ORDER BY KURS;

Ожидается 3 строки: курсы 1 (6), 2 (4), 3 (4). Курсы 4 и 5 отсеялись — в группе ≤ 3 студента.

3.2. Предметы со средним баллом ≥ 4

SELECT SUBJ_ID, AVG(CAST(MARK AS FLOAT)) AS avg_mark FROM dbo.EXAM_MARKS WHERE MARK IS NOT NULL GROUP BY SUBJ_ID HAVING AVG(CAST(MARK AS FLOAT)) >= 4 ORDER BY SUBJ_ID;

Ожидается 6 предметов: 10, 18, 31, 43, 56, 94. Предмет 22 (средний 3.50) в список не попадает.

4. WHERE до GROUP BY

SELECT KURS, AVG(CAST(STIPEND AS FLOAT)) AS avg_st FROM dbo.STUDENT WHERE STIPEND > 0 GROUP BY KURS ORDER BY KURS;

Сначала отбрасываются нулевые стипендии, затем считается среднее по оставшимся в группе. Пример: курс 1 — среднее ≈ 162.00 (5 студентов с ненулевой стипендией), курс 4 — 180.00 (студент 6 с нулём не участвует).

Если написать HAVING AVG(STIPEND) > 0 вместо WHERE STIPEND > 0, нули всё равно войдут в расчёт среднего внутри группы — результат будет другим. Это частая ошибка на защите.

5. ROLLUP

SELECT KURS, COUNT(*) AS cnt, AVG(STIPEND) AS avg_st FROM dbo.STUDENT GROUP BY ROLLUP(KURS) ORDER BY KURS;

ROLLUP добавляет строку с KURS IS NULLитог по всей таблице: cnt = 19, avg_st122.89 (как на ЛР №7 без группировки). Строки с числом в KURS — группы по курсам из §1.1.

6. Файл отчёта

  1. Сохраните запросы §0–5 в lab08_FIO.sql (ФИО латиницей).
  2. В начале: -- ЛР №8, IvanovII, группа ВО-ИСИТ-31.
  3. К каждому блоку — комментарий с числом строк результата и ключевыми значениями.
  4. Скриншоты: GROUP BY KURS; HAVING COUNT(*) > 3; ROLLUP с итоговой строкой NULL.

Имя файла отчёта: lab08_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab08_IvanovII.sql.

7. Дополнительно

  1. GROUP BY KURS, CITY — сколько групп получится? Сравните с группировкой только по KURS.
  2. Почему SELECT KURS, SURNAME, COUNT(*) FROM STUDENT GROUP BY KURS вызывает ошибку?
  3. Добавьте WITH ROLLUP к запросу §3.2 — что изменится в результате?

Контрольные вопросы

  1. Почему столбцы в SELECT должны быть в GROUP BY или внутри агрегата?
  2. Чем HAVING отличается от WHERE?
  3. Зачем фильтровать STIPEND>0 до GROUP BY, а не в HAVING?
  4. Что означает строка с NULL в ROLLUP?
  5. Какие SUBJ_ID имеют средний балл ≥ 4 по вашим данным?

Лабораторная работа №9. Вложенные подзапросы

Дата: 06.10.2026, вт, 16:00–17:35, ауд. 220 · Отчёт: скрипт lab09_FIO.sql (ФИО латиницей) + скриншоты результатов.

Цель: писать скалярные подзапросы, использовать IN и NOT IN; понять, почему NOT IN опасен при NULL в подзапросе.

Связь с ЛР №8: там вы считали агрегаты с GROUP BY; здесь тот же MAX/AVG спрятан внутри WHERE — подзапрос возвращает одно значение для сравнения с каждой строкой внешнего запроса.

0. Перед началом

USE UniversityDB; SELECT COUNT(*) AS student_cnt FROM dbo.STUDENT;

Ожидается 19 студентов.

1. Скалярный подзапрос

Скалярный подзапрос возвращает одно значение (одну строку, один столбец). Его ставят в WHERE после =, >, < и т.д. Если вернётся больше одной строки — ошибка.

1.1. Максимальная стипендия

SELECT SURNAME, STIPEND FROM dbo.STUDENT WHERE STIPEND = (SELECT MAX(STIPEND) FROM dbo.STUDENT);

Ожидается 1 строка: Морозова, стипендия 250 (STUDENT_ID = 7).

1.2. Выше средней (только ненулевые стипендии)

SELECT SURNAME, STIPEND FROM dbo.STUDENT WHERE STIPEND > (SELECT AVG(STIPEND) FROM dbo.STUDENT WHERE STIPEND > 0) ORDER BY STIPEND DESC;

Средняя по ненулевым ≈ 155.67. Ожидается 7 строк (Сидорова, Козлова, Морозова, Соколова, Зайцева, Лебедева, Крылова).

1.3. Вузы с рейтингом выше среднего

SELECT UNIVERSITY_NAME, RATING FROM dbo.UNIVERSITY WHERE RATING > (SELECT AVG(RATING) FROM dbo.UNIVERSITY) ORDER BY RATING DESC;

Средний рейтинг ≈ 496.25. Ожидается 3 вуза: НГУ (580), СПбГУ (650), МГУ (700).

Результат подзапроса со стипендией

Результат §1.1 — одна строка с максимальной стипендией.

2. Подзапрос с IN

IN (подзапрос) проверяет, входит ли значение во множество строк подзапроса. Эквивалентно нескольким OR, но короче и читабельнее.

2.1. Студенты московских вузов

SELECT SURNAME, KURS, UNIVERSITY_ID FROM dbo.STUDENT WHERE UNIVERSITY_ID IN ( SELECT UNIVERSITY_ID FROM dbo.UNIVERSITY WHERE CITY = N'Москва' ) ORDER BY SURNAME;

В эталоне в Москве только МГУ (UNIVERSITY_ID = 22). Ожидается 4 студента (Сидорова, Сидоров, Кузнецов, Лебедева).

2.2. Оценки по «Информатике»

SELECT em.STUDENT_ID, em.MARK, em.EXAM_DATE FROM dbo.EXAM_MARKS em WHERE em.SUBJ_ID IN ( SELECT SUBJ_ID FROM dbo.SUBJECT WHERE SUBJ_NAME LIKE N'%информ%' ) ORDER BY em.STUDENT_ID;

Предмет SUBJ_ID = 10 (Информатика). Ожидается 8 строк в EXAM_MARKS по этому предмету.

Тот же результат можно получить через JOIN — на ЛР №11 сравните оба стиля.

3. NOT IN

NOT IN исключает строки, попадающие в список подзапроса. Важно: если подзапрос вернёт хотя бы один NULL, результат внешнего запроса может стать пустым (логика трёхзначная). Поэтому в подзапросе часто пишут WHERE столбец IS NOT NULL.

3.1. Вузы без студентов

SELECT UNIVERSITY_NAME, CITY FROM dbo.UNIVERSITY u WHERE u.UNIVERSITY_ID NOT IN ( SELECT DISTINCT UNIVERSITY_ID FROM dbo.STUDENT WHERE UNIVERSITY_ID IS NOT NULL );

В эталоне студенты есть в каждом из 8 вузов — результат 0 строк. Это нормально: запишите в отчёте «пустой результат — все вузы представлены».

3.2. Студенты без оценок

SELECT s.STUDENT_ID, s.SURNAME, s.NAME FROM dbo.STUDENT s WHERE s.STUDENT_ID NOT IN ( SELECT DISTINCT STUDENT_ID FROM dbo.EXAM_MARKS WHERE STUDENT_ID IS NOT NULL );

Ожидается 1 строка: Медведев (STUDENT_ID = 19) — специально для заданий с NOT EXISTS на ЛР №10.

3.3. Предметы без экзаменов в ведомости

SELECT SUBJ_ID, SUBJ_NAME FROM dbo.SUBJECT WHERE SUBJ_ID NOT IN ( SELECT DISTINCT SUBJ_ID FROM dbo.EXAM_MARKS WHERE SUBJ_ID IS NOT NULL );

Ожидается 1 предмет: Физкультура (SUBJ_ID = 73).

Если убрать WHERE SUBJ_ID IS NOT NULL и в EXAM_MARKS появится строка с SUBJ_ID = NULL, NOT IN может вернуть ноль строк для всех предметов. На ЛР №10 сравните с NOT EXISTS — он NULL не «ломает».

4. Файл отчёта

  1. Сохраните запросы §0–3 в lab09_FIO.sql (ФИО латиницей).
  2. В начале: -- ЛР №9, IvanovII, группа ВО-ИСИТ-31.
  3. К каждому блоку — комментарий -- rows: N и краткий вывод.
  4. Скриншоты: §1.1 (одна строка); §1.2 (семь фамилий); §3.2 (Медведев).

Имя файла отчёта: lab09_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab09_IvanovII.sql.

5. Дополнительно

  1. Перепишите §2.1 через JOIN с UNIVERSITY — совпали ли строки?
  2. WHERE STIPEND > ALL (SELECT STIPEND FROM STUDENT WHERE STIPEND > 0 AND STUDENT_ID <> 7) — кого оставит?
  3. Почему SELECT * FROM STUDENT WHERE STUDENT_ID NOT IN (SELECT STUDENT_ID FROM EXAM_MARKS) без фильтра NULL может вести себя странно, если в EXAM_MARKS появится NULL в STUDENT_ID?

Контрольные вопросы

  1. Когда подзапрос в WHERE должен вернуть ровно одно значение?
  2. Чем IN с подзапросом отличается от JOIN?
  3. Почему NOT IN опасен, если в подзапросе есть NULL?
  4. Как найти студентов без оценок через NOT IN?
  5. Зачем DISTINCT в подзапросе для UNIVERSITY_ID?

Лабораторная работа №10. Коррелированные подзапросы и EXISTS

Дата: 13.10.2026, вт, 12:30–14:05, ауд. 220 · Отчёт: скрипт lab10_FIO.sql (ФИО латиницей) + скриншоты результатов.

Цель: писать коррелированные подзапросы; использовать EXISTS, NOT EXISTS, операторы ANY/ALL.

Связь с ЛР №9: там подзапрос был «сам по себе»; здесь внутренний запрос ссылается на строку внешнего (s1.UNIVERSITY_ID) — выполняется заново для каждой строки снаружи.

0. Перед началом

USE UniversityDB;

1. Коррелированный подзапрос

Внутренний SELECT использует столбец внешней строки (s1.UNIVERSITY_ID, s1.KURS). Для каждого студента заново считается средняя стипендия в его вузе на его курсе.

SELECT s1.STUDENT_ID, s1.SURNAME, s1.STIPEND, s1.KURS, s1.UNIVERSITY_ID FROM dbo.STUDENT s1 WHERE s1.STIPEND > ( SELECT AVG(CAST(s2.STIPEND AS FLOAT)) FROM dbo.STUDENT s2 WHERE s2.UNIVERSITY_ID = s1.UNIVERSITY_ID AND s2.KURS = s1.KURS ) ORDER BY s1.UNIVERSITY_ID, s1.KURS, s1.STIPEND DESC;

Ожидается 3 строки: Иванов (ВГУ, 1 курс — выше среднего по группе), Орлов (ЮФУ, 1 курс), Белкин (ВГУ, 3 курс). Нули в знаменателе не мешают — они входят в среднее по группе.

2. EXISTS и NOT EXISTS

EXISTS (подзапрос) возвращает true, если подзапрос вернул хотя бы одну строку. Часто пишут SELECT 1 — важен факт наличия строк, а не их содержимое.

2.1. Вузы, где есть студенты 5-го курса

SELECT u.UNIVERSITY_NAME, u.CITY FROM dbo.UNIVERSITY u WHERE EXISTS ( SELECT 1 FROM dbo.STUDENT s WHERE s.UNIVERSITY_ID = u.UNIVERSITY_ID AND s.KURS = 5 ) ORDER BY u.UNIVERSITY_NAME;

Ожидается 2 вуза: БГУ (студент 16) и МГУ (студент 10).

2.2. Вузы без студентов

SELECT u.UNIVERSITY_NAME FROM dbo.UNIVERSITY u WHERE NOT EXISTS ( SELECT 1 FROM dbo.STUDENT s WHERE s.UNIVERSITY_ID = u.UNIVERSITY_ID );

В эталоне у каждого вуза есть студенты — результат 0 строк (как NOT IN в ЛР №9).

3. EXISTS по оценкам

SELECT s.SURNAME, s.NAME FROM dbo.STUDENT s WHERE EXISTS ( SELECT 1 FROM dbo.EXAM_MARKS em WHERE em.STUDENT_ID = s.STUDENT_ID AND em.MARK = 5 ) ORDER BY s.SURNAME;

Ожидается 8 студентов с хотя бы одной «5» (в эталоне — Иванов, Петров, Козлова, Волков, Кузнецов, Лебедева, Крылова и др.).

SELECT s.STUDENT_ID, s.SURNAME, s.NAME FROM dbo.STUDENT s WHERE NOT EXISTS ( SELECT 1 FROM dbo.EXAM_MARKS em WHERE em.STUDENT_ID = s.STUDENT_ID );

Ожидается 1 строка: Медведев (STUDENT_ID = 19) — тот же результат, что NOT IN на ЛР №9, но без ловушки NULL.

Результат NOT EXISTS

Результат §3 — один студент без оценок.

4. Оператор ALL

SELECT em.STUDENT_ID, em.SUBJ_ID, em.MARK FROM dbo.EXAM_MARKS em WHERE em.MARK IS NOT NULL AND em.MARK >= ALL ( SELECT em2.MARK FROM dbo.EXAM_MARKS em2 WHERE em2.SUBJ_ID = em.SUBJ_ID AND em2.MARK IS NOT NULL ) ORDER BY em.SUBJ_ID, em.STUDENT_ID;

Строки, где оценка максимальна для своего предмета. Ожидается 12 строк (несколько «лучших» по предметам 10, 43, 56, 94 и т.д.). Если для предмета одна оценка — она тоже «максимальна».

Если подзапрос после ALL пуст (нет оценок по предмету), условие для внешней строки не выполняется — такие строки не попадут в результат.

5. Файл отчёта

  1. Сохраните запросы §0–4 в lab10_FIO.sql (ФИО латиницей).
  2. В начале: -- ЛР №10, IvanovII, группа ВО-ИСИТ-31.
  3. К каждому блоку — -- rows: N и пояснение корреляции или EXISTS.
  4. Скриншоты: §1 (3 строки); §3 NOT EXISTS (Медведев); §4 (несколько SUBJ_ID).

Имя файла отчёта: lab10_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab10_IvanovII.sql.

6. Дополнительно

  1. Перепишите §3 NOT EXISTS через LEFT JOIN … WHERE em.STUDENT_ID IS NULL.
  2. Сравните время выполнения (план запроса) IN vs EXISTS для §2.1 — кратко в комментарии.
  3. WHERE STIPEND > ANY (SELECT …) — чем отличается от > ALL?

Контрольные вопросы

  1. Почему коррелированный подзапрос ссылается на s1.UNIVERSITY_ID?
  2. Чем EXISTS отличается от IN при проверке «есть строки»?
  3. Когда NOT EXISTS предпочтительнее NOT IN?
  4. Что вернёт ALL над пустым подзапросом?
  5. Зачем в EXISTS пишут SELECT 1, а не SELECT *?

Лабораторная работа №11. INNER и OUTER JOIN

Дата: 20.10.2026, вт, 14:15–15:50, ауд. 220 · Отчёт: скрипт lab11_FIO.sql (ФИО латиницей) + скриншоты результатов.

Цель: соединять таблицы через INNER JOIN и LEFT JOIN; строить отчёты по связям FK; считать агрегаты после JOIN.

Связь с ЛР №9–10: подзапрос с IN можно заменить JOIN — на этой работе учитесь читать и писать явные соединения. Схема FK — в приложении.

0. Перед началом

Нарисуйте цепочку: UNIVERSITYSTUDENTEXAM_MARKSSUBJECT; отдельно SUBJ_LECT связывает SUBJECT и LECTURER. Условие соединения — равенство ключей FK.

USE UniversityDB;

1. INNER JOIN — студент и вуз

INNER JOIN оставляет только строки, для которых есть пара в обеих таблицах. У каждого студента в эталоне есть вуз — потерь строк не будет.

1.1. Список с городом вуза

SELECT s.SURNAME, s.KURS, u.UNIVERSITY_NAME, u.CITY FROM dbo.STUDENT s INNER JOIN dbo.UNIVERSITY u ON s.UNIVERSITY_ID = u.UNIVERSITY_ID ORDER BY u.CITY, s.SURNAME;

Ожидается 19 строк — по числу студентов.

1.2. Студенты вузов не из Воронежа

SELECT s.SURNAME, u.UNIVERSITY_NAME, u.CITY FROM dbo.STUDENT s INNER JOIN dbo.UNIVERSITY u ON s.UNIVERSITY_ID = u.UNIVERSITY_ID WHERE u.CITY <> N'Воронеж' ORDER BY u.UNIVERSITY_NAME, s.SURNAME;

Ожидается 13 строк (студенты вузов в Москве, СПб, Новосибирске и т.д.; вузы ВГУ и ВГМУ в Воронеже отсеяны).

2. Несколько INNER JOIN

2.1. Ведомость: студент, предмет, оценка

SELECT s.SURNAME, sub.SUBJ_NAME, em.MARK, em.EXAM_DATE FROM dbo.EXAM_MARKS em INNER JOIN dbo.STUDENT s ON em.STUDENT_ID = s.STUDENT_ID INNER JOIN dbo.SUBJECT sub ON em.SUBJ_ID = sub.SUBJ_ID ORDER BY s.SURNAME, em.EXAM_DATE;

Ожидается 24 строки — все строки EXAM_MARKS с подставленными фамилиями и названиями предметов.

2.2. Кто какой предмет ведёт

SELECT sub.SUBJ_NAME, l.SURNAME AS lecturer_surname, l.NAME AS lecturer_name FROM dbo.SUBJ_LECT sl INNER JOIN dbo.SUBJECT sub ON sl.SUBJ_ID = sub.SUBJ_ID INNER JOIN dbo.LECTURER l ON sl.LECTURER_ID = l.LECTURER_ID ORDER BY sub.SUBJ_NAME, l.SURNAME;

Ожидается 12 строк — по таблице SUBJ_LECT в приложении.

К отчёту приложите свой скриншот вкладки Results для запроса §2.1 (ожидается 24 строки: фамилия, предмет, оценка, дата).

3. LEFT JOIN

LEFT JOIN сохраняет все строки левой таблицы; если справа нет пары — столбцы справа NULL.

3.1. Все вузы и их студенты

SELECT u.UNIVERSITY_NAME, s.SURNAME FROM dbo.UNIVERSITY u LEFT JOIN dbo.STUDENT s ON u.UNIVERSITY_ID = s.UNIVERSITY_ID ORDER BY u.UNIVERSITY_NAME, s.SURNAME;

Ожидается 19 строк с фамилиями (у каждого вуза есть студенты; «пустых» вузов нет).

3.2. Вузы без студентов

SELECT u.UNIVERSITY_NAME FROM dbo.UNIVERSITY u LEFT JOIN dbo.STUDENT s ON u.UNIVERSITY_ID = s.UNIVERSITY_ID WHERE s.STUDENT_ID IS NULL;

В эталоне — 0 строк. Запишите в отчёте: «все 8 вузов представлены студентами».

3.3. Студенты без оценок

SELECT s.STUDENT_ID, s.SURNAME, s.NAME FROM dbo.STUDENT s LEFT JOIN dbo.EXAM_MARKS em ON s.STUDENT_ID = em.STUDENT_ID WHERE em.STUDENT_ID IS NULL;

Ожидается 1 строка: Медведев (STUDENT_ID = 19) — тот же результат, что NOT EXISTS на ЛР №10.

4. Агрегаты с JOIN

SELECT u.UNIVERSITY_NAME, COUNT(s.STUDENT_ID) AS student_cnt FROM dbo.UNIVERSITY u LEFT JOIN dbo.STUDENT s ON u.UNIVERSITY_ID = s.UNIVERSITY_ID GROUP BY u.UNIVERSITY_NAME ORDER BY u.UNIVERSITY_NAME;

Ожидается 8 строк. Используйте COUNT(s.STUDENT_ID), а не COUNT(*) — иначе вуз без студентов дал бы 1 вместо 0 (в эталоне все счётчики ≥ 1).

SELECT s.SURNAME, AVG(CAST(em.MARK AS FLOAT)) AS avg_mark FROM dbo.STUDENT s LEFT JOIN dbo.EXAM_MARKS em ON s.STUDENT_ID = em.STUDENT_ID AND em.MARK IS NOT NULL GROUP BY s.SURNAME HAVING COUNT(em.MARK) > 0 ORDER BY avg_mark DESC;

Только студенты с оценками; у Медведева строки не будет. Число строк — 18 (19 − 1 без ведомости).

5. Файл отчёта

  1. Сохраните запросы §0–4 и схему связей (фото/скан) в lab11_FIO.sql или приложите схему отдельно в PDF.
  2. В начале: -- ЛР №11, IvanovII, группа ВО-ИСИТ-31.
  3. Скриншоты: §1.2; §2.1; §3.3; §4 COUNT по вузам.

Имя файла отчёта: lab11_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab11_IvanovII.sql.

6. Дополнительно

  1. Перепишите §1.2 через подзапрос IN (ЛР №9) — совпали ли строки?
  2. Чем RIGHT JOIN отличается от LEFT JOIN (поменяли таблицы местами)?
  3. Нарисуйте, что произойдёт при JOIN без условия ON (декартово произведение).

Контрольные вопросы

  1. Чем INNER JOIN отличается от LEFT JOIN на примере вузов без студентов?
  2. Почему COUNT(s.STUDENT_ID) и COUNT(*) могут различаться при LEFT JOIN?
  3. Сколько таблиц участвует в ведомости §2.2?
  4. Как найти студента без оценок через LEFT JOIN?
  5. Зачем рисовать схему связей перед сложным JOIN?

Лабораторная работа №12. UNION, EXCEPT, INTERSECT

Дата: 21.10.2026, ср, 12:30–14:05 · Отчёт: скрипт lab12_FIO.sql (ФИО латиницей) + скриншоты результатов.

Цель: объединять результаты нескольких SELECT; понять разницу UNION и UNION ALL; применить множественные операции к эталону UniversityDB.

Связь с ЛР №11: JOIN соединяет таблицы в одном запросе; UNION складывает результаты двух запросов с одинаковым числом столбцов.

0. Перед началом

USE UniversityDB;

В эталоне: 19 студентов, 10 преподавателей, 24 строки EXAM_MARKS; у Медведева (STUDENT_ID=19) нет оценок.

1. Отчёт со JOIN

Средний балл по студенту с названием вуза — закрепление ЛР №11.

SELECT s.KURS, s.SURNAME, u.UNIVERSITY_NAME, AVG(CAST(em.MARK AS FLOAT)) AS avg_mark FROM dbo.STUDENT s INNER JOIN dbo.UNIVERSITY u ON s.UNIVERSITY_ID = u.UNIVERSITY_ID LEFT JOIN dbo.EXAM_MARKS em ON s.STUDENT_ID = em.STUDENT_ID AND em.MARK IS NOT NULL GROUP BY s.KURS, s.SURNAME, u.UNIVERSITY_NAME ORDER BY s.KURS, s.SURNAME;

Ожидается 19 строк; у Медведева avg_mark = NULL.

2. UNION ALL — общий список фамилий

SELECT SURNAME, N'student' AS person_type FROM dbo.STUDENT UNION ALL SELECT SURNAME, N'lecturer' AS person_type FROM dbo.LECTURER ORDER BY SURNAME;

Ожидается 29 строк (19 студентов + 10 преподавателей).

3. INTERSECT и EXCEPT

SELECT CITY FROM dbo.STUDENT WHERE CITY IS NOT NULL INTERSECT SELECT CITY FROM dbo.UNIVERSITY ORDER BY CITY; SELECT CITY FROM dbo.STUDENT WHERE CITY IS NOT NULL EXCEPT SELECT CITY FROM dbo.UNIVERSITY ORDER BY CITY;

INTERSECT7 городов (Воронеж, Москва, Новосибирск, Санкт-Петербург, Белгород, Томск, Ростов-на-Дону). EXCEPT1 строка: Курск (есть у студентов, нет среди городов вузов).

4. UNION vs UNION ALL

Повторите §2 с UNION вместо UNION ALL. В эталоне фамилии студентов и преподавателей не пересекаются — снова 29 строк. Запишите в отчёте: UNION удаляет дубликаты между двумя наборами; UNION ALL — нет.

5. Топ предметов

SELECT TOP 5 sub.SUBJ_NAME, AVG(CAST(em.MARK AS FLOAT)) AS avg_mark FROM dbo.EXAM_MARKS em JOIN dbo.SUBJECT sub ON em.SUBJ_ID = sub.SUBJ_ID WHERE em.MARK IS NOT NULL GROUP BY sub.SUBJ_NAME HAVING COUNT(*) >= 2 ORDER BY avg_mark DESC;

Только предметы с не менее двух оценок. Ожидается до 5 строк — зафиксируйте фактическое число и значения avg_mark в комментарии -- rows: N.

6. Файл отчёта

  1. Сохраните запросы §0–5 в lab12_FIO.sql.
  2. В начале: -- ЛР №12, IvanovII, группа ВО-ИСИТ-31.
  3. Скриншоты: §3 INTERSECT и EXCEPT; §5 TOP 5.

Имя файла отчёта: lab12_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab12_IvanovII.sql.

Контрольные вопросы

  1. Почему в UNION число и типы столбцов должны совпадать?
  2. Чем UNION ALL быстрее UNION?
  3. Что вернёт INTERSECT городов студентов и вузов?
  4. Зачем HAVING COUNT(*) >= 2 в топе предметов?
  5. Когда EXCEPT полезнее NOT IN?

Лабораторная работа №13. Функции строк, чисел, дат

Дата: 27.10.2026, вт, 14:15–15:50 · Отчёт: скрипт lab13_FIO.sql (ФИО латиницей) + скриншоты результатов.

Цель: строковые и дата-функции T-SQL, ROUND, CAST на UniversityDB.

0. Перед началом

USE UniversityDB;

1. Строки

SELECT SURNAME, LEFT(NAME, 1) + N'.' + LEFT(SURNAME, 1) + N'.' AS initials, LEN(SURNAME) AS surname_len FROM dbo.STUDENT; SELECT SURNAME FROM dbo.STUDENT WHERE LEN(SURNAME) = 6; SELECT SURNAME FROM dbo.STUDENT WHERE SURNAME LIKE N'______';

Первый запрос — 19 строк. LEN(SURNAME)=68 студентов: Петров, Козлова, Новиков, Сидоров, Волков, Павлов, Белкин, Крылова.

2. Даты и возраст

SELECT SURNAME, BIRTHDAY, DATEDIFF(YEAR, BIRTHDAY, GETDATE()) AS age_years FROM dbo.STUDENT WHERE BIRTHDAY IS NOT NULL; SELECT YEAR(BIRTHDAY) AS birth_year, COUNT(*) AS cnt FROM dbo.STUDENT WHERE BIRTHDAY IS NOT NULL GROUP BY YEAR(BIRTHDAY); SELECT COUNT(*) AS exams_in_jan FROM dbo.EXAM_MARKS WHERE EXAM_DATE >= '2026-01-01' AND EXAM_DATE < '2026-02-01';

Ожидается 16 экзаменов в январе 2026 (все даты EXAM_MARKS в эталоне — 2026 год).

3. Числа

SELECT KURS, ROUND(AVG(CAST(STIPEND AS FLOAT)), 2) AS avg_st FROM dbo.STUDENT GROUP BY KURS; SELECT KURS, MAX(STIPEND) - MIN(STIPEND) AS spread FROM dbo.STUDENT GROUP BY KURS;

По каждому курсу — одна строка агрегата (курсы 1–4 в эталоне).

4. CAST

SELECT UNIVERSITY_NAME, CAST(RATING AS NVARCHAR(10)) + N' баллов' AS rating_text FROM dbo.UNIVERSITY;

Ожидается 8 строк — по числу вузов.

5. Файл отчёта

  1. Сохраните запросы §0–4 в lab13_FIO.sql.
  2. В начале: -- ЛР №13, IvanovII, группа ВО-ИСИТ-31.
  3. Скриншоты: §1 LEN=6; §2 exams_in_jan; §4 rating_text.

Имя файла отчёта: lab13_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab13_IvanovII.sql.

Контрольные вопросы

  1. Чем LEN отличается от DATALENGTH для NVARCHAR?
  2. Почему DATEDIFF(YEAR,…) может «ошибаться» на день рождения?
  3. Зачем ROUND при AVG стипендии?
  4. Почему фильтр по YEAR(BIRTHDAY) хуже диапазона дат для индекса?
  5. Зачем CAST рейтинга в NVARCHAR перед конкатенацией?

Лабораторная работа №14. CASE, ISNULL, COALESCE

Дата: 28.10.2026, ср, 12:30–14:05 · Отчёт: скрипт lab14_FIO.sql (ФИО латиницей) + скриншоты результатов.

Цель: условные выражения и обработка NULL в SELECT; студент STUDENT_ID=19 (Медведев) с CITY IS NULL.

0. Перед началом

USE UniversityDB; SELECT STUDENT_ID, SURNAME, CITY FROM dbo.STUDENT WHERE CITY IS NULL;

Ожидается 1 строка: STUDENT_ID=19, Медведев, CITY = NULL.

1. CASE для оценок

SELECT STUDENT_ID, SUBJ_ID, MARK, CASE MARK WHEN 5 THEN N'отлично' WHEN 4 THEN N'хорошо' WHEN 3 THEN N'удовлетворительно' WHEN 2 THEN N'неудовлетворительно' ELSE N'нет оценки' END AS mark_text FROM dbo.EXAM_MARKS;

Ожидается 24 строки — все записи ведомости.

2. Категории стипендии

SELECT SURNAME, STIPEND, CASE WHEN STIPEND = 0 THEN N'нет' WHEN STIPEND < 100 THEN N'низкая' WHEN STIPEND <= 150 THEN N'средняя' ELSE N'высокая' END AS stipend_cat FROM dbo.STUDENT;

Ожидается 19 строк — по каждому студенту.

3. COALESCE и ISNULL

SELECT SURNAME, COALESCE(CITY, N'не указан') AS city_display FROM dbo.STUDENT; SELECT SURNAME, ISNULL(CAST(CITY AS NVARCHAR(40)), N'не указан') AS city2 FROM dbo.STUDENT;

У Медведева в обоих запросах — не указан вместо NULL.

4. IIF и сортировка NULL

SELECT SURNAME, IIF(STIPEND > 0, N'да', N'нет') AS has_stipend FROM dbo.STUDENT; SELECT SURNAME, CITY FROM dbo.STUDENT ORDER BY CASE WHEN CITY IS NULL THEN 1 ELSE 0 END, CITY;

Во втором запросе Медведев с NULL — в конце списка.

5. GROUP BY CASE

SELECT CASE WHEN STIPEND = 0 THEN N'нет' WHEN STIPEND < 100 THEN N'низкая' WHEN STIPEND <= 150 THEN N'средняя' ELSE N'высокая' END AS cat, COUNT(*) AS cnt FROM dbo.STUDENT GROUP BY CASE WHEN STIPEND = 0 THEN N'нет' WHEN STIPEND < 100 THEN N'низкая' WHEN STIPEND <= 150 THEN N'средняя' ELSE N'высокая' END;

Ожидается 4 строки — по числу категорий стипендии.

6. Файл отчёта

  1. Сохраните запросы §0–5 в lab14_FIO.sql.
  2. В начале: -- ЛР №14, IvanovII, группа ВО-ИСИТ-31.
  3. Скриншоты: §0 NULL город; §3 COALESCE; §4 ORDER BY.

Имя файла отчёта: lab14_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab14_IvanovII.sql.

Контрольные вопросы

  1. Чем простой CASE отличается от searched CASE?
  2. Чем COALESCE отличается от ISNULL?
  3. Зачем выводить «не указан» для NULL города?
  4. Как ORDER BY CASE ставит NULL в конец?
  5. Почему GROUP BY CASE повторяет выражение из SELECT?

Лабораторная работа №15. Переменные и IF

Дата: 03.11.2026, вт, 14:15–15:50 · Отчёт: скрипт lab15_FIO.sql (ФИО латиницей) + скриншоты результатов.

Цель: объявление переменных DECLARE/SET, ветвление IF/ELSE, проверка IF EXISTS в T-SQL.

0. Перед началом

USE UniversityDB;

1. Переменная курса

DECLARE @kurs INT = 3; SELECT STUDENT_ID, SURNAME, KURS FROM dbo.STUDENT WHERE KURS = @kurs;

При @kurs = 3 ожидается 4 студента.

2. IF по средней стипендии

DECLARE @avg DECIMAL(10,2); SELECT @avg = AVG(STIPEND) FROM dbo.STUDENT WHERE STIPEND > 0; IF @avg > 120 PRINT N'Средняя стипендия выше 120: ' + CAST(@avg AS NVARCHAR(20)); ELSE PRINT N'Средняя стипендия не выше 120: ' + CAST(@avg AS NVARCHAR(20));

Результат PRINT — на вкладке Messages в SSMS.

3. IF EXISTS — студенты без оценок

IF EXISTS ( SELECT 1 FROM dbo.STUDENT s WHERE NOT EXISTS (SELECT 1 FROM dbo.EXAM_MARKS em WHERE em.STUDENT_ID = s.STUDENT_ID) ) PRINT N'Есть студенты без экзаменов'; ELSE PRINT N'У всех студентов есть оценки';

Ожидается сообщение «Есть студенты без экзаменов» (Медведев, STUDENT_ID=19).

4. Файл отчёта

  1. Сохраните запросы §0–3 в lab15_FIO.sql.
  2. В начале: -- ЛР №15, IvanovII, группа ВО-ИСИТ-31.
  3. Скриншоты: §1 SELECT при @kurs=3; §2 и §3 — вкладка Messages.

Имя файла отчёта: lab15_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab15_IvanovII.sql.

Контрольные вопросы

  1. Почему имя переменной начинается с @?
  2. Чем IF EXISTS лучше COUNT(*) > 0?
  3. Где увидеть результат PRINT в SSMS?
  4. Можно ли DECLARE @kurs внутри каждого пакета GO отдельно?
  5. Зачем фильтровать STIPEND>0 перед AVG?

Лабораторная работа №16. Циклы WHILE и TRY/CATCH

Дата: 04.11.2026, ср, 12:30–14:05 · Отчёт: скрипт lab16_FIO.sql (ФИО латиницей) + скриншоты результатов.

Цель: цикл WHILE, обработка ошибок TRY/CATCH, транзакция с откатом.

0. Перед началом

USE UniversityDB;

1. WHILE — числа 1..10

DECLARE @i INT = 1; DECLARE @nums TABLE (n INT); WHILE @i <= 10 BEGIN INSERT INTO @nums (n) VALUES (@i); SET @i = @i + 1; END SELECT * FROM @nums;

Ожидается 10 строк — числа от 1 до 10.

2. TRY/CATCH — неверный FK

BEGIN TRY UPDATE dbo.STUDENT SET UNIVERSITY_ID = 999 WHERE STUDENT_ID = 1; END TRY BEGIN CATCH SELECT ERROR_NUMBER() AS err_num, ERROR_MESSAGE() AS err_msg; END CATCH;

Ожидается строка с err_num (нарушение FK) — без изменения данных.

3. CHECK на MARK

BEGIN TRY INSERT INTO dbo.EXAM_MARKS (EXAM_ID, STUDENT_ID, SUBJ_ID, MARK, EXAM_DATE) VALUES (99999, 1, 10, 6, GETDATE()); END TRY BEGIN CATCH SELECT ERROR_NUMBER(), ERROR_MESSAGE(); END CATCH;

Оценка 6 вне диапазона CHECK — попадание в CATCH, строка не вставляется.

4. TRAN + TRY/CATCH

BEGIN TRY BEGIN TRAN; UPDATE dbo.STUDENT SET STIPEND = STIPEND - 500 WHERE STUDENT_ID = 1; UPDATE dbo.STUDENT SET STIPEND = STIPEND + 500 WHERE STUDENT_ID = 3; COMMIT TRAN; END TRY BEGIN CATCH IF @@TRANCOUNT > 0 ROLLBACK TRAN; SELECT ERROR_NUMBER(), ERROR_MESSAGE(); END CATCH;

При успехе стипендии студентов 1 и 3 не меняются в сумме; при ошибке — ROLLBACK.

5. Файл отчёта

  1. Сохраните запросы §0–4 в lab16_FIO.sql.
  2. В начале: -- ЛР №16, IvanovII, группа ВО-ИСИТ-31.
  3. Скриншоты: §1 @nums; §2 и §3 — блок CATCH.

Имя файла отчёта: lab16_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab16_IvanovII.sql.

Контрольные вопросы

  1. Чем табличная переменная @nums отличается от #temp?
  2. Что вернёт ERROR_NUMBER() при нарушении FK?
  3. Почему INSERT с MARK=6 попадает в CATCH?
  4. Зачем проверять @@TRANCOUNT перед ROLLBACK?
  5. Как связаны TRY/CATCH и лекция 5 про ACID?

Лабораторная работа №17. XML в SQL Server

Дата: 10.11.2026, вт, 14:15–15:50 · Отчёт: скрипт lab17_FIO.sql (ФИО латиницей) + скриншоты результатов.

Цель: тип XML, методы .value() и .query(); связь с лекциями 9–10.

0. Перед началом

USE UniversityDB;

1. Таблица с XML

IF OBJECT_ID(N'dbo.UnivXml', N'U') IS NOT NULL DROP TABLE dbo.UnivXml; CREATE TABLE dbo.UnivXml ( univ_id INT NOT NULL PRIMARY KEY, payload XML NOT NULL );

2. Загрузка фрагмента ВГУ

INSERT INTO dbo.UnivXml (univ_id, payload) VALUES (10, N'<Univ id="10"> <Name>Воронежский государственный университет</Name> <City>Воронеж</City> <Student id="1" kurs="2">Иванов</Student> <Student id="3" kurs="3">Петров</Student> </Univ>');

Ожидается 1 строка в UnivXml для univ_id=10 (ВГУ).

3. value() — одно поле

SELECT univ_id, payload.value(N'(/Univ/Name)[1]', N'NVARCHAR(80)') AS univ_name, payload.value(N'(/Univ/City)[1]', N'NVARCHAR(40)') AS city FROM dbo.UnivXml;

Ожидается название ВГУ и город Воронеж.

4. query() — список студентов

SELECT univ_id, payload.query(N'//Student') AS students_xml FROM dbo.UnivXml; SELECT stu.stu.value(N'@id', N'int') AS student_id, stu.stu.value(N'.', N'NVARCHAR(50)') AS surname FROM dbo.UnivXml x CROSS APPLY x.payload.nodes(N'//Student') AS stu(stu);

Во втором запросе — 2 строки (Иванов, Петров из XML).

5. PRIMARY XML INDEX (обзорно)

Если права позволяют:

CREATE PRIMARY XML INDEX PXI_UnivXml ON dbo.UnivXml(payload);

Иначе в отчёте опишите: индекс ускоряет XPath-запросы к большим документам.

6. Файл отчёта

  1. Сохраните запросы §0–5 в lab17_FIO.sql.
  2. В начале: -- ЛР №17, IvanovII, группа ВО-ИСИТ-31.
  3. Скриншоты: §3 value(); §4 nodes().

Имя файла отчёта: lab17_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab17_IvanovII.sql.

Контрольные вопросы

  1. Чем XML-столбец отличается от NVARCHAR(MAX)?
  2. Что делает .value() с XPath (/Univ/Name)[1]?
  3. Зачем CROSS APPLY … nodes()?
  4. Когда нужен PRIMARY XML INDEX?
  5. Как XML в этой работе связан с лекцией 10?

Лабораторная работа №18. Иерархические данные

Дата: 11.11.2026, ср, 12:30–14:05 · Отчёт: скрипт lab18_FIO.sql (ФИО латиницей) + скриншоты результатов.

Цель: рекурсивный CTE по таблице ORG_UNIT в UniversityDB; сравнение adjacency list и nested sets.

0. Перед началом

USE UniversityDB; SELECT * FROM dbo.ORG_UNIT ORDER BY UNIT_ID;

В эталоне 10 строк в ORG_UNIT (иерархии ВГУ и МГУ).

1. Рекурсивный CTE — потомки ВГУ

WITH org_tree AS ( SELECT UNIT_ID, UNIT_NAME, PARENT_ID, CAST(UNIT_NAME AS NVARCHAR(400)) AS path, 0 AS lvl FROM dbo.ORG_UNIT WHERE UNIT_ID = 1 UNION ALL SELECT c.UNIT_ID, c.UNIT_NAME, c.PARENT_ID, CAST(p.path + N' / ' + c.UNIT_NAME AS NVARCHAR(400)), p.lvl + 1 FROM dbo.ORG_UNIT c INNER JOIN org_tree p ON c.PARENT_ID = p.UNIT_ID ) SELECT UNIT_ID, UNIT_NAME, path, lvl FROM org_tree ORDER BY path;

От корня UNIT_ID=1 (ВГУ) ожидается 7 строк — всё поддерево вуза 10.

2. Отступ в отчёте

WITH org_tree AS ( SELECT UNIT_ID, UNIT_NAME, PARENT_ID, 0 AS lvl FROM dbo.ORG_UNIT WHERE UNIT_ID = 1 UNION ALL SELECT c.UNIT_ID, c.UNIT_NAME, c.PARENT_ID, p.lvl + 1 FROM dbo.ORG_UNIT c JOIN org_tree p ON c.PARENT_ID = p.UNIT_ID ) SELECT REPLICATE(N' ', lvl) + UNIT_NAME AS tree_view, lvl FROM org_tree ORDER BY UNIT_ID;

Столбец lvl — уровень вложенности (0 у ректората, 1 у факультетов и т.д.).

3. Теория в отчёте

Кратко сравните adjacency list (PARENT_ID, как в ORG_UNIT) и nested sets (left/right): плюсы и минусы каждой модели.

4. Файл отчёта

  1. Сохраните запросы §0–2 в lab18_FIO.sql.
  2. В начале: -- ЛР №18, IvanovII, группа ВО-ИСИТ-31.
  3. Скриншоты: §1 path/lvl; §2 tree_view.

Имя файла отчёта: lab18_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab18_IvanovII.sql.

Контрольные вопросы

  1. Где в CTE задаётся якорь рекурсии?
  2. Что будет, если в PARENT_ID появится цикл?
  3. Зачем столбец lvl или path в результате?
  4. Когда nested sets выигрывают у parent_id?
  5. Как ORG_UNIT связана с иерархией подразделений вуза?

Лабораторная работа №19. MongoDB — нереляционная БД

Дата: 17.11.2026, вт, 14:15–15:50 · Отчёт: скриншоты Compass + lab19_FIO.pdf (ФИО латиницей).

Цель: документная модель в MongoDB Compass; сравнение с реляционной строкой dbo.STUDENT.

Стенд: MongoDB Compass на учебном ПК (или MongoDB Atlas по указанию преподавателя). SQL Server для сравнения — UniversityDB.

0. Перед началом

  1. Установите/откройте MongoDB Compass.
  2. Создайте базу University и коллекцию students.
  3. В SSMS выполните USE UniversityDB; — данные для документов возьмите из STUDENT + UNIVERSITY.

1. Пять документов

Вставьте минимум пять документов с полями _id, surname, name, kurs, вложенный объект university: { name, city }:

{ "_id": 1, "surname": "Иванов", "name": "Иван", "kurs": 2, "university": { "name": "ВГУ", "city": "Воронеж" } }

Данные можно взять из:

SELECT TOP 5 s.STUDENT_ID, s.SURNAME, s.NAME, s.KURS, u.UNIVERSITY_NAME, u.CITY FROM dbo.STUDENT s JOIN dbo.UNIVERSITY u ON s.UNIVERSITY_ID = u.UNIVERSITY_ID;

Ожидается 5 документов в коллекции students.

2. find, filter, projection

db.students.find({ "kurs": 3 }) db.students.find( { "kurs": { "$gte": 2 } }, { surname: 1, kurs: 1, "university.city": 1 } )

Зафиксируйте число документов при фильтре kurs: 3 — в эталоне SQL при KURS=3 четыре студента.

3. insert, update, delete

db.students.insertOne({ "_id": 99, "surname": "Тестов", "kurs": 1 }) db.students.updateOne({ "_id": 99 }, { "$set": { "kurs": 2 } }) db.students.deleteOne({ "_id": 99 })

После deleteOne документ 99 отсутствует — приложите скриншот.

4. Отчёт PDF

  1. Оформите lab19_FIO.pdf: скриншоты Compass, примеры запросов.
  2. Ответьте: чем документ MongoDB отличается от строки STUDENT+JOIN UNIVERSITY.
  3. Укажите, где в документе денормализация (город вуза внутри студента).

Имя файла отчёта: lab19_FIO.pdf (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab19_IvanovII.pdf.

Контрольные вопросы

  1. Чем коллекция MongoDB отличается от таблицы SQL Server?
  2. Зачем вложенный объект university вместо UNIVERSITY_ID?
  3. Чем find с projection отличается от SELECT с списком столбцов?
  4. Когда денормализация в MongoDB оправдана?
  5. Какие аномалии обновления появляются при дублировании city в каждом документе?

Лабораторная работа №20. Представления VIEW

Дата: 18.11.2026, ср, 12:30–14:05 · Отчёт: скрипт lab20_FIO.sql (ФИО латиницей) + скриншоты результатов.

Цель: создать представления VIEW на UniversityDB, упростить доступ к JOIN и проверить чтение через представление.

Связь с лекцией 12: VIEW — сохранённый запрос с именем, а не копия таблицы.

0. Перед началом

USE UniversityDB;

1. VIEW студент + вуз

CREATE OR ALTER VIEW dbo.v_StudentUniv AS SELECT s.STUDENT_ID, s.SURNAME, s.NAME, s.KURS, u.UNIVERSITY_NAME, u.CITY, u.RATING FROM dbo.STUDENT s INNER JOIN dbo.UNIVERSITY u ON s.UNIVERSITY_ID = u.UNIVERSITY_ID; GO SELECT TOP 10 * FROM dbo.v_StudentUniv ORDER BY SURNAME;

VIEW содержит 19 строк — по числу студентов.

2. VIEW успеваемости

CREATE OR ALTER VIEW dbo.v_StudentMarks AS SELECT s.STUDENT_ID, s.SURNAME, sub.SUBJ_NAME, em.MARK, em.EXAM_DATE FROM dbo.EXAM_MARKS em JOIN dbo.STUDENT s ON em.STUDENT_ID = s.STUDENT_ID JOIN dbo.SUBJECT sub ON em.SUBJ_ID = sub.SUBJ_ID; GO SELECT * FROM dbo.v_StudentMarks WHERE MARK = 5;

Во VIEW — 24 строки; фильтр MARK=59 пятёрок в эталоне.

3. SCHEMABINDING (обзорно)

Объясните в комментарии к скрипту: WITH SCHEMABINDING защищает определение VIEW от изменения базовых столбцов.

4. Удаление VIEW

-- в конце работы по договорённости: -- DROP VIEW IF EXISTS dbo.v_StudentMarks; -- DROP VIEW IF EXISTS dbo.v_StudentUniv;

5. Файл отчёта

  1. Сохраните запросы §0–4 в lab20_FIO.sql.
  2. В начале: -- ЛР №20, IvanovII, группа ВО-ИСИТ-31.
  3. Скриншот SELECT из v_StudentUniv и v_StudentMarks WHERE MARK=5.

Имя файла отчёта: lab20_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab20_IvanovII.sql.

Контрольные вопросы

  1. Чем VIEW отличается от таблицы в Object Explorer?
  2. Обновляются ли данные в VIEW при изменении STUDENT?
  3. Зачем прятать JOIN за v_StudentUniv для пользователя отчётов?
  4. Можно ли INSERT в простой VIEW — когда да?
  5. Как VIEW связано с INSTEAD OF триггером (ЛР №22)?

Лабораторная работа №21. Хранимые процедуры

Дата: 24.11.2026, вт, 14:15–15:50 · Отчёт: скрипт lab21_FIO.sql (ФИО латиницей) + скриншоты результатов.

Цель: создать и вызвать хранимые процедуры на T-SQL, в том числе usp_StudentByKurs из лекции 12.

0. Перед началом

USE UniversityDB;

1. Процедура usp_StudentByKurs

CREATE OR ALTER PROC dbo.usp_StudentByKurs @kurs INT AS BEGIN SET NOCOUNT ON; SELECT STUDENT_ID, SURNAME, NAME, KURS, UNIVERSITY_ID FROM dbo.STUDENT WHERE KURS = @kurs ORDER BY SURNAME; END; GO EXEC dbo.usp_StudentByKurs @kurs = 2; EXEC dbo.usp_StudentByKurs @kurs = 3;

При @kurs = 3 ожидается 4 студента.

2. Процедура со средней стипендией по вузу

CREATE OR ALTER PROC dbo.usp_AvgStipendByUniv @univ_id INT AS BEGIN SELECT @univ_id AS university_id, AVG(CAST(STIPEND AS FLOAT)) AS avg_stipend FROM dbo.STUDENT WHERE UNIVERSITY_ID = @univ_id AND STIPEND > 0; END; GO EXEC dbo.usp_AvgStipendByUniv @univ_id = 10;

3. OUTPUT-параметр (дополнительно)

CREATE OR ALTER PROC dbo.usp_AvgStipendOut @univ_id INT, @avg DECIMAL(10,2) OUTPUT AS BEGIN SELECT @avg = AVG(CAST(STIPEND AS FLOAT)) FROM dbo.STUDENT WHERE UNIVERSITY_ID = @univ_id AND STIPEND > 0; END; GO DECLARE @result DECIMAL(10,2); EXEC dbo.usp_AvgStipendOut @univ_id = 10, @avg = @result OUTPUT; SELECT @result AS avg_stipend;

4. Очистка

-- DROP PROC IF EXISTS dbo.usp_AvgStipendOut; -- DROP PROC IF EXISTS dbo.usp_AvgStipendByUniv; -- DROP PROC IF EXISTS dbo.usp_StudentByKurs;

5. Файл отчёта

  1. Сохраните запросы §0–4 в lab21_FIO.sql.
  2. В начале: -- ЛР №21, IvanovII, группа ВО-ИСИТ-31.
  3. Скриншоты: EXEC @kurs=3; OUTPUT @result.

Имя файла отчёта: lab21_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab21_IvanovII.sql.

Контрольные вопросы

  1. Чем EXEC процедуры отличается от ad-hoc SELECT?
  2. Зачем SET NOCOUNT ON внутри процедуры?
  3. Как передать OUTPUT-параметр при EXEC?
  4. Почему логику usp_StudentByKurs удобно хранить на сервере?
  5. Как GRANT EXECUTE связано с ЛР №23?

Лабораторная работа №22. Триггеры DML и INSTEAD OF

Дата: 01.12.2026, вт, 12:30–14:05 · Отчёт: скрипт lab22_FIO.sql (ФИО латиницей) + скриншоты результатов.

Цель: создать AFTER-триггер аудита на EXAM_MARKS и INSTEAD OF INSERT на представление v_StudentUniv.

0. Перед началом

USE UniversityDB; IF OBJECT_ID(N'dbo.v_StudentUniv', N'V') IS NULL EXEC(N'CREATE VIEW dbo.v_StudentUniv AS SELECT s.*, u.UNIVERSITY_NAME FROM dbo.STUDENT s JOIN dbo.UNIVERSITY u ON s.UNIVERSITY_ID = u.UNIVERSITY_ID');

1. Таблица аудита

IF OBJECT_ID(N'dbo.AuditLog', N'U') IS NULL CREATE TABLE dbo.AuditLog ( log_id INT IDENTITY(1,1) PRIMARY KEY, evt NVARCHAR(100) NOT NULL, evt_time DATETIME2 NOT NULL DEFAULT SYSDATETIME() );

2. AFTER INSERT, UPDATE, DELETE

CREATE OR ALTER TRIGGER dbo.trg_ExamAudit ON dbo.EXAM_MARKS AFTER INSERT, UPDATE, DELETE AS BEGIN SET NOCOUNT ON; INSERT INTO dbo.AuditLog (evt) VALUES (N'EXAM_MARKS changed'); END; GO

Измените оценку в транзакции с ROLLBACK и проверьте SELECT * FROM dbo.AuditLog; — после ROLLBACK записей аудита не останется.

3. Запрет уменьшения оценки

CREATE OR ALTER TRIGGER dbo.trg_ExamNoDowngrade ON dbo.EXAM_MARKS AFTER UPDATE AS BEGIN IF EXISTS ( SELECT 1 FROM inserted i JOIN deleted d ON i.EXAM_ID = d.EXAM_ID WHERE i.MARK < d.MARK ) BEGIN RAISERROR(N'Нельзя уменьшать оценку', 16, 1); ROLLBACK TRAN; END END; GO

4. INSTEAD OF INSERT на VIEW

CREATE OR ALTER TRIGGER dbo.trg_StudentUnivInsert ON dbo.v_StudentUniv INSTEAD OF INSERT AS BEGIN INSERT INTO dbo.STUDENT (STUDENT_ID, NAME, SURNAME, KURS, UNIVERSITY_ID, STIPEND, CITY, BIRTHDAY) SELECT i.STUDENT_ID, i.NAME, i.SURNAME, i.KURS, u.UNIVERSITY_ID, 0, u.CITY, NULL FROM inserted i JOIN dbo.UNIVERSITY u ON u.UNIVERSITY_NAME = i.UNIVERSITY_NAME; END; GO

Объясните в отчёте: VIEW с JOIN не всегда updatable — INSTEAD OF перенаправляет INSERT на базовые таблицы.

5. Очистка

DROP TRIGGER IF EXISTS dbo.trg_StudentUnivInsert ON dbo.v_StudentUniv; DROP TRIGGER IF EXISTS dbo.trg_ExamNoDowngrade ON dbo.EXAM_MARKS; DROP TRIGGER IF EXISTS dbo.trg_ExamAudit ON dbo.EXAM_MARKS;

6. Файл отчёта

  1. Сохраните запросы §0–5 в lab22_FIO.sql.
  2. В начале: -- ЛР №22, IvanovII, группа ВО-ИСИТ-31.
  3. Скриншоты: AuditLog; ошибка при уменьшении оценки.

Имя файла отчёта: lab22_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab22_IvanovII.sql.

Контрольные вопросы

  1. Чем таблицы inserted и deleted отличаются в триггере?
  2. Когда нужен AFTER, а когда INSTEAD OF?
  3. Почему INSERT в v_StudentUniv без триггера может не работать?
  4. Зачем ROLLBACK внутри триггера при RAISERROR?
  5. Чем триггер отличается от CHECK constraint?

Лабораторная работа №23. GRANT, REVOKE, роли

Дата: 02.12.2026, ср, 12:30–14:05 · Отчёт: скрипт lab23_FIO.sql (ФИО латиницей) + скриншоты результатов.

Цель: login, user, database role; выдать минимальные права на UniversityDB; связь с лекцией 14.

На общем сервере класса создавайте логины только по указанию преподавателя; в конце работы удалите тестовые учётные записи.

0. Перед началом

USE UniversityDB;

1. Логины и пользователи (на тестовом экземпляре)

USE master; CREATE LOGIN reader_test WITH PASSWORD = N'Strong_Pass_123!', CHECK_POLICY = OFF; CREATE LOGIN clerk_test WITH PASSWORD = N'Strong_Pass_456!', CHECK_POLICY = OFF; USE UniversityDB; CREATE USER reader_user FOR LOGIN reader_test; CREATE USER clerk_user FOR LOGIN clerk_test;

2. Роли

CREATE ROLE role_read; CREATE ROLE role_marks; GRANT SELECT ON dbo.STUDENT TO role_read; GRANT SELECT ON dbo.UNIVERSITY TO role_read; GRANT SELECT, INSERT, UPDATE ON dbo.EXAM_MARKS TO role_marks; ALTER ROLE role_read ADD MEMBER reader_user; ALTER ROLE role_marks ADD MEMBER clerk_user;

3. Проверка отказа

Подключитесь вторым окном SSMS как reader_test и попробуйте:

INSERT INTO dbo.STUDENT (STUDENT_ID, NAME, SURNAME, KURS, UNIVERSITY_ID, STIPEND) VALUES (90, N'X', N'X', 1, 10, 0);

Ожидается отказ — нет INSERT на STUDENT (только SELECT через role_read).

4. REVOKE и EXECUTE

REVOKE SELECT ON dbo.LECTURER FROM role_read; GRANT EXECUTE ON dbo.usp_StudentByKurs TO role_read;

После GRANT EXECUTE пользователь reader_test может вызвать процедуру без прямого SELECT на LECTURER.

5. Очистка

DROP USER IF EXISTS reader_user; DROP USER IF EXISTS clerk_user; USE master; DROP LOGIN IF EXISTS reader_test; DROP LOGIN IF EXISTS clerk_test;

6. Файл отчёта

  1. Сохраните скрипт §0–5 в lab23_FIO.sql.
  2. В начале: -- ЛР №23, IvanovII, группа ВО-ИСИТ-31.
  3. Скриншоты: ошибка INSERT под reader_test; успешный SELECT или EXEC.

Имя файла отчёта: lab23_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab23_IvanovII.sql.

Контрольные вопросы

  1. Чем login отличается от user в базе?
  2. Зачем принцип минимальных привилегий для ФИО студентов?
  3. Почему reader не может INSERT в STUDENT после GRANT SELECT?
  4. Зачем GRANT EXECUTE на процедуру вместо SELECT на таблицу?
  5. Что произойдёт, если не DROP LOGIN после лабораторной?

Лабораторная работа №24. Восстановление данных и итоговый практикум

Дата: 08.12.2026, вт, 14:15–15:50 · Отчёт: lab24_FIO.sql (ФИО латиницей) + защита.

Цель: резервное копирование и восстановление (лекции 13–14) + комплексный практикум по материалам семестра на UniversityDB.

0. Перед началом

  1. Убедитесь, что UniversityDB в эталонном состоянии: 19 студентов, 24 оценки.
  2. Согласуйте с преподавателем каталог для файлов .bak на учебном сервере.
USE UniversityDB; SELECT COUNT(*) AS student_cnt FROM dbo.STUDENT; SELECT COUNT(*) AS mark_cnt FROM dbo.EXAM_MARKS;

Часть A. Резервное копирование и восстановление

A.1. Полная копия

BACKUP DATABASE UniversityDB TO DISK = N'C:\Temp\univ_lab24_full.bak' WITH INIT, STATS = 10;

A.2. Изменение данных

BEGIN TRAN; UPDATE dbo.STUDENT SET STIPEND = STIPEND + 100 WHERE KURS = 1; SELECT SURNAME, STIPEND FROM dbo.STUDENT WHERE KURS = 1; ROLLBACK TRAN;

A.3. Восстановление на копию базы

RESTORE DATABASE UniversityDB_restore FROM DISK = N'C:\Temp\univ_lab24_full.bak' WITH MOVE N'UniversityDB' TO N'C:\Temp\univ_restore.mdf', MOVE N'UniversityDB_log' TO N'C:\Temp\univ_restore_log.ldf', REPLACE, RECOVERY;

Если нет прав — приложите скриншоты SSMS и текстовый план RESTORE.

A.4. Теория в отчёте

Опишите цепочку FULL / DIFF / LOG backup и когда нужен STOPAT.

Часть B. Итоговый практикум (8 из 10)

Выполните минимум восемь пунктов ниже; каждый — отдельный блок в lab24_FIO.sql с комментарием.

  1. JOIN трёх таблиц + фильтр по городу или курсу.
  2. GROUP BY + HAVING (средний балл по предметам).
  3. Подзапрос или EXISTS (студенты без оценок — ожидается Медведев).
  4. CREATE VIEW + SELECT из VIEW.
  5. Процедура usp_StudentByKurs с @kurs=34 строки.
  6. AFTER-триггер аудита (с DROP TRIGGER в конце скрипта).
  7. План запроса: Index Seek vs Scan для фильтра по CITY.
  8. Демонстрация GRANT/REVOKE или описание, если нет прав.
  9. Рекурсивный CTE по ORG_UNIT от UNIT_ID=17 строк.
  10. Фрагмент XML в dbo.UnivXml (если таблица ещё есть с ЛР №17).

Файл отчёта

  1. Сохраните части A и B в lab24_FIO.sql.
  2. В начале: -- ЛР №24, IvanovII, группа ВО-ИСИТ-31.
  3. Подготовьтесь к защите на занятии.

Имя файла отчёта: lab24_FIO.sql (ФИО латиницей) — вместо FIO подставьте фамилию и инициалы латиницей, например lab24_IvanovII.sql.

Контрольные вопросы

  1. Чем BACKUP DATABASE отличается от RESTORE DATABASE?
  2. Зачем восстанавливать на UniversityDB_restore, а не поверх боевой базы?
  3. Какие три темы SQL вы считаете сильными после семестра?
  4. Что проверяет экзамен по дисциплине?
  5. Как связаны лабораторные №1–24 с лекциями курса?

Учебный план

ТемаВидЧасыМатериал курса
Раздел 1. Основы баз данных и проектирование (нед. 1–3)
1Основные понятия баз данных и СУБДЛек2Л.1
2SSMS: системные и учебные БДЛаб2ЛР №1
3Реляционная модель. Функциональные зависимостиЛек2Л.2
4Таблицы и первый SELECTЛаб2ЛР №2
5Нормализация. Аномалии обновленияЛек2Л.3
6DDL: CREATE, типы, ограниченияЛаб2ЛР №3
7FK, ALTER TABLE, индексыЛаб2ЛР №4
Раздел 2. SQL: выборка и изменение данных (нед. 4)
8Многопользовательские и распределённые БДЛек2Л.4
9INSERT, SELECT, WHEREЛаб2ЛР №5
10UPDATE, DELETE, ORDER BYЛаб2ЛР №6
Раздел 3. Транзакции и многопользовательский доступ (нед. 5–8)
11Транзакции. Свойства ACIDЛек2Л.5
12Агрегатные функцииЛаб2ЛР №7
13GROUP BY, HAVING, ROLLUPЛаб2ЛР №8
14Аномалии параллельного доступаЛек2Л.6
15Вложенные подзапросыЛаб2ЛР №9
16Коррелированные подзапросы и EXISTSЛаб2ЛР №10
17Уровни изоляции транзакцийЛек2Л.7
18INNER и OUTER JOINЛаб2ЛР №11
19UNION, EXCEPT, INTERSECTЛаб2ЛР №12
20Блокировки, тупики, репликацияЛек2Л.8
21Функции строк, чисел, датЛаб2ЛР №13
22CASE, 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
27XML в SQL ServerЛаб2ЛР №17
28Иерархические данныеЛаб2ЛР №18
Раздел 5. Администрирование и программирование в СУБД (нед. 11–12)
29Администрирование и мониторинг СУБДЛек2Л.11
30MongoDB — документная БДЛаб2ЛР №19
31Представления VIEWЛаб2ЛР №20
32Программирование в БД: процедуры, триггерыЛек2Л.12
33Хранимые процедурыЛаб2ЛР №21
34Триггеры DML и INSTEAD OFЛаб2ЛР №22
Раздел 6. Резервное копирование и защита данных (нед. 13–14)
35Резервное копированиеЛек2Л.13
36GRANT, REVOKE, ролиЛаб2ЛР №23
37Восстановление данных и защитаЛек2Л.14
38Восстановление данных и итоговый практикумЛаб2ЛР №24
Раздел 7. Распределённые БД и хранилища данных (нед. 15–16)
39Распределённые БД и двухфазная фиксацияЛек2Л.15 · курсовые №6, 21
40Хранилища данных и подготовка к экзаменуЛек2Л.16 · билеты
Раздел 8. Итоговая аттестация
41Экзамен по дисциплине «Управление данными»ИКР2,3Экзамен · вопросы

Соответствие лекций и лабораторных

Краткая карта: какая лекция подводит к каким ЛР на UniversityDB (ЛР №19 — MongoDB).

ЛекцияТемаЛРНа практике
Л.1Понятия БД, СУБД, SSMS№1CREATE DATABASE, подключение
Л.2Реляционная модель, ФЗ№2таблицы, INSERT, SELECT
Л.3Нормализация, ключи№3–4DDL, FK, ALTER, индексы
Л.4Многопользовательский доступ№5–6DML, WHERE, UPDATE, DELETE
Л.5ACID, транзакции№7–8агрегаты, GROUP BY
Л.6Аномалии параллельного доступа№9–10подзапросы, EXISTS
Л.7Уровни изоляции№11–12JOIN, UNION
Л.8Блокировки, тупики, репликация№13–14функции, CASE
Л.9Структурированные / неструктурированные данные№15–16переменные, TRY/CATCH
Л.10XML, XSD№17–18XML в SQL Server, CTE-иерархии
Л.11Администрирование, мониторинг№19–20MongoDB, VIEW
Л.12Процедуры, триггеры, планы№21–22процедуры, триггеры
Л.13Резервное копирование№23GRANT, роли
Л.14Восстановление, защита данных№24BACKUP/RESTORE + практикум
Л.15Распределённые БД, 2PCтеория · курсовые №6, 21
Л.16OLAP, подготовка к экзаменувопросы · билеты

Объём занятий

ВидКоличествоАкадем. часы
Лекции16 пар32
Лабораторные24 пары48
Итого контакт40 пар80
Экзамен (ИКР)12,3

Курсовая работа

Что должно быть в любой курсовой (минимум)

  1. Предметная область — краткое описание задачи «своими словами» (1–2 страницы): кто пользуется системой, какие данные хранятся, зачем нужна БД.
  2. Проектирование — ER-диаграмма (сущности, связи 1:N и M:N), список функциональных зависимостей, обоснование нормализации (1НФ–3НФ) и выбор ключей.
  3. Реализация в SQL Server — отдельная база Kursovaya_FIO (или согласованное имя); не менее 5 таблиц с PRIMARY KEY, FOREIGN KEY, минимум два ограничения CHECK или UNIQUE; осмысленное наполнение (не «пустые таблицы»).
  4. Запросы и логика — не менее 8 SQL-запросов разного типа: SELECT с WHERE, JOIN, агрегаты с GROUP BY/HAVING, подзапрос или EXISTS; плюс один из элементов серверного программирования: VIEW, хранимая процедура или AFTER-триггер (аудит или бизнес-правило).
  5. Надёжность данных — один сценарий с BEGIN TRAN … COMMIT/ROLLBACK (операция из нескольких шагов) или демонстрация резервного копирования своей базы (BACKUP / описание RESTORE).
  6. Отчёт — скрипт 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 для витрины заказов.
16IT-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

UniversityDB — учебная база курса: вузы, студенты, преподаватели, предметы, оценки. На ней выполняются почти все лабораторные (кроме отдельных схем вроде «Библиотека» на ЛР №3). После лабораторных с изменением данных (DML, триггеры) базу можно восстановить, заново выполнив блоки ниже.

Что такое SQL-скрипт и откуда он взялся

SQL-скрипт — это обычный текст с командами T-SQL: создание таблиц, вставка строк, запросы. В SSMS его набирают или вставляют в окно New Query и выполняют клавишей F5 (или кнопкой Execute). Сервер выполняет команды и сохраняет результат в файлах базы на диске — не в окне SSMS.

Эталонный скрипт UniversityDB собран для этого курса и лежит на этой странице — отдельного файла скачивать не нужно. Ниже он разбит на блоки с пояснениями. На ЛР №2 вы копируете блоки по порядку в SSMS и сохраняете свою копию в файл lab02_FIO.sql (ФИО латиницей) — это уже ваш рабочий файл, а не «чужой скрипт из ниоткуда».

  1. Откройте SSMS, подключитесь к серверу, выберите базу UniversityDB.
  2. New Query — вставьте блок 1 (или пропустите, если база уже создана на ЛР №1).
  3. Блоки 3–5 — CREATE TABLE. Блок 6 — INSERT. Между частями с GO можно выполнять по очереди.
  4. Таблицы ниже на странице — те же данные в виде, удобном для чтения; в SSMS нужен именно SQL из блоков.

Схема связей

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 (иерархия).

Сборка базы по шагам (SQL Server)

Выполняйте блоки по порядку. Если база пустая после ЛР №1, блок 2 можно пропустить.

Блок 1. База данных

Создаёт базу UniversityDB, если её ещё нет, и переключает контекст на неё. На ЛР №1 вы уже делали то же командой CREATE DATABASE — здесь повтор для полного эталона.

-- UniversityDB для Microsoft SQL Server IF DB_ID(N'UniversityDB') IS NULL CREATE DATABASE UniversityDB; GO USE UniversityDB; GO SET NOCOUNT ON;

Блок 2. Очистка старых таблиц (по необходимости)

Нужен только если таблицы уже создавали и хотите пересобрать схему с нуля. Удаление идёт от зависимых таблиц к независимым — иначе СУБД не даст удалить родительскую таблицу.

IF OBJECT_ID('dbo.SUBJ_LECT') IS NOT NULL DROP TABLE dbo.SUBJ_LECT; IF OBJECT_ID('dbo.EXAM_MARKS') IS NOT NULL DROP TABLE dbo.EXAM_MARKS; IF OBJECT_ID('dbo.ORG_UNIT') IS NOT NULL DROP TABLE dbo.ORG_UNIT; IF OBJECT_ID('dbo.STUDENT') IS NOT NULL DROP TABLE dbo.STUDENT; IF OBJECT_ID('dbo.LECTURER') IS NOT NULL DROP TABLE dbo.LECTURER; IF OBJECT_ID('dbo.SUBJECT') IS NOT NULL DROP TABLE dbo.SUBJECT; IF OBJECT_ID('dbo.UNIVERSITY') IS NOT NULL DROP TABLE dbo.UNIVERSITY; GO

Блок 3. Справочники без внешних ключей

Таблицы, на которые ссылаются другие: список вузов и список предметов. Создаются первыми.

CREATE TABLE dbo.UNIVERSITY ( UNIVERSITY_ID INT CONSTRAINT PK_UNIVERSITY PRIMARY KEY, UNIVERSITY_NAME NVARCHAR(80) NOT NULL, RATING INT, CITY NVARCHAR(40) NOT NULL ); CREATE TABLE dbo.SUBJECT ( SUBJ_ID INT CONSTRAINT PK_SUBJECT PRIMARY KEY, SUBJ_NAME NVARCHAR(80) NOT NULL, HOUR INT NOT NULL, SEMESTER INT NOT NULL, CONSTRAINT CK_SUBJECT_HOUR CHECK (HOUR > 0), CONSTRAINT CK_SUBJECT_SEM CHECK (SEMESTER BETWEEN 1 AND 12) ); GO

Блок 4. Студенты и преподаватели

У каждой строки — ссылка UNIVERSITY_ID на справочник вузов (внешний ключ). Именно так устроена схема из лекции 2.

CREATE TABLE dbo.STUDENT ( STUDENT_ID INT CONSTRAINT PK_STUDENT PRIMARY KEY, SURNAME NVARCHAR(50) NOT NULL, NAME NVARCHAR(50) NOT NULL, STIPEND DECIMAL(10,2) NOT NULL CONSTRAINT DF_STIPEND DEFAULT (0), KURS INT NOT NULL, CITY NVARCHAR(40) NULL, BIRTHDAY DATE NULL, UNIVERSITY_ID INT NOT NULL, CONSTRAINT CK_STUDENT_KURS CHECK (KURS BETWEEN 1 AND 6), CONSTRAINT CK_STUDENT_STIP CHECK (STIPEND >= 0), CONSTRAINT FK_STUDENT_UNIVERSITY FOREIGN KEY (UNIVERSITY_ID) REFERENCES dbo.UNIVERSITY(UNIVERSITY_ID) ); CREATE TABLE dbo.LECTURER ( LECTURER_ID INT CONSTRAINT PK_LECTURER PRIMARY KEY, SURNAME NVARCHAR(50) NOT NULL, NAME NVARCHAR(50) NOT NULL, CITY NVARCHAR(40) NOT NULL, UNIVERSITY_ID INT NOT NULL, CONSTRAINT FK_LECTURER_UNIVERSITY FOREIGN KEY (UNIVERSITY_ID) REFERENCES dbo.UNIVERSITY(UNIVERSITY_ID) ); GO

Блок 5. Оценки, связи и подразделения

EXAM_MARKS — оценка студента по предмету. SUBJ_LECT — кто какой предмет ведёт. ORG_UNIT — иерархия кафедр (нужна на ЛР №18).

CREATE TABLE dbo.EXAM_MARKS ( EXAM_ID INT CONSTRAINT PK_EXAM PRIMARY KEY, STUDENT_ID INT NOT NULL, SUBJ_ID INT NOT NULL, MARK INT NULL, EXAM_DATE DATE NOT NULL, CONSTRAINT CK_MARK CHECK (MARK IS NULL OR MARK BETWEEN 2 AND 5), CONSTRAINT FK_EXAM_ST FOREIGN KEY (STUDENT_ID) REFERENCES dbo.STUDENT(STUDENT_ID), CONSTRAINT FK_EXAM_SUB FOREIGN KEY (SUBJ_ID) REFERENCES dbo.SUBJECT(SUBJ_ID) ); CREATE TABLE dbo.SUBJ_LECT ( LECTURER_ID INT NOT NULL, SUBJ_ID INT NOT NULL, CONSTRAINT PK_SUBJ_LECT PRIMARY KEY (LECTURER_ID, SUBJ_ID), CONSTRAINT FK_SL_L FOREIGN KEY (LECTURER_ID) REFERENCES dbo.LECTURER(LECTURER_ID), CONSTRAINT FK_SL_S FOREIGN KEY (SUBJ_ID) REFERENCES dbo.SUBJECT(SUBJ_ID) ); CREATE TABLE dbo.ORG_UNIT ( UNIT_ID INT CONSTRAINT PK_ORG PRIMARY KEY, PARENT_ID INT NULL, UNIT_NAME NVARCHAR(80) NOT NULL, UNIVERSITY_ID INT NOT NULL, CONSTRAINT FK_ORG_PARENT FOREIGN KEY (PARENT_ID) REFERENCES dbo.ORG_UNIT(UNIT_ID), CONSTRAINT FK_ORG_UNIVERSITY FOREIGN KEY (UNIVERSITY_ID) REFERENCES dbo.UNIVERSITY(UNIVERSITY_ID) ); GO

Блок 6. Эталонные данные (INSERT)

Строки вставляются в порядке зависимостей: сначала родители (UNIVERSITY, SUBJECT), потом дети. Иначе внешний ключ не найдёт ссылку и INSERT завершится ошибкой.

6.1. Вузы:

INSERT INTO dbo.UNIVERSITY VALUES (10,N'ВГУ',450,N'Воронеж'),(11,N'НГУ',580,N'Новосибирск'), (12,N'СПбГУ',650,N'Санкт-Петербург'),(14,N'БГУ',320,N'Белгород'), (15,N'ТГУ',390,N'Томск'),(18,N'ВГМУ',410,N'Воронеж'), (22,N'МГУ',700,N'Москва'),(32,N'ЮФУ',470,N'Ростов-на-Дону');

6.2. Предметы:

INSERT INTO dbo.SUBJECT VALUES (10,N'Информатика',56,1),(18,N'Химия',40,2),(22,N'Физика',34,1),(31,N'Базы данных',72,5), (43,N'Математика',56,2),(56,N'История',34,4),(73,N'Физкультура',34,5),(94,N'Английский',56,3);

6.3. Студенты (19 строк; у id=19 город NULL — для заданий с IS NULL):

INSERT INTO dbo.STUDENT VALUES (1,N'Иванов',N'Иван',150,1,N'Воронеж','2007-03-12',10), (2,N'Сидорова',N'Анна',200,1,N'Москва','2007-07-01',22), (3,N'Петров',N'Пётр',0,3,N'Курск','2005-11-20',10), (4,N'Козлова',N'Мария',180,2,N'Санкт-Петербург','2006-04-15',12), (5,N'Новиков',N'Дмитрий',120,2,N'Новосибирск','2006-09-03',11), (6,N'Сидоров',N'Вадим',0,4,N'Москва','2004-01-28',22), (7,N'Морозова',N'Елена',250,1,N'Белгород','2007-12-05',14), (8,N'Волков',N'Алексей',140,3,N'Томск','2005-06-17',15), (9,N'Соколова',N'Ирина',160,2,N'Воронеж','2006-02-22',18), (10,N'Кузнецов',N'Борис',0,5,N'Москва','2003-08-09',22), (11,N'Орлов',N'Никита',130,1,N'Ростов-на-Дону','2007-05-14',32), (12,N'Зайцева',N'Ольга',170,4,N'Воронеж','2004-10-30',10), (13,N'Павлов',N'Андрей',90,3,N'Новосибирск','2005-03-08',11), (14,N'Лебедева',N'Татьяна',210,2,N'Москва','2006-12-19',22), (15,N'Котов',N'Павел',0,1,N'Курск','2008-01-11',10), (16,N'Лукин',N'Артём',110,5,N'Белгород','2003-04-25',14), (17,N'Белкин',N'Вадим',155,3,N'Воронеж','2005-09-16',10), (18,N'Крылова',N'Светлана',190,4,N'Санкт-Петербург','2004-07-07',12), (19,N'Медведев',N'Олег',80,1,NULL,'2007-08-21',32);

6.4. Преподаватели:

INSERT INTO dbo.LECTURER VALUES (24,N'Колесников',N'Борис',N'Воронеж',10),(46,N'Никонов',N'Иван',N'Воронеж',10), (74,N'Лагутин',N'Павел',N'Москва',22),(108,N'Струков',N'Николай',N'Москва',22), (276,N'Николаев',N'Виктор',N'Воронеж',10),(328,N'Сорокин',N'Андрей',N'Орёл',10), (401,N'Смирнова',N'Ольга',N'Санкт-Петербург',12),(512,N'Гусев',N'Игорь',N'Новосибирск',11), (620,N'Фролов',N'Сергей',N'Томск',15),(705,N'Макарова',N'Анна',N'Белгород',14);

6.5. Оценки (24 строки; у студента 19 оценок нет — для NOT EXISTS и LEFT JOIN):

INSERT INTO dbo.EXAM_MARKS VALUES (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');

6.6. Кто какой предмет ведёт:

INSERT INTO dbo.SUBJ_LECT VALUES (24,10),(24,31),(46,22),(46,18),(74,43),(108,56),(276,73),(328,10),(401,94),(512,10),(620,18),(705,56);

6.7. Подразделения вузов:

INSERT INTO dbo.ORG_UNIT VALUES (1,NULL,N'Ректорат',10),(2,1,N'Учебное управление',10),(3,1,N'Факультет КНиИТ',10), (4,3,N'Кафедра информационных технологий',10),(5,3,N'Кафедра математики',10), (6,1,N'Факультет ПММ',10),(7,6,N'Кафедра механики',10), (20,NULL,N'Ректорат',22),(21,20,N'Факультет ВМК',22),(22,21,N'Кафедра алгоритмических языков',22);

Проверка после блока 6: SELECT COUNT(*) FROM STUDENT; — должно быть 19. У студента с STUDENT_ID = 19 нет строк в EXAM_MARKS.

SQLite (если работаете не в SSMS)

PRAGMA foreign_keys = ON; CREATE TABLE UNIVERSITY ( UNIVERSITY_ID INTEGER PRIMARY KEY, UNIVERSITY_NAME TEXT NOT NULL, RATING INTEGER, CITY TEXT NOT NULL ); -- остальные таблицы аналогично; DATE храните как TEXT 'YYYY-MM-DD' -- DECIMAL заменить на REAL или INTEGER копеек -- NVARCHAR заменить на TEXT -- IDENTITY не нужен при явных id

Данные в таблицах (для просмотра)

Те же строки, что в блоке 6, в удобном виде — можно сверить результат после INSERT.

На телефоне широкие таблицы прокручиваются пальцем влево и вправо.

UNIVERSITY

UNIVERSITY_IDUNIVERSITY_NAMERATINGCITY
10ВГУ450Воронеж
11НГУ580Новосибирск
12СПбГУ650Санкт-Петербург
14БГУ320Белгород
15ТГУ390Томск
18ВГМУ410Воронеж
22МГУ700Москва
32ЮФУ470Ростов-на-Дону

STUDENT (19 строк)

IDФамилияИмяСтип.КурсГородРождениеВуз
1ИвановИван1501Воронеж2007-03-1210
2СидороваАнна2001Москва2007-07-0122
3ПетровПётр03Курск2005-11-2010
4КозловаМария1802Санкт-Петербург2006-04-1512
5НовиковДмитрий1202Новосибирск2006-09-0311
6СидоровВадим04Москва2004-01-2822
7МорозоваЕлена2501Белгород2007-12-0514
8ВолковАлексей1403Томск2005-06-1715
9СоколоваИрина1602Воронеж2006-02-2218
10КузнецовБорис05Москва2003-08-0922
11ОрловНикита1301Ростов-на-Дону2007-05-1432
12ЗайцеваОльга1704Воронеж2004-10-3010
13ПавловАндрей903Новосибирск2005-03-0811
14ЛебедеваТатьяна2102Москва2006-12-1922
15КотовПавел01Курск2008-01-1110
16ЛукинАртём1105Белгород2003-04-2514
17БелкинВадим1553Воронеж2005-09-1610
18КрыловаСветлана1904Санкт-Петербург2004-07-0712
19МедведевОлег801NULL2007-08-2132

LECTURER

IDФамилияИмяГородВуз
24КолесниковБорисВоронеж10
46НиконовИванВоронеж10
74ЛагутинПавелМосква22
108СтруковНиколайМосква22
276НиколаевВикторВоронеж10
328СорокинАндрейОрёл10
401СмирноваОльгаСанкт-Петербург12
512ГусевИгорьНовосибирск11
620ФроловСергейТомск15
705МакароваАннаБелгород14

SUBJECT

SUBJ_IDНазваниеЧасыСеместр
10Информатика561
18Химия402
22Физика341
31Базы данных725
43Математика562
56История344
73Физкультура345
94Английский563

EXAM_MARKS (24 строки)

EXAM_IDSTUDENT_IDSUBJ_IDMARKEXAM_DATE
111052026-01-15
212242026-01-18
331032026-01-15
432242026-01-18
521052026-01-16
644352026-06-10
751042026-01-15
865632026-06-12
989452026-01-20
1091842026-06-08
11103152026-01-22
12125642026-06-12
13131022026-01-15
14149452026-01-20
15172232026-01-18
1671052026-01-16
17111042026-01-16
18152232026-01-18
19185652026-06-12
20163142026-01-22
2114352026-06-10
22123132026-01-22
2363142026-01-22
2441042026-01-16

Студент 19 (Медведев) специально без строк в EXAM_MARKS и с CITY NULL: на нём проверяют IS NULL, NOT EXISTS и LEFT JOIN … IS NULL.

SUBJ_LECT

LECTURER_IDSUBJ_ID
2410
2431
4622
4618
7443
10856
27673
32810
40194
51210
62018
70556

ORG_UNIT (для ЛР №18)

UNIT_IDPARENT_IDUNIT_NAMEUNIVERSITY_ID
1NULLРекторат10
21Учебное управление10
31Факультет КНиИТ10
43Кафедра информационных технологий10
53Кафедра математики10
61Факультет ПММ10
76Кафедра механики10
20NULLРекторат22
2120Факультет ВМК22
2221Кафедра алгоритмических языков22

Шпаргалка диалектов

ЗадачаSQL ServerSQLite
Первые N строкTOP (N) … ORDER BYLIMIT N
ПагинацияOFFSET FETCHLIMIT … OFFSET
Строка сейчасGETDATE(), SYSDATETIME()datetime('now')
Конкатенация+ или CONCAT||
АвточислоINT IDENTITYINTEGER PRIMARY KEY
Юникод-литералN'текст''текст' UTF-8
Удаление дубликатов строк запросаDISTINCTDISTINCT
FULL JOINестьэмуляция UNION
ПроцедурыCREATE PROCнет
БэкапBACKUP DATABASEVACUUM INTO / копия файла

Экзамен

Контрольные вопросы

На экзамене из этого списка задают два вопроса (см. билеты ниже).

  1. Данные, БД, СУБД. Отличие. Примеры.
  2. Недостатки файлового подхода. Преимущества БД.
  3. Архитектура ANSI/SPARC. Независимость данных.
  4. Реляционная модель: отношение, домен, ключи.
  5. Функциональная зависимость. Тривиальные и полные ФЗ.
  6. Аксиомы Армстронга. Замыкание атрибутов. Поиск ключа.
  7. Аномалии обновления, вставки, удаления. Пример.
  8. 1НФ, 2НФ, 3НФ. Определения и пример декомпозиции.
  9. НФБК. Чем строже 3НФ. Пример с потерей ФЗ.
  10. Идея 4НФ и многозначной зависимости (кратко).
  11. Транзакция. Команды BEGIN, COMMIT, ROLLBACK, SAVEPOINT.
  12. Свойства ACID. Что СУБД не гарантирует.
  13. Грязное, неповторяемое чтение, фантом, потерянное обновление.
  14. Уровни изоляции SQL-92. Таблица аномалий. Умолчание SQL Server.
  15. Блокировки S/X. Двухфазный протокол.
  16. Тупик: граф ожидания, жертва, профилактика. Ошибка 1205.
  17. SQLite vs SQL Server (опционально, кратко).
  18. Задачи администратора БД. Login, user, роль, GRANT.
  19. План выполнения. Scan и Seek. Зачем индекс и когда вреден.
  20. RPO и RTO. Полная, разностная копия, журнал. Правило 3-2-1.
  21. RESTORE: порядок, NORECOVERY, STOPAT. Логическая ошибка vs потеря диска.
  22. Распределённая БД. Виды репликации. Идея 2PC.
  23. OLTP и OLAP. Хранилище, факт, измерение, операции куба.
  24. VIEW, CTE, хранимая процедура, триггер: назначение и отличия.

Экзаменационные билеты

Скачать билеты (.docx)

Билеты к экзамену

На экзамене выдаётся один билет из списка ниже: два теоретических вопроса + одна SQL-задача по UniversityDB. Нажмите на номер билета, чтобы открыть.

Билет №1
  1. Данные, БД, СУБД. Отличие. Примеры.
  2. НФБК. Чем строже 3НФ. Пример с потерей ФЗ.
  3. SQL: Студенты со стипендией выше средней по своему вузу.
Билет №2
  1. Недостатки файлового подхода. Преимущества БД.
  2. Идея 4НФ и многозначной зависимости (кратко).
  3. SQL: Вузы без студентов (NOT EXISTS или LEFT JOIN … IS NULL).
Билет №3
  1. Архитектура ANSI/SPARC. Независимость данных.
  2. Транзакция. Команды BEGIN, COMMIT, ROLLBACK, SAVEPOINT.
  3. SQL: Средний балл по предметам 1-го семестра (GROUP BY, HAVING).
Билет №4
  1. Реляционная модель: отношение, домен, ключи.
  2. Свойства ACID. Что СУБД не гарантирует.
  3. SQL: Иногородние студенты (город студента не совпадает с городом вуза).
Билет №5
  1. Функциональная зависимость. Тривиальные и полные ФЗ.
  2. Грязное, неповторяемое чтение, фантом, потерянное обновление.
  3. SQL: Преподаватели, ведущие предмет «Информатика» (через SUBJ_LECT).
Билет №6
  1. Аксиомы Армстронга. Замыкание атрибутов. Поиск ключа.
  2. Уровни изоляции SQL-92. Таблица аномалий. Умолчание SQL Server.
  3. SQL: Число оценок «5» по каждому вузу.
Билет №7
  1. Аномалии обновления, вставки, удаления. Пример.
  2. Блокировки S/X. Двухфазный протокол.
  3. SQL: Студенты с CITY IS NULL (ожидается Медведев, STUDENT_ID=19).
Билет №8
  1. 1НФ, 2НФ, 3НФ. Определения и пример декомпозиции.
  2. Тупик: граф ожидания, жертва, профилактика. Ошибка 1205.
  3. SQL: Рекурсивный CTE: подразделения вуза UNIVERSITY_ID=10 от UNIT_ID=1.
Билет №9
  1. НФБК. Чем строже 3НФ. Пример с потерей ФЗ.
  2. SQLite vs SQL Server (кратко).
  3. SQL: Студенты со стипендией выше средней по своему вузу.
Билет №10
  1. Идея 4НФ и многозначной зависимости (кратко).
  2. Задачи администратора БД. Login, user, роль, GRANT.
  3. SQL: Вузы без студентов (NOT EXISTS или LEFT JOIN … IS NULL).
Билет №11
  1. Транзакция. Команды BEGIN, COMMIT, ROLLBACK, SAVEPOINT.
  2. План выполнения. Scan и Seek. Зачем индекс и когда вреден.
  3. SQL: Средний балл по предметам 1-го семестра (GROUP BY, HAVING).
Билет №12
  1. Свойства ACID. Что СУБД не гарантирует.
  2. RPO и RTO. Полная, разностная копия, журнал. Правило 3-2-1.
  3. SQL: Иногородние студенты (город студента не совпадает с городом вуза).
Билет №13
  1. Грязное, неповторяемое чтение, фантом, потерянное обновление.
  2. RESTORE: порядок, NORECOVERY, STOPAT. Логическая ошибка vs потеря диска.
  3. SQL: Преподаватели, ведущие предмет «Информатика» (через SUBJ_LECT).
Билет №14
  1. Уровни изоляции SQL-92. Таблица аномалий. Умолчание SQL Server.
  2. Распределённая БД. Виды репликации. Идея 2PC.
  3. SQL: Число оценок «5» по каждому вузу.
Билет №15
  1. Блокировки S/X. Двухфазный протокол.
  2. OLTP и OLAP. Хранилище, факт, измерение, операции куба.
  3. SQL: Студенты с CITY IS NULL (ожидается Медведев, STUDENT_ID=19).
Билет №16
  1. Тупик: граф ожидания, жертва, профилактика. Ошибка 1205.
  2. VIEW, CTE, хранимая процедура, триггер: назначение и отличия.
  3. SQL: Рекурсивный CTE: подразделения вуза UNIVERSITY_ID=10 от UNIT_ID=1.
Билет №17
  1. SQLite vs SQL Server (кратко).
  2. Данные, БД, СУБД. Отличие. Примеры.
  3. SQL: Студенты со стипендией выше средней по своему вузу.
Билет №18
  1. Задачи администратора БД. Login, user, роль, GRANT.
  2. Недостатки файлового подхода. Преимущества БД.
  3. SQL: Вузы без студентов (NOT EXISTS или LEFT JOIN … IS NULL).
Билет №19
  1. План выполнения. Scan и Seek. Зачем индекс и когда вреден.
  2. Архитектура ANSI/SPARC. Независимость данных.
  3. SQL: Средний балл по предметам 1-го семестра (GROUP BY, HAVING).
Билет №20
  1. RPO и RTO. Полная, разностная копия, журнал. Правило 3-2-1.
  2. Реляционная модель: отношение, домен, ключи.
  3. SQL: Иногородние студенты (город студента не совпадает с городом вуза).
Билет №21
  1. RESTORE: порядок, NORECOVERY, STOPAT. Логическая ошибка vs потеря диска.
  2. Функциональная зависимость. Тривиальные и полные ФЗ.
  3. SQL: Преподаватели, ведущие предмет «Информатика» (через SUBJ_LECT).
Билет №22
  1. Распределённая БД. Виды репликации. Идея 2PC.
  2. Аксиомы Армстронга. Замыкание атрибутов. Поиск ключа.
  3. SQL: Число оценок «5» по каждому вузу.
Билет №23
  1. OLTP и OLAP. Хранилище, факт, измерение, операции куба.
  2. Аномалии обновления, вставки, удаления. Пример.
  3. SQL: Студенты с CITY IS NULL (ожидается Медведев, STUDENT_ID=19).
Билет №24
  1. VIEW, CTE, хранимая процедура, триггер: назначение и отличия.
  2. 1НФ, 2НФ, 3НФ. Определения и пример декомпозиции.
  3. SQL: Рекурсивный CTE: подразделения вуза UNIVERSITY_ID=10 от UNIT_ID=1.