Что такое constraints и зачем они нужны в таблице?
Databases → SQL → Constraints
Основная идея
Constraints (ограничения) — это правила, которые применяются к данным в таблицах SQL для обеспечения целостности, точности и надёжности данных. Они автоматически контролируют, какие значения можно вставить в столбцы.
Ключевые аспекты
NOT NULL — запрещает пустые значения в столбце
UNIQUE — гарантирует уникальность всех значений в столбце
PRIMARY KEY — комбинация NOT NULL и UNIQUE, идентифицирует запись
FOREIGN KEY — связывает таблицы и обеспечивает ссылочную целостность
CHECK — проверяет значения по заданному условию
DEFAULT — устанавливает значение по умолчанию
Плюсы использования constraints
Автоматическая валидация данных на уровне БД
Защита от некорректных данных независимо от приложения
Поддержание целостности связей между таблицами
Уменьшение количества ошибок в данных
Минусы
Дополнительная нагрузка на БД при INSERT/UPDATE операциях
Необходимость продумывать constraints заранее
Сложность изменения constraints в production
Частые ошибки на собеседованиях
Путают PRIMARY KEY и UNIQUE (PRIMARY KEY = UNIQUE + NOT NULL)
Забывают, что FOREIGN KEY требует существования ссылаемого значения
Не знают разницу между CHECK и валидацией на уровне приложения
Введение и проблематика
При работе с базами данных критически важно обеспечить целостность данных — гарантию того, что данные корректны, согласованы и соответствуют бизнес-правилам. Без ограничений любое приложение могло бы записать в базу некорректные данные: пользователя без email, заказ с отрицательной ценой, или ссылку на несуществующую запись.
Constraints работают как «охранники» базы данных — они проверяют каждую операцию INSERT, UPDATE и DELETE, отклоняя те, что нарушают установленные правила.
Какую проблему решают constraints?
Защита от человеческих ошибок — даже если разработчик забудет проверку в коде
Единая точка валидации — правила хранятся в одном месте (БД), а не дублируются в каждом приложении
Ссылочная целостность — невозможно создать «висячие» ссылки на удалённые записи
Базовая теория
Что такое constraint?
Constraint (ограничение) — это декларативное правило, определённое на уровне столбца или таблицы, которое автоматически проверяется СУБД при каждой операции изменения данных.
Типы constraints в SQL
Constraint
Описание
Уровень
NOT NULL
Запрещает NULL значения
Столбец
UNIQUE
Все значения должны быть уникальны
Столбец/Таблица
PRIMARY KEY
Уникальный идентификатор записи (NOT NULL + UNIQUE)
Столбец/Таблица
FOREIGN KEY
Ссылка на PRIMARY KEY другой таблицы
Столбец/Таблица
CHECK
Произвольное условие проверки
Столбец/Таблица
DEFAULT
Значение по умолчанию
Столбец
Практические примеры
NOT NULL — обязательные поля
sql
CREATETABLEusers ( id SERIALPRIMARY KEY, email VARCHAR(255) NOT NULL, -- email обязателен nickname VARCHAR(50) -- nickname опционален);-- ✅ УспешноINSERT INTO users (email) VALUES ('user@example.com');-- ❌ Ошибка: Column 'email' cannot be nullINSERT INTO users (nickname) VALUES ('john');
UNIQUE — уникальные значения
sql
CREATETABLEusers ( id SERIALPRIMARY KEY, email VARCHAR(255) UNIQUENOT NULL, phone VARCHAR(20) UNIQUE);-- ✅ УспешноINSERT INTO users (email, phone) VALUES ('a@test.com', '+1234567890');-- ❌ Ошибка: Duplicate entry 'a@test.com' for key 'email'INSERT INTO users (email, phone) VALUES ('a@test.com', '+0987654321');
⚠️
UNIQUE допускает несколько NULL значений в большинстве СУБД (PostgreSQL, MySQL). Это логично: NULL означает «неизвестно», а два «неизвестных» значения не считаются равными.
PRIMARY KEY — идентификатор записи
sql
CREATETABLEproducts ( id SERIALPRIMARY KEY, -- автоинкремент + NOT NULL + UNIQUE sku VARCHAR(50) NOT NULL,nameVARCHAR(255) NOT NULL);-- Составной PRIMARY KEYCREATETABLEorder_items ( order_id INT, product_id INT, quantity INTNOT NULL,PRIMARY KEY (order_id, product_id) -- уникальная комбинация);
FOREIGN KEY — связь между таблицами
sql
CREATETABLEorders ( id SERIALPRIMARY KEY, user_id INTNOT NULL, total DECIMAL(10, 2),FOREIGN KEY (user_id) REFERENCES users(id));-- ✅ Успешно (если пользователь с id=1 существует)INSERT INTO orders (user_id, total) VALUES (1, 99.99);-- ❌ Ошибка: Cannot add or update a child row:-- a foreign key constraint failsINSERT INTO orders (user_id, total) VALUES (9999, 50.00);
CREATETABLEarticles ( id SERIALPRIMARY KEY, title VARCHAR(255) NOT NULL,statusVARCHAR(20) DEFAULT'draft', created_at TIMESTAMPDEFAULT CURRENT_TIMESTAMP, views INTDEFAULT0);-- created_at, status и views заполнятся автоматическиINSERT INTO articles (title) VALUES ('My First Article');
Порядок создания таблиц: При использовании FOREIGN KEY сначала создаётся родительская таблица (на которую ссылаются), затем дочерняя (которая ссылается).
Каскадные операции
sql
CREATETABLEorders ( id SERIALPRIMARY KEY, user_id INTNOT NULL,FOREIGN KEY (user_id) REFERENCES users(id)ON DELETE CASCADE-- удаление пользователя удалит все его заказыONUPDATE CASCADE -- изменение id пользователя обновит ссылки);
Варианты действий при удалении/обновлении:
CASCADE — автоматически удалить/обновить связанные записи
SET NULL — установить NULL в связанных записях
SET DEFAULT — установить значение по умолчанию
RESTRICT / NO ACTION — запретить операцию (по умолчанию)
Сравнение: валидация в БД vs в приложении
Плюсы:
Гарантированная защита независимо от источника данных
Единая точка правды
Работает даже при прямом доступе к БД
Минусы:
Нагрузка на БД
Сообщения об ошибках менее user-friendly
Сложнее изменять в production
Best practice: Используйте оба подхода. Constraints в БД — как последний рубеж защиты, валидация в приложении — для UX и бизнес-логики.
Плюсы и минусы constraints
Аспект
Плюсы
Минусы
Целостность
✅ Гарантированная защита данных
Производительность
❌ Дополнительные проверки при записи
Разработка
✅ Меньше багов с данными
❌ Нужно продумывать заранее
Миграции
❌ Сложно изменять существующие constraints
Масштабирование
✅ Индексы на UNIQUE/PK ускоряют чтение
❌ FK могут замедлять запись
Вопросы интервьюера
Q: Чем PRIMARY KEY отличается от UNIQUE?
PRIMARY KEY = UNIQUE + NOT NULL. В таблице может быть только один PRIMARY KEY, но несколько UNIQUE constraints.
Q: Можно ли добавить FOREIGN KEY на столбец с существующими некорректными данными?
Нет, СУБД выдаст ошибку. Сначала нужно исправить данные или удалить «сиротские» записи.
Q: Какой constraint использовать для проверки email?
CHECK с регулярным выражением (если СУБД поддерживает) или валидация на уровне приложения. CHECK лучше для простых проверок.
Q: Влияют ли constraints на производительность?
Да. UNIQUE и FOREIGN KEY создают индексы, что ускоряет SELECT, но замедляет INSERT/UPDATE. CHECK выполняет дополнительные проверки.