Интерактивный отчёт · Настоящие данные с базы

База данных учебных курсов и заявок

В базе всё просто: есть курсы (в таблице Course) и заявки людей на эти курсы (в таблице Application). У каждой заявки указан ровно один курс, а значит, один курс может иметь много заявок — это связь 1 : N («один ко многим»). Все данные ниже настоящие — их получили из реально запущенной базы, ничего не выдумано.

Схема базы данных

Courseкаталог учебных курсов · сторона «1» 1
Applicationзаявки студентов на курсы · сторона «N» N
ЛКМ перетащить · колесо масштаб · клик по таблице — вкладки · по линии связи — объяснение
Линия между таблицами — это связь 1 : N: один курс, много заявок. Заявка «знает» свой курс по номеру в колонке CourseId. Удалишь курс — его заявки удалятся сами. Нажми на линию — откроется простое объяснение.

Заявки по статусам

Заявки по курсам

С чего начать

4 шага по одному клику — от «что это за база» до «как выглядит код».

1Что хранится

Две таблицы и все их колонки — с простыми объяснениями.

2Связь 1 : N

Почему заявка всегда относится к курсу и что значит каскад.

3Реальные данные

Настоящие записи курсов и заявок — можно искать и сортировать.

4SQL-код

Весь код проекта — нажми на слово, узнаешь, что оно значит.

Словарик новичка

Слова из отчёта — простыми словами и с примером из жизни. Нажми на слово со значком — появится подсказка.

Раздел 02 · Структура

Таблицы и колонки

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

Раздел 03 · Отношения

Связи: как таблицы связаны

Связь одна: Course (1) —< Application (N). Это значит: один курс — много заявок. Заявка всегда «ссылается» на конкретный курс. Ниже — объяснение по шагам и живой пример.

Связь · FK_Application_Course

Что связываетCourse.CourseId (PK, родитель) ↔ Application.CourseId (FK, потомок) Тип1 : N — один курс, много заявок ПоведениеON DELETE CASCADE · ON UPDATE CASCADE

Нажми, чтобы открыть подробное объяснение →

Как работает связь — по шагам

1
Первичный ключ (PK)

Course.CourseId — «паспорт» курса: у каждого курса свой номер, двух одинаковых не бывает.

2
Внешний ключ (FK)

Application.CourseId — номер курса, на который подана заявка. Такого номера нет в Course — заявка «повиснет в воздухе».

3
Проверка при добавлении

База сама проверяет каждую новую заявку: если такого курса не существует — заявку добавить не даст.

4
1 : N

Один и тот же номер курса может стоять у многих заявок — отсюда и название «один ко многим».

5
Удаление курса

Удалили курс — его заявки удалятся сами, никто не останется без курса. Поменялся номер курса — он сам поменяется у всех заявок.

Один курс → несколько заявок

Выбери курс ниже — заявки, связанные с ним, подсветятся.

Очистка: клик по выбранному курсу снимает выделение.
Раздел 04 · Реальные данные

Данные из отчёта

Здесь — настоящие данные: 4 курса и 11 заявок. Нажми на курс — увидишь его заявки. Нажми на заявку — увидишь её курс. Можно искать, сортировать и фильтровать.

Информация о записи

Выбери строку в таблице выше — здесь появятся подробности и связанные записи.

Связанные записи

Выбери курс, чтобы увидеть его заявки, или заявку, чтобы увидеть её курс.

Данные настоящие, как в отчёте. Заявка №1 уже в работе (её статус изменило демо). Курс «Архив: COBOL» удалили — чтобы показать, как каскад убирает его заявки.
Раздел 05 · Исходный код

SQL-запросы и код проекта

Код всех 8 файлов проекта — такой же, как в базе. Нажми на подсвеченное слово (например PRIMARY KEY или CHECK) — появится простое объяснение, что оно значит.

ключевые слова — кликабельны строки и литералы комментарии числа
Откуда код: из файлов проекта sql/01_schema.sql … deploy_all.sql. Это настоящий код — ничего не сокращали и не придумывали. Листай вниз, чтобы увидеть файл целиком.
Раздел 06 · Целостность

Ограничения

Это правила для данных. Например: «цена не бывает отрицательной». Нажми на правило — увидишь пример хорошего и плохого значения и что случится, если его нарушить.

Раздел 07 · Производительность

Индексы

Индексы — это «ускорители» базы: по ним компьютер быстрее находит нужные записи. Всего их 7. Нажми на карточку — узнаешь, что ускоряет каждый.

