使用10.0.31-MariaDB-1~jessie
。
我有两个表:provider_contact
和provider_contact_x_role
,其中contact_id
表中的provider_contact_x_role
列具有对{{1}的id
列的外键引用}表。
当我运行以下查询时,结果为成功:
provider_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 <> '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`))
条件。
问题:
1)SQL中是否有任何东西可以确保在执行这些查询时,首先删除WHERE
中的行?
2)知道这两个查询之间有什么区别(为什么第一个查询成功而第二个查询失败)吗?
答案 0 :(得分:1)
摘自MySQL文档:
如果您使用涉及InnoDB表的多表DELETE语句 对于有外键约束的情况,MySQL优化器可能 处理表的顺序不同于它们的顺序 父母/子女关系。在这种情况下,该语句将失败并滚动 背部。相反,您应该从单个表中删除并依靠 InnoDB提供的ON DELETE功能导致其他表 进行相应的修改。
如果您使用EXPLAIN
,您会发现它更喜欢先按主表过滤(并删除),因为它需要执行JOIN。
如果您使用INNER JOIN
,则可以尝试与STRAIGHT_JOIN
相同的INNER JOIN
,不同之处在于:总是先读取左表,然后再将右表放在右表中。您想要实现的删除顺序。
作为级联的替代,您可以使用SET FOREIGN_KEY_CHECKS=0;
禁用delete语句中的外键。
答案 1 :(得分:0)
您是否可以尝试先删除 provider_contact 表中的记录,而不要删除 provider_contact_x_role ,因为这是从 contact_id 外部强制执行参照完整性的原因键。
DELETE c, cr
FROM provider_contact AS c
INNER JOIN provider_contact_x_role AS cr
ON c.id = cr.contact_id
WHERE c.email_address <> 'suren@test.com';