SQL 使用连接和外键约束删除
SQL Delete with Join and Foreign Key constraint
使用 10.0.31-MariaDB-1~jessie
.
我有两个 table:provider_contact
和 provider_contact_x_role
其中 provider_contact_x_role
中的 contact_id
列 table 有一个外键引用id
列 provider_contact
table。
当我运行下面的查询结果是成功的:
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) 知道这两个查询之间有什么不同吗(为什么第一个成功而第二个失败)?
您能否尝试先删除 provider_contact table 中的记录,而不是 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';
摘自 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
,您会发现它更喜欢先按主 table 过滤(和删除),因为它需要它来执行 JOIN。
如果您使用 INNER JOIN
,您可以尝试 STRAIGHT_JOIN
,它与 INNER JOIN
相同,只是左边的 table 总是先于右边的 table 并把 table 放在你想要达到的删除顺序中。
除了级联之外,您可以使用 SET FOREIGN_KEY_CHECKS=0;
.
在删除语句中禁用外键
使用 10.0.31-MariaDB-1~jessie
.
我有两个 table:provider_contact
和 provider_contact_x_role
其中 provider_contact_x_role
中的 contact_id
列 table 有一个外键引用id
列 provider_contact
table。
当我运行下面的查询结果是成功的:
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) 知道这两个查询之间有什么不同吗(为什么第一个成功而第二个失败)?
您能否尝试先删除 provider_contact table 中的记录,而不是 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';
摘自 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
,您会发现它更喜欢先按主 table 过滤(和删除),因为它需要它来执行 JOIN。
如果您使用 INNER JOIN
,您可以尝试 STRAIGHT_JOIN
,它与 INNER JOIN
相同,只是左边的 table 总是先于右边的 table 并把 table 放在你想要达到的删除顺序中。
除了级联之外,您可以使用 SET FOREIGN_KEY_CHECKS=0;
.