Раздел 08 · Проверка на живом сервере

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

Базу создавали с нуля три раза подряд — и каждый раз без ни одной ошибки. Все 13 правил базы проверили «на плохих данных» — все сработали как надо. Ниже — живое доказательство: настоящий вывод из терминала.

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

Базу создавали с нуля 3 раза подряд — все 3 раза без ни одной ошибки.

Где запускали

База жила в «коробке» Docker — как маленький компьютер внутри большого.

Повтори хоть сто раз

Одни и те же команды можно запускать снова — копии и дубли не появляются.

Отклонённое — не вернёшь

Заявку со статусом «отклонена» или «отменена» нельзя вернуть в работу — это защита от ошибок.

Как это выглядело в терминале (настоящий вывод)

sqlcmd -S localhost -U sa -C -d CourseManagement
================================================================
 1. СТРУКТУРА ТАБЛИЦ
================================================================
TableName Pos ColumnName DataType MaxBytes Nullable DefaultValue
--------- --- ---------- -------- -------- -------- ------------
Application 1 ApplicationId int 4 0 NULL
Application 2 CourseId int 4 0 NULL
Application 3 ApplicantName nvarchar 300 0 NULL
Application 4 Phone nvarchar 64 0 NULL
Application 5 Email nvarchar 508 0 NULL
Application 6 PreferredStartDate date 3 0 NULL
Application 7 Status ApplicationStatus (alias-тип) 0 ('new')
Application 8 CreatedAt datetime2 7 0 (sysutcdatetime())
Application 9 Comment nvarchar 2000 1 NULL
Course 1 CourseId int 4 0 NULL
Course 2 Title nvarchar 400 0 NULL
Course 3 DurationHours int 4 0 NULL
Course 4 Price decimal 9 0 NULL
Course 5 IsActive bit 1 0 ((1))
Course 6 CreatedAt datetime2 7 0 (sysutcdatetime())
 
================================================================
 2. СВЯЗЬ 1:N  (Course -> Application)
================================================================
ForeignKey ChildTable ChildColumn ParentTable ParentColumn OnDelete
---------- ---------- ----------- ----------- ------------ --------
FK_Application_Course Application CourseId Course CourseId CASCADE
 
================================================================
 3. ОГРАНИЧЕНИЯ (CHECK / PK / UNIQUE)
================================================================
ConstraintName Type TableName
-------------- ---- ---------
CK_Application_ApplicantName_NotBlank CHECK_CONSTRAINT Application
CK_Application_Email_Format CHECK_CONSTRAINT Application
CK_Application_Email_NotBlank CHECK_CONSTRAINT Application
CK_Application_Phone_Format CHECK_CONSTRAINT Application
CK_Application_Phone_NotBlank CHECK_CONSTRAINT Application
CK_Application_StartDate_NotPast CHECK_CONSTRAINT Application
CK_Application_Status_Valid CHECK_CONSTRAINT Application
CK_Course_DurationHours_Positive CHECK_CONSTRAINT Course
CK_Course_Price_NonNegative CHECK_CONSTRAINT Course
CK_Course_Title_NotBlank CHECK_CONSTRAINT Course
FK_Application_Course FOREIGN_KEY_CONSTRAINT Application
PK_Application PRIMARY_KEY_CONSTRAINT Application
PK_Course PRIMARY_KEY_CONSTRAINT Course
 
================================================================
 4. ИНДЕКСЫ
================================================================
TableName IndexName Type IsUnique Filtered KeyColumns
--------- --------- ---- -------- -------- ----------
Application IX_Application_CourseId NONCLUSTERED 0 0 CourseId
Application IX_Application_CreatedAt NONCLUSTERED 0 0 CreatedAt
Application IX_Application_Status_CourseId NONCLUSTERED 0 0 Status, CourseId
Application PK_Application CLUSTERED 1 0 ApplicationId
Course IX_Course_IsActive NONCLUSTERED 0 0 IsActive
Course PK_Course CLUSTERED 1 0 CourseId
Course UX_Course_Active_Title NONCLUSTERED 1 1 Title
-- Объём данных:
Courses Applications
------- ------------
4 11
 
================================================================
 ЗАДАНИЕ 4.1  Активные курсы с количеством заявок
