我想在两个以上的表上使用内部联接从表中删除记录。假设我有 A、B、C、D 表,A 的 pk 在所有其他提到的表中共享。然后如何编写删除查询以使用表 B 和 A 上的内部连接从表 D 中删除记录,因为条件是从这两个表中获取的。从 DB2 的角度来看,我需要这个查询。由于它们的限制,我没有使用 IN 子句或 EXISTS。
3 回答
根据您的描述,我将架构视为:
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 引用。我们不想从 D 中删除 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 在任何数据库中只查找行的存在,而不是列内的任何特定值。
基于“使用 SQL 将使用 INNER JOIN 的表中的行删除到另一个表”
关键是您将要删除的表的名称指定为 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';
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 )
这应该工作