DELETE 子句删除的行多于 SELECT 子查询 returns

DELETE clause deletes more rows than the SELECT subquery returns

我有两个 table 具有相同的列但行数不同,table 有一个 3 列复合主键。

有 table1 原始 table 和 table2 更新后的 table,由于数据已删除,行数较少。我有一个 SELECT 声明 returns table1 中的行,但不在 table2 中;然而,当我使用 WHERE EXISTS 将 SELECT 语句作为子查询放在 DELETE 子句中时,它想要删除 table 1 中的所有行,而不仅仅是子查询中的行。

代码:

DELETE FROM table1
WHERE EXISTS(
SELECT t1.*
FROM table1 AS t1 LEFT JOIN table2 AS t2
ON (t1.compositekey1 = t2.compositekey1)
AND (t1.compositekey2 = t2.compositekey2)
AND (t1.compositekey3 = t2.compositekey3)
WHERE (t2.compositekey1 IS NULL) AND 
(t2.compositekey2 IS NULL) AND (t2.compositekey3 IS 
NULL)
);

我将子查询作为独立的 SELECT 查询进行了测试,它返回了 110 行,这是正确的数量,但是当放入上面的 DELETE 查询时,它想要删除所有 9600 行。我的印象是 WHERE EXISTS 应该只删除子查询返回的虚拟 table 中的行。

当我将反向查询用作 INSERT 查询时,将 table2 中不在 table1 中的所有行插入到 table1 中,它也工作正常.

所以我不知道我在哪里搞砸了 DELETE 语句。

我尝试使用:

WHERE t1.compositekey1, t1.compositekey2, t1.compositekey3 IN (......)

但是我收到一条错误消息说使用 EXISTS。这是在访问数据库中使用的,所以我猜同样的规则适用于 sql 服务器。

在此先感谢您的帮助。

您的子查询不相关,并且 return 至少有一行。因此 exists 总是 return true 并且删除操作会尝试删除所有内容。

尝试将 not exists 与相关子查询一起使用:

delete
from table1 t1
where not exists (
        select 1
        from table2 t2
        where t1.compositekey1 = t2.compositekey1
            and t1.compositekey2 = t2.compositekey2
            and t1.compositekey3 = t2.compositekey3
        );

您也可以使用左连接来做到这一点:

delete t1
from table1 t1
left join table2 t2 on t1.compositekey1 = t2.compositekey1
    and t1.compositekey2 = t2.compositekey2
    and t1.compositekey3 = t2.compositekey3
where t2.compositekey1 is null;

此外,我注意到您试图在子查询中检查所有三列是否为空。您只需检查一个 - 任何一个。

这也应该有效:

DELETE
FROM
    table1
WHERE
    EXISTS
    (
        SELECT
            *
        FROM
            table2
        WHERE
            table1.compositekey1 = table2.compositekey1
        AND table1.compositekey2 = table2.compositekey2
        AND table1.compositekey3 = table2.compositekey3 );