Часть 9 из 16

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

В этой части вернёмся от запросов к устройству самой базы и разберём нормализацию на фестивальной модели. Мы не будем делить данные ради теории: посмотрим, какие ошибки предотвращает отдельная таблица, как связаны записи и когда ограничение внешнего ключа должно остановить удаление.

Одна строка — одно событие модели

venues описывает площадки, events — концерты, artists — исполнителей, performances — отдельные слоты. Переименование площадки делается в одной строке, а не во всех событиях.

Связи закрепляет сервер

Внешние ключи требуют, чтобы event_id и artist_id выступления существовали в родительских таблицах. Проверьте реальные правила так:

SHOW CREATE TABLE performances;

Диаграмма phpMyAdmin удобна для обзора, но ограничение хранит MySQL, а не рисунок.

Продумываем удаление

RESTRICT блокирует удаление площадки, пока есть связанные события. CASCADE удалил бы дочерние строки автоматически. Для истории расписания и продаж часто лучше запретить удаление, а запись пометить отменённой или архивной.

Что вынести из таблицы?

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

Три ошибки таблицы с повторами

Представьте один широкий лист со столбцами venue_name, event_name, artist_names, ticket_codes. Если у события три артиста, появляются неудобные варианты: перечислить их в одной ячейке, завести три столбца artist_1/artist_2/artist_3 или скопировать площадку в несколько строк.

Первый вариант мешает искать отдельного артиста, второй ограничивает число исполнителей, третий создаёт повторы.

Разделение на venues, events, artists, performances и ticket_sales устраняет эти аномалии. Название площадки редактируется один раз; новый артист добавляется без изменения таблицы; каждая продажа получает отдельную строку. Ключи не позволяют связи зависеть от текста имени.

Нормализация — средство, а не ритуал

Нормализация не требует максимально возможного количества таблиц. Если два поля всегда описывают одну сущность и обновляются вместе, отдельная таблица может только усложнить проект. Разбивайте модель тогда, когда отдельные факты имеют собственную идентичность, жизненный цикл или повторяются во многих строках.

Посмотрите на схему в phpMyAdmin Designer и попробуйте объяснить каждую линию: какой ключ ссылается на какой, какое действие следует при удалении? Если связь трудно описать, уточните модель до импорта реальных данных. Следом рассмотрим безопасное изменение существующих строк.

Как увидеть проблему на примере

Представьте таблицу festival_report, где каждая строка — продажа, но одновременно повторяются название площадки, вместимость и имя события. Если у события 2000 продаж, одна и та же вместимость повторится 2000 раз. Исправляя название или вместимость, пришлось бы обновить все записи.

Если одна строка пропущена, отчёт станет противоречивым.

В нормализованной модели продажа ссылается на событие через event_id, событие — на площадку через venue_id, а подробность выступления хранится отдельно. Запрос JOIN собирает эту картину только тогда, когда она нужна. Это уменьшает повторение фактов и позволяет базе контролировать ссылки.

Связи имеют кратность

Одной площадке соответствует много событий, поэтому venue_id повторяется в events. Одному событию соответствует много слотов, поэтому event_id повторяется в performances. Один артист тоже может иметь много слотов.

Уникальность не надо накладывать на каждое внешнее поле: она должна отражать реальное правило, иначе база запретит допустимые данные.

Перед добавлением UNIQUE спросите, действительно ли два события не могут иметь одно название или два слота не могут стартовать одновременно. Если сомневаетесь, не вводите искусственное ограничение только ради «чистоты» таблицы.

Сущности и их роль

Таблица Что представляет одна строка Связь
venues Одну площадку У одной площадки может быть много событий
events Одно событие Ссылается на площадку
performances Один слот артиста Связывает событие и артиста
ticket_sales Один проданный билет Ссылается на событие

Таблица отвечает за один понятный вид факта. Если строку трудно описать одной фразой, проверьте, не смешались ли в ней несколько сущностей.

← Предыдущая статья: Подзапросы и CTE MySQL: строим отчёт по выручке

Следующая статья: UPDATE и DELETE в MySQL: безопасно меняем данные →