Удаление из нескольких таблиц с внешними ограничениями - PullRequest
18 голосов
/ 30 июля 2011

Я пытаюсь удалить из нескольких таблиц.Вот как выглядят мои таблицы

    A_has_B ---- B ---- C_has_B
(many to many)        (many to many)

Я пытаюсь удалить все строки из A_has_B, B и C_has_B, используя идентификатор записи в B. Я использую MySQL с механизмом хранения innodb с определенными внешними ключамидля A_has_B и C_has_B ссылаясь на идентификаторы в B.

Я пытаюсь выполнить удаление следующим образом:

DELETE A_has_B.*, C_has_B.*, B.*

FROM
A

join
B
on (B.B_id = A.B_id)

join
C
on (C.B_id = B.B_id)

where B.B_id IN(1,2, 4);

Проблема в том, что когда я выполняю запрос, mysql жалуется:

Error Code: 1451. Cannot delete or update a parent row: a foreign key constraint fails (`db`.`C`, CONSTRAINT `fk_C` FOREIGN KEY (`B_id`) REFERENCES `B` (`B_id`) ON DELETE NO ACTION ON UPDATE NO)

Как мне исправить это?

Ответы [ 4 ]

30 голосов
/ 30 июля 2011

Самый простой способ - удалить из каждой таблицы по отдельности:

-- Remove all connections from A which reference
-- the B-rows you want to remove
DELETE FROM A_has_B
WHERE B_id IN (1,2,4);

-- Remove all connections from C which reference
-- the B-rows you want to remove
DELETE FROM C_has_B
WHERE B_id IN (1,2,4);

-- Finally remove the B-rows
DELETE FROM B
WHERE B_id IN (1,2,4);

MySQL также позволяет удалять из нескольких таблиц одним оператором. Но нет способа контролировать порядок удаления. Из руководства :

Если вы используете оператор DELETE для нескольких таблиц, включающий таблицы InnoDB, для которых существуют ограничения внешнего ключа, оптимизатор MySQL может обрабатывать таблицы в порядке, отличном от порядка их родительских / дочерних отношений. В этом случае утверждение не выполняется и выполняется откат. Вместо этого вы должны удалить из одной таблицы и полагаться на возможности ON DELETE, которые предоставляет InnoDB, для того, чтобы другие таблицы были изменены соответствующим образом.

9 голосов
/ 15 сентября 2011

На самом деле, в MySQL вы можете отключить проверки ограничений внешнего ключа

SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
--your SQL statements
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;

Оператор в первой строке вынуждает сервер MySQL отключать проверки внешнего ключа, а последняя строка отключает их обратно на (очень важно).Необходимо помнить две вещи:

  • Отключать проверки на наличие ограничений довольно опасно, и это не то, что должно быть сделано, скажем, в рабочей БД ... самый безопасный способ - это использоватьотдельные заявления.
  • Всегда включать проверку ограничений обратно
3 голосов
/ 24 ноября 2012

Вы можете указать «удалить каскад» на внешнем ключе.Когда вы удаляете родительскую строку, движок mysql удалит записи в связанных дочерних таблицах

0 голосов
/ 30 июля 2011

Удаляет в отдельных отчетах, и это будет работать.

...