DELETE子句删除的行比SELECT子查询返回的行数多

时间:2017-05-10 16:21:43

标签: sql sql-server database sql-delete delete-row

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

原始表有table1,table2有更少的行,因为数据已被删除。我有一个SELECT语句,返回table1中的行,但不返回table2中的行;然而,当我使用WHERE EXISTS将SELECT语句作为子查询放在DELETE子句中时,它想要删除表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应该只删除子查询返回的虚拟表中的行。

当我使用反向查询作为INSERT查询时,将table2中不在table1中的所有行插入表1中,它也可以正常工作。

所以我不知道我在哪里弄乱DELETE声明。

我试图使用:

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

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

提前感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

您的子查询没有相关性,并且至少返回一行。因此exists总是返回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;

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

答案 1 :(得分:0)

这也应该有效:

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