Ограничение CHECK — это в каком-то смысле охранник на входе вашей таблицы. Оно гарантирует, что данные, которые вы добавляете в таблицу, соответствуют определённым условиям. Если передать в таблицу данные, которые нарушают эти условия, база данных откажется принимать такие данные.
Представьте, что вы хотите открыть магазин в Германии. Но по закону воскресенье — выходной, и торговля в этот день запрещена. Это ограничение — аналог CHECK в базе данных. Вы пытаетесь указать расписание магазина: открыт 7 дней в неделю, но система тут же отвечает: "Nein, nein, воскресенье — это нарушение. Такой график не пройдёт проверку!"
Так и в базе данных: если вы задаёте значение, которое нарушает правило CHECK, система блокирует его, чтобы не допустить "логическую ошибку" в данных.
Зачем нужен CHECK?
- Поддержка качества данных:
CHECKпредотвращает попадание в таблицу некорректной или несоответствующей логике информации. - Снижение вероятности ошибок: вместо того чтобы вручную проверять данные перед вставкой, вы можете доверить эту задачу базе данных.
- Автономность логики: правила проверки можно встроить в структуру базы данных, а не возлагать эту задачу на уровень прикладного кода.
Как работает CHECK?
Ограничение CHECK задается в момент создания таблицы или может быть добавлено позднее с помощью команды ALTER TABLE. Вот базовый синтаксис:
CREATE TABLE таблица (
колонка тип_данных CHECK (условие)
);
условие — это логическое выражение, которое должно выполняться для каждого значения в указанном столбце. Если условие нарушается, база данных выдаёт ошибку.
Пример 1: Проверка диапазона значений
Давайте создадим таблицу students, где возраст студентов (age) должен быть в пределах от 16 до 100:
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
age INTEGER CHECK (age >= 16 AND age <= 100)
);
Теперь, если вы попробуете вставить студента с возрастом 12, база данных вас "поймает за руку":
INSERT INTO students (name, age)
VALUES ('Maria Chi', 12);
Ошибка:
ERROR: new row for relation "students" violates check constraint "students_age_check"
DETAIL: Failing row contains (1, Maria Chi, 12).
Да, база данных тут — суровый привратник. Нет 16 — не суйся.
Пример 2: Проверка формата данных
Допустим, у нас есть таблица emails, где хранится список адресов электронной почты. Мы хотим убедиться, что адреса содержат символ @ (это упрощённый способ проверки):
CREATE TABLE emails (
id SERIAL PRIMARY KEY,
email VARCHAR(255) CHECK (email LIKE '%@%')
);
Попробуем добавить некорректный адрес, который не соответствует условию:
INSERT INTO emails (email)
VALUES ('notanemail.com');
Ошибка:
ERROR: new row for relation "emails" violates check constraint "emails_email_check"
DETAIL: Failing row contains (1, notanemail.com).
Ошибки можно избежать, если все данные содержат символ @:
INSERT INTO emails (email)
VALUES ('example@student.com');
Запрос выполнится успешно.
Пример 3: Проверка условий для нескольких столбцов
Ограничения CHECK могут проверять не только один столбец, но и логическое выражение, завязанное на несколько столбцов. Давайте рассмотрим пример с таблицей employees, где зарплата (salary) должна быть больше, чем бонусы (bonus):
CREATE TABLE employees (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
salary NUMERIC CHECK (salary > 0),
bonus NUMERIC CHECK (bonus >= 0),
CHECK (salary > bonus)
);
Теперь, если кто-то попытается добавить сотрудника, у которого бонус больше зарплаты, база данных это не позволит:
INSERT INTO employees (name, salary, bonus)
VALUES ('Otto Lin', 3000, 4000);
Ошибка:
ERROR: new row for relation "employees" violates check constraint "employees_salary_bonus_check"
DETAIL: Failing row contains (1, Otto Lin, 3000, 4000).
Практическое применение
Ограничение CHECK помогает в тех случаях, когда ваш бизнес-логика тесно связана с ограничениями на данные. Например:
- Интернет-магазины: запрет на добавление товаров с отрицательной ценой.
- Образовательные платформы: проверка на возраст участников курсов.
- Медицинские системы: уверенность, что температура тела пациента лежит в допустимых пределах.
Эти проверки — не просто дополнительный слой безопасности, они экономят время и нервы разработчиков и пользователей.
Особенности и типичные ошибки
Когда работаете с CHECK, учтите следующие моменты:
Логические выражения в
CHECKдолжны быть истинными для всех строк таблицы. Если хотя бы одна строка нарушает правило, перед добавлением ограничения эту строку нужно скорректировать.Проверка не будет выполняться, если вставляемое значение равно
NULL. Иными словами,CHECK (age >= 18)не выдаст ошибку дляage = NULL. Это потому, что любое выражение, включающееNULL, автоматически становится неопределённым. Если вы хотите запретитьNULL, добавьтеNOT NULL.Сложные условия в
CHECKмогут ухудшить производительность при вставке и обновлении данных, особенно в больших таблицах.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