================================================================
CourseId Title DurationHours Price ApplicationCount NewCount InProgressCount ApprovedCount RejectedCount
-------- ----- ------------- ----- ---------------- -------- --------------- ------------- -------------
1 Python для начинающих 40 25000.00 5 1 2 1 1
4 Английский язык (B2) 96 18000.00 2 1 0 0 0
3 Веб-разработка на C# 72 55000.00 2 0 1 1 0
2 Основы SQL и проектирование БД 32 30000.00 2 2 0 0 0
================================================================
 ЗАДАНИЕ 4.2  Заявки со статусом "новая" для конкретного курса
================================================================
ApplicationId CourseId CourseTitle ApplicantName Phone Email PreferredStartDate Comment CreatedAt
------------- -------- ----------- ------------- ----- ----- ------------------ ------- ---------
6 2 Основы SQL и проектирование БД Волков Игорь +7 911 222-33-44 i.volkov@example.com 2026-10-12 NULL 2026-09-28 12:40:02.332
5 2 Основы SQL и проектирование БД Смирнова Екатерина +7 925 444-55-66 e.smirnova@example.com 2026-10-12 NULL 2026-09-28 12:40:02.332
================================================================
 ЗАДАНИЕ 4.3  Полная информация о заявке + данные курса (JOIN)
================================================================
ApplicationId ApplicantName Phone Email PreferredStartDate Status Comment ApplicationCreatedAt CourseId CourseTitle CourseDurationHours CoursePrice CourseIsActive CourseCreatedAt
------------- ------------- ----- ----- ------------------ ------ ------- -------------------- -------- ----------- ------------------- ----------- -------------- ---------------
1 Иванова Мария Петровна +7 999 123-45-67 maria.ivanova@example.com 2026-10-19 in_progress NULL 2026-09-28 12:40:02.332 1 Python для начинающих 40 25000.00 1 2026-09-28 12:40:02.300
================================================================
 ДОПОЛНИТЕЛЬНО: сводка по статусам + выручка
================================================================
Title Total NewCnt InProgressCnt ApprovedCnt RejectedCnt CancelledCnt
----- ----- ------ ------------- ----------- ----------- ------------
Python для начинающих 5 1 2 1 1 0
Английский язык (B2) 2 1 0 0 0 1
Веб-разработка на C# 2 0 1 1 0 0
Основы SQL и проектирование БД 2 2 0 0 0 0
Title ApprovedCnt Price Revenue
----- ----------- ----- -------
Веб-разработка на C# 1 55000.00 55000.00
Python для начинающих 1 25000.00 25000.00
================================================================
 CRUD: создание заявки -> смена статуса -> удаление
================================================================
ApplicationId CourseId ApplicantName Phone Email PreferredStartDate Status CreatedAt Comment
------------- -------- ------------- ----- ----- ------------------ ------ --------- -------
21 1 Демонстрация Иванова +7 999 555-33-22 demo.showcase@example.com 2026-10-28 new 2026-09-28 12:40:02.723 заявка из демонстрации
-- создана заявка, Status по умолчанию = new
ApplicationId Status CreatedAt
------------- ------ ---------
21 in_progress 2026-09-28 12:40:02.723
-- статус изменён на in_progress
ApplicationId Status CreatedAt
------------- ------ ---------
21 rejected 2026-09-28 12:40:02.723
-- заявка отклонена
-- защита сработала: Нельзя изменить статус закрытой заявки.
-- заявка удалена
 
================================================================
 ПРОВЕРКА ОГРАНИЧЕНИЙ (ожидаются срабатывания на мусоре)
================================================================
  OK  | Price >= 0        -> The INSERT statement conflicted with the CHECK constraint "CK_Course_Price_NonNegative". The conflict occurred in database "CourseManagement", table "dbo.Course", column 'Price'.
  OK  | FK защищает       -> The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Application_Course". The conflict occurred in database "CourseManagement", table "dbo.Course", column 'CourseId'.
  OK  | Формат e-mail     -> The INSERT statement conflicted with the CHECK constraint "CK_Application_Email_Format". The conflict occurred in database "CourseManagement", table "dbo.Application", column 'Email'.
  OK  | Список статусов   -> The INSERT statement conflicted with the CHECK constraint "CK_Application_Status_Valid". The conflict occurred in database "CourseManagement", table "dbo.Application", column 'Status'.
  OK  | Дата не в прошлом -> The INSERT statement conflicted with the CHECK constraint "CK_Application_StartDate_NotPast". The conflict occurred in database "CourseManagement", table "dbo.Application", column 'PreferredStartDate'.

Связанные материалы