Ответ
Внешние ключи (FK) сами по себе не удаляют данные. Их основная задача — обеспечить целостность ссылочных данных (referential integrity). Они гарантируют, что в дочерней таблице (order_items) не может существовать запись, ссылающаяся на несуществующую запись в родительской таблице (orders).
Однако, при определении внешнего ключа можно задать правило каскадного действия (ON DELETE). Вот как это работает:
-- Родительская таблица
CREATE TABLE orders (
id INT PRIMARY KEY AUTO_INCREMENT,
customer_id INT NOT NULL,
total DECIMAL(10,2)
);
-- Дочерняя таблица с внешним ключом и разными правилами ON DELETE
CREATE TABLE order_items (
id INT PRIMARY KEY AUTO_INCREMENT,
order_id INT NOT NULL,
product_id INT NOT NULL,
quantity INT,
-- 1. CASCADE: автоматическое удаление дочерних записей
CONSTRAINT fk_items_order_cascade
FOREIGN KEY (order_id) REFERENCES orders(id)
ON DELETE CASCADE,
-- 2. SET NULL: установка NULL в поле внешнего ключа (поле должно быть NULLABLE)
-- CONSTRAINT fk_items_order_setnull
-- FOREIGN KEY (order_id) REFERENCES orders(id)
-- ON DELETE SET NULL,
-- 3. RESTRICT (или NO ACTION): запрет удаления родительской записи, если есть дочерние
-- CONSTRAINT fk_items_order_restrict
-- FOREIGN KEY (order_id) REFERENCES orders(id)
-- ON DELETE RESTRICT
);
Практический пример с CASCADE:
-- Вставка данных
INSERT INTO orders (id, customer_id, total) VALUES (101, 1, 150.00);
INSERT INTO order_items (order_id, product_id, quantity) VALUES (101, 500, 2);
INSERT INTO order_items (order_id, product_id, quantity) VALUES (101, 501, 1);
-- Удаление заказа. Благодаря ON DELETE CASCADE, две связанные строки в order_items будут удалены автоматически.
DELETE FROM orders WHERE id = 101;
-- После этого запрос SELECT * FROM order_items WHERE order_id = 101 вернет пустой результат.
Ключевые моменты:
ON DELETE CASCADE— это именно то правило, которое «помогает удалять» связанные данные автоматически. Используйте его с осторожностью, так как это может привести к неожиданной потере данных.ON DELETE RESTRICT(илиNO ACTION) — это поведение по умолчанию во многих СУБД. Оно не помогает удалить, а наоборот, предотвращает удаление, если существуют зависимые записи, защищая от «висячих» ссылок.ON DELETE SET NULL— не удаляет дочернюю запись, а обнуляет ссылку. Для этого столбецorder_idдолжен быть объявлен какINT NULL.
Вывод: Внешние ключи — это механизм поддержания целостности. Правило ON DELETE CASCADE — это опция, которая автоматизирует удаление зависимых записей, но ее применение должно быть осознанным и соответствовать бизнес-логике (например, удаление заказа должно удалять его позиции, но удаление клиента, вероятно, не должно удалять все его исторические заказы).
Ответ 18+ 🔞
А, ну это же классика, ёпта! Смотри, с внешними ключами постоянно путаница возникает, будто они сами по себе что-то удаляют. Хуй с горы! Их главная работа — следить, чтобы в твоей базе не появилось сирот-записей, которые тыкаются пальцем в пустоту.
Представь таблицу заказов (orders) — это как папа. А таблица позиций в заказе (order_items) — это его дети. Внешний ключ в order_items на orders.id — это просто верёвка, которая не даёт ребёнку убежать и назваться сиротой. Сам по себе он ничего не удаляет, он просто стоит и смотрит, чтобы хуйни не было.
Но! Если ты очень хочешь, чтобы при исчезновении папы дети тоже шли лесом, то это нужно явно прописать — правило ON DELETE CASCADE. Вот тогда да, удалил заказ — и все его позиции накрылись медным тазом автоматически. Но это твой сознательный выбор, а не магия.
CREATE TABLE orders (
id INT PRIMARY KEY AUTO_INCREMENT,
customer_id INT NOT NULL,
total DECIMAL(10,2)
);
CREATE TABLE order_items (
id INT PRIMARY KEY AUTO_INCREMENT,
order_id INT NOT NULL,
product_id INT NOT NULL,
quantity INT,
-- Вот этот самый CASCADE и есть наш "помощник" в удалении
CONSTRAINT fk_items_order_cascade
FOREIGN KEY (order_id) REFERENCES orders(id)
ON DELETE CASCADE -- Смотри-ка, мама, что я могу!
);
На практике это выглядит так:
-- Был заказ 101 с двумя позициями
INSERT INTO orders (id, customer_id, total) VALUES (101, 1, 150.00);
INSERT INTO order_items (order_id, product_id, quantity) VALUES (101, 500, 2);
INSERT INTO order_items (order_id, product_id, quantity) VALUES (101, 501, 1);
-- Бац! И заказ 101 удаляем.
DELETE FROM orders WHERE id = 101;
-- И теперь волнение ебать: если полезешь в order_items искать позиции по order_id = 101, нихуя не найдёшь. CASCADE их прибрал.
А есть и другие правила, ядрёна вошь:
ON DELETE RESTRICT(илиNO ACTION) — это как раз поведение по умолчанию у многих. Это не помощник, а охранник. Он тебе скажет: «Чувак, какого хуя? У тебя же дети (позиции) есть! Сначала разберись с ними, а потом уже папу удаляй». Удаление родителя просто не пройдёт.ON DELETE SET NULL— это типа мягкий вариант. Папу удалили, а дети остались, но теперь у них в графе «папа» стоитNULL. Сиротами при живых родителях, грустная история. Для этого само полеorder_idдолжно позволять быть пустым (NULL).
Так что вывод, бля, простой: сам внешний ключ — это просто верёвка для целостности. А вот ON DELETE CASCADE — это уже топор, который ты можешь вручить системе со словами «на, помоги». Пользуйся им с головой, а то так и до хиросимы в базе недалеко. Удалишь клиента по ошибке, а CASCADE тебе за ним все его заказы похерит — и пиши пропало.