Ограничения: NOT NULL, UNIQUE, DEFAULT, CHECK

Учим базу саму отбраковывать некорректные данные с помощью ограничений.

Ограничение (constraint) — правило на уровне таблицы, которое база проверяет при каждой вставке и обновлении; нарушающие данные не сохраняются.

Зачем ограничения

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

NOT NULL — значение обязательно

Запрещает пустое (NULL) значение. Ставьте на поля, без которых строка бессмысленна (email, имя).

DEFAULT — значение по умолчанию

Если при вставке столбец не указан, подставляется значение по умолчанию.

UNIQUE — без повторов

Гарантирует, что в столбце не будет двух одинаковых значений (например, email у пользователей). В отличие от первичного ключа, UNIQUE-столбцов в таблице может быть несколько, и они могут допускать NULL.

CHECK — произвольное условие

Проверяет логическое условие (поддерживается в MySQL 8.0+). Например, что цена не отрицательна.

Всё вместе — пример MySQL

CREATE TABLE products (
  id INT AUTO_INCREMENT PRIMARY KEY,
  sku VARCHAR(50) NOT NULL UNIQUE,
  name VARCHAR(200) NOT NULL,
  price DECIMAL(10,2) NOT NULL DEFAULT 0,
  in_stock TINYINT(1) NOT NULL DEFAULT 1,
  CHECK (price >= 0)
) ENGINE=InnoDB;

Проверяем на песочнице

Ограничения NOT NULL, UNIQUE, DEFAULT переносимы — работают и в SQLite. Создадим таблицу и убедимся, что DEFAULT подставляется:

CREATE TABLE products (
  id INTEGER PRIMARY KEY,
  sku TEXT NOT NULL UNIQUE,
  name TEXT NOT NULL,
  price INTEGER NOT NULL DEFAULT 0
);

INSERT INTO products (sku, name) VALUES ('A-1', 'Кружка');
INSERT INTO products (sku, name, price) VALUES ('A-2', 'Термос', 1500);

SELECT sku, name, price FROM products;

Вывод:

sku  name    price
A-1  Кружка  0
A-2  Термос  1500

У «Кружки» цену мы не указали — сработал DEFAULT 0. А попытка вставить второй товар с sku = 'A-1' упадёт из-за UNIQUE.

Памятка

ОграничениеЗащищает от
NOT NULLпустых обязательных полей
UNIQUEдубликатов значений
DEFAULTотсутствующих значений (подставит своё)
CHECKзначений, нарушающих условие

Итог

  • Ограничения проверяет сама база — это надёжнее проверок только в коде.
  • NOT NULL — поле обязательно; DEFAULT — подставит значение, если его нет.
  • UNIQUE — запрет дублей; таких столбцов может быть несколько.
  • CHECK (8.0+) — произвольное условие, например price >= 0.
Проверьте себя
1. Чем UNIQUE отличается от PRIMARY KEY?
AUNIQUE нельзя индексировать
BUNIQUE-столбцов в таблице может быть несколько и они могут допускать NULL
CUNIQUE запрещает NULL всегда
Dэто полные синонимы
2. Что произойдёт при вставке строки, если столбец с DEFAULT 0 не указан?
Aвставка завершится ошибкой
Bв столбец запишется 0
Cзапишется NULL
Dстрока не сохранится
3. Почему ограничения на уровне базы надёжнее проверок только в коде приложения?
Aкод работает медленнее
Bбаза проверяет данные при любом источнике запроса, минуя возможные баги приложения
Cограничения ускоряют SELECT
Dкод не умеет проверять данные
Поддержать проект