Часть 2 из 16
В прошлой части мы проверили подключение к MySQL и договорились, что строим базу фестиваля, а не набор разрозненных таблиц. Теперь заложим фундамент: опишем площадки и события, выберем типы полей и зададим связи.
Это нужно сделать до загрузки данных: иначе можно случайно сохранить событие без площадки или дату в виде произвольного текста. В конце проверим структуру в phpMyAdmin и увидим, как сервер сам отвергает невозможные значения.
Создаём учебную базу
CREATE DATABASE city_festival CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
USE city_festival;
utf8mb4 поддерживает Unicode целиком. Если конкретная колляция недоступна на вашей версии, найдите подходящую через SHOW COLLATION.
Таблица площадок
CREATE TABLE venues (
venue_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(120) NOT NULL,
district VARCHAR(80) NOT NULL,
capacity INT UNSIGNED NOT NULL,
PRIMARY KEY (venue_id),
CHECK (capacity > 0)
) ENGINE=InnoDB;
Первичный ключ не зависит от названия. NOT NULL требует значение, а CHECK запрещает вместимость ноль или меньше.
События ссылаются на площадку
CREATE TABLE events (
event_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
venue_id BIGINT UNSIGNED NOT NULL,
name VARCHAR(160) NOT NULL,
starts_at DATETIME NOT NULL,
ends_at DATETIME NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT 'planned',
PRIMARY KEY (event_id),
CHECK (ends_at > starts_at),
FOREIGN KEY (venue_id) REFERENCES venues(venue_id) ON DELETE RESTRICT
) ENGINE=InnoDB;
Внешний ключ запрещает ссылку на отсутствующую площадку. RESTRICT не даст удалить площадку, пока к ней привязано событие. InnoDB понадобится для транзакций позднее.
Осматриваем структуру
Выполните SHOW TABLES и SHOW CREATE TABLE events, затем сравните результат с вкладкой «Структура» phpMyAdmin. В следующей части добавим строки и научимся читать их запросом.
Как читать объявление таблицы
Команда CREATE TABLE — это договор с базой о форме каждой будущей строки. Названия и типы полей определяют, что можно сохранить; ключи определяют идентичность и связи; ограничения отклоняют недопустимые состояния. Например, если событие заканчивается раньше начала, ограничение времени вернёт ошибку прямо во время INSERT.
Важно: ограничение помогает лишь тогда, когда это правило действительно универсально для всех строк.
Тип выбирайте по смыслу. VARCHAR подходит для названий переменной длины; целое число — для вместимости; DATETIME — для даты и времени; для цены позднее возьмём точный DECIMAL.
Не храните дату как текст: сортировка строк может дать не хронологический порядок, а сервер не сможет проверять дату как дату.
Если MySQL выдаёт ошибку при создании внешнего ключа, сначала сверьте типы обоих venue_id: они должны совпадать, включая UNSIGNED. Затем проверьте, что обе таблицы используют InnoDB. В phpMyAdmin загляните в «Структуру» и найдите блоки «Индексы» и «Связи».
В следующем уроке мы наполним схему и проверим эти правила практикой.
Первичный ключ и внешний ключ — разные задачи
Первичный ключ отвечает на вопрос «какая это строка?». Значение venue_id уникально для каждой площадки и не должно быть пустым. Внешний ключ отвечает на вопрос «с какой строкой она связана?»: поле events.venue_id указывает на ключ площадки.
Название площадки для связи не подходит: оно может измениться или случайно повториться.
Проверка схемы на практике: после создания таблиц попробуйте добавить событие с venue_id, которого нет в venues. MySQL откажет из-за внешнего ключа. Затем добавьте площадку и повторите INSERT с её настоящим ID.
Так становится понятно, почему структура — не просто набор колонок, а набор правил допустимых данных.
Если это была не отдельная пустая база, не создавайте таблицу поверх существующей. Команда CREATE TABLE должна выполниться один раз; перед экспериментом используйте отдельную схему или удаляйте только учебную таблицу, чьи данные точно не нужны.
Шпаргалка по типам в нашей схеме
| Тип | Для чего | Пример |
|---|---|---|
| BIGINT UNSIGNED | Идентификатор без отрицательных значений | venue_id |
| VARCHAR(n) | Текст ограниченной длины | name |
| INT UNSIGNED | Целое неотрицательное число | capacity |
| DATETIME | Дата и время без зоны | starts_at |
Выбирайте тип по смыслу поля. Тогда MySQL сможет проверять значения и выполнять подходящие операции.
← Предыдущая статья: SQL на практике: создаём базу MySQL в phpMyAdmin
Следующая статья: INSERT и SELECT в MySQL: добавляем первые данные →
0
25