使用 10.0.31-MariaDB-1~jessie
。
我有两个表:provider_contact
和 provider_contact_x_role
其中 provider_contact_x_role
表中的 contact_id
列有一个外键引用provider_contact
表中的 id
列。
当我运行以下查询时,结果是成功的:
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 <> 'suren@test.com';
结果是下面的错误:
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 文档:
If you use a multiple-table DELETE statement involving InnoDB tables for which there are foreign key constraints, the MySQL optimizer might process tables in an order that differs from that of their parent/child relationship. In this case, the statement fails and rolls back. Instead, you should delete from a single table and rely on the ON DELETE capabilities that InnoDB provides to cause the other tables to be modified accordingly.
如果您使用 EXPLAIN
,您会发现它更喜欢先按主表过滤(和删除),因为它需要它来执行 JOIN。
如果您使用 INNER JOIN
,您可以尝试 STRAIGHT_JOIN
,它与 INNER JOIN
相同,只是左表始终是在右表之前阅读,并将表按照您想要实现的删除顺序排列。
除了级联,您还可以使用 SET FOREIGN_KEY_CHECKS=0;
在删除语句中禁用外键。
关于SQL Delete with Join 和 Foreign Key 约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51721919/