Каскадное удаление и обновление: ON DELETE CASCADE / SET NULL
Как работают каскадные действия в SQL? 🔄
Представь ситуацию: у тебя есть таблица orders (заказы), которая ссылается на customers (клиентов) через customer_id. Что произойдёт, если удалить клиента? Сотрётся ли его заказ? Или останется висеть в базе без связи?
Вот тут и приходят на помощь ON DELETE CASCADE и ON DELETE SET NULL — мощные инструменты контроля связей между таблицами!
ON DELETE CASCADE: «Удали родителя — удалятся и дети» 🗑️
Этот параметр автоматически удаляет все зависимые записи при удалении родительской.
Пример:
CREATE TABLE customers (
customer_id INT PRIMARY KEY,
name VARCHAR(100)
);
CREATE TABLE orders (
order_id INT PRIMARY KEY,
customer_id INT,
amount DECIMAL(10, 2),
FOREIGN KEY (customer_id)
REFERENCES customers(customer_id)
ON DELETE CASCADE -- Если удалим клиента, его заказы исчезнут!
);
Что произойдёт?
DELETE FROM customers WHERE customer_id = 1; -- Все заказы customer_id=1 удалятся автоматически!
✔ Где использовать?
- Когда дочерние записи не имеют смысла без родителя (например, комментарии к посту).
- Если нужно полное синхронное удаление без «мусора» в базе.
❌ Осторожно!
Можно случайно удалить больше данных, чем планировалось!
ON DELETE SET NULL: «Родитель удалён, но дети остаются» 🏠➡️❓
В отличие от CASCADE, этот вариант не удаляет дочерние записи, а просто обнуляет ссылку на родителя.
Пример:
CREATE TABLE orders (
order_id INT PRIMARY KEY,
customer_id INT,
amount DECIMAL(10, 2),
FOREIGN KEY (customer_id)
REFERENCES customers(customer_id)
ON DELETE SET NULL -- При удалении клиента customer_id станет NULL
);
Что произойдёт?
DELETE FROM customers WHERE customer_id = 1; -- В orders.customer_id запишется NULL
✔ Где применять?
- Если нужно сохранить исторические данные, даже если сущность-родитель удалена.
- Когда дочерние записи могут существовать автономно (например, заказы в архиве).
⚠ Важно!
Поле customer_id должно поддерживать NULL, иначе будет ошибка!
Что насчёт ON UPDATE? 🔄
Аналогично DELETE, но срабатывает при изменении родительского ключа (например, customer_id).
Пример:
CREATE TABLE orders (
order_id INT PRIMARY KEY,
customer_id INT,
FOREIGN KEY (customer_id)
REFERENCES customers(customer_id)
ON UPDATE CASCADE -- Если customer_id изменится, orders.customer_id тоже обновится
);
Сценарий:
UPDATE customers SET customer_id = 100 WHERE customer_id = 1;
-- Все заказы с customer_id=1 теперь будут ссылаться на customer_id=100!
Практика: как выбрать нужный вариант? 🤔
| Действие | ON DELETE CASCADE | ON DELETE SET NULL |
|---|---|---|
| Что делает? | Удаляет дочерние записи | Обнуляет ссылку в них |
| Когда использовать? | Если связи жёсткие (например, почта → письма) | Если связи условные (например, клиент → заказы в архиве) |
| Риски | Потеря данных при случайном удалении | NULL может усложнить выборки |
Итог: мощь и ответственность 💪
Каскадные действия экономят время, но требуют внимания:
- CASCADE — радикально, но эффективно.
- SET NULL — мягче, но оставляет «висячие» записи.
Попробуй на практике — и ты увидишь, насколько это удобно!