我有两个列相同但行数不同的表,这些表有一个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。
提前感谢您的帮助。
答案 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 );