在不更新外键的情况下使用ON DELETE CASCADE

时间:2018-09-17 07:20:48

标签: mysql foreign-keys

我必须删除具有外键关系的多个表中的数据。我可以使用外键定义中的ON DELETE CASCADE规则轻松地做到这一点,但我不想这样做。我只想创建一个可以执行ON DELETE CASCADE功能而不更新我的FK的查询,但是我不知道该怎么做。

我尝试创建多个delete语句,每个表一个,但这似乎太麻烦了。

从具有FK关系的多个表中删除数据的最简单方法是什么?

1 个答案:

答案 0 :(得分:1)

尽管on delete cascade是首选的方法,但是您也可以使用单个delete查询来完成此操作,因为它支持从多个表中删除。如果您可以正确地连接表(您应该可以通过它们的外键关系轻松地进行连接),则可以立即从它们中删除:

  

您可以在DELETE语句中指定多个表,以根据WHERE子句中的条件从一个或多个表中删除行。 [...],仅删除FROM子句之前列出的表中匹配的行。

因此您可以使用例如:

CREATE TABLE parent (
    id INT PRIMARY KEY
);
CREATE TABLE child (
    id INT PRIMARY KEY,
    parent_id INT,
    FOREIGN KEY (parent_id) REFERENCES parent (id)
);

INSERT INTO parent(id) VALUES (1), (2), (3);
INSERT INTO child(id, parent_id) VALUES (1,1), (2,1), (3,2), (4,2), (5,3), (6,3);

SET FOREIGN_KEY_CHECKS=0;

DELETE child, parent 
FROM child
JOIN parent ON child.parent_id = parent.id 
WHERE parent.id = 1;

SET FOREIGN_KEY_CHECKS=1;

您几乎无法控制删除顺序,并且在几乎每种情况下,MySQL都倾向于使用违反外键约束的执行顺序(因为这可能是连接表的唯一可行方法),因此要工作,您需要暂时禁用FOREIGN_KEY_CHECKS;另请参见the manual中的备注:

  

如果您使用涉及InnoDB表的多表DELETE语句(对于该表具有外键约束),则MySQL优化器可能以与其父/子关系不同的顺序处理表。在这种情况下,该语句将失败并回滚。相反,您应该从单个表中删除,并依靠InnoDB提供的ON DELETE功能来相应地修改其他表。