我想在两个以上的表上使用内部联接从表中删除记录。假如我在所有其他提到的表中共享了表A,B,C,D和A的pk。然后,如何编写删除查询以使用表B和A上的内部联接从表D中删除记录,因为从这两个表中获取条件。我从DB2的角度来看需要这个查询。我没有使用IN子句或EXISTS,因为它们有局限性。
答案 0 :(得分:11)
根据您的描述,我将架构视为:
A(pk_A,col1,col2,...)
B(pk_B,fk_A,col1,col2,...,外键fk_A引用A(pk_A))
C(pk_c,fk_A,col1,col2,...,外键fk_A引用A(pk_A))
D(pk_d,fk_A,col1,col2,...,外键fk_A引用A(pk_A))
正如您所说,如果使用IN子句,DB2将只允许删除1000行。我不了解DB2,但Oracle在IN子句中只允许1000个手动值。至少在Oracle中对子查询结果没有这样的限制。 EXISTS不应该是一个问题,因为任何数据库,包括Oracle和DB2只检查是否存在行,无论是一行还是一百万。
从表D中删除数据有三种情况:
您想要删除表D中的数据,其中fk_A(自然地)使用列A.pk_A引用表A中的记录:
DELETE FROM d
WHERE EXISTS (
SELECT 1
FROM a
WHERE a.pk_A = d.fk_A
);
您想要删除表D中的数据,其中fk_A引用表A中的记录,表A中的记录也由列B.fk_A引用。我们不想删除A中但不包含在B中的数据。我们可以写:
DELETE FROM d
WHERE EXISTS (
SELECT 1
FROM a
INNER JOIN b ON a.pk_A = b.fk_A
WHERE a.pk_A = d.fk_A
);
第三种情况是我们必须删除表D中引用表A中记录的数据,并且A中的记录也由列B.fk_A和表C.fk_A引用。我们想要从表D中删除 那些数据,这些数据在所有四个表中都很常见 - A,B,C和D.我们可以写:
DELETE FROM d
WHERE EXISTS (
SELECT 1
FROM a
INNER JOIN b ON a.pk_A = b.fk_A
INNER JOIN c ON a.pk_A = c.fk_A
WHERE a.pk_A = d.fk_A
);
根据您的要求,您可以合并其中一个查询。
请注意,如果子查询检索多行,“=”运算符将返回错误。另外,我不知道DB2是否支持ANY或ALL关键字,因此我使用了一个简单但功能强大的EXISTS关键字,其执行速度比IN,ANY和ALL快。
此外,您可以在此观察到EXISTS子句中的子查询使用“SELECT 1”,而不是“SELECT a.pk”或其他列。这是因为EXISTS在任何数据库中都只查找行的存在,而不是查找列中的任何特定值。
答案 1 :(得分:1)
基于'Using SQL to delete rows from a table using INNER JOIN to another table'
关键是您指定要删除的表的名称 作为SELECT。所以,JOIN和WHERE进行选择和限制, DELETE执行删除操作。您不仅限于一个 但是,桌子。如果你有多对多的关系(例如, 杂志和订阅者,通过订阅加入)和您 删除订阅者,您需要删除任何潜在的记录 加入模型也是如此。
DELETE subscribers
FROM subscribers INNER JOIN subscriptions
ON subscribers.id = subscriptions.subscriber_id
INNER JOIN magazines
ON subscriptions.magazine_id = magazines.id
WHERE subscribers.name='Wes';
答案 2 :(得分:0)
delete from D
where fk = (select d.fk from D d,A a,B b where a.pk = b.fk and b.fk = d.fk )
这应该有效