具有联接和外键约束的SQL删除

苏伦·阿兹纳里扬(Suren Aznauryan)

使用10.0.31-MariaDB-1~jessie

我有两个表:provider_contactprovider_contact_x_role其中contact_id在列provider_contact_x_role表中有一个外键引用idprovider_contact的表。

当我运行以下查询时,结果为成功:

DELETE cr, c
FROM provider_contact_x_role AS cr
INNER JOIN provider_contact AS c
ON cr.contact_id = c.id
WHERE c.is_test_contact = 0;

当我运行下一个查询时:

DELETE cr, c
FROM provider_contact_x_role AS cr
INNER JOIN provider_contact AS c
ON cr.contact_id = c.id
WHERE c.email_address <> '[email protected]';

结果是以下错误:

Cannot delete or update a parent row: a foreign key constraint fails 
(`ins_db`.`provider_contact_x_role`, CONSTRAINT 
`FK_contact_id--provider_contact.id` FOREIGN KEY (`contact_id`) 
REFERENCES `provider_contact` (`id`))

请注意,这两个查询之间的唯一区别是WHERE条件。

问题:

1)SQL中是否有任何东西可以确保在执行这些查询时,provider_contact_x_role首先删除中的行

2)知道这两个查询有什么区别(为什么第一个查询成功而第二个查询失败)?

音素

从MySQL文档中摘录:

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

而且,如果您使用它,EXPLAIN您会发现它更喜欢先通过主表过滤(并删除),因为它需要执行JOIN。

如果使用INNER JOIN,则可以尝试STRAIGHT_JOIN与进行相同的操作,INNER JOIN不同的是,总是先读取左表,然后再读取右表,然后按要实现的删除顺序排列这些表。

除了级联之外,还可以使用禁用Delete语句中的外键SET FOREIGN_KEY_CHECKS=0;

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章