使用IN子句删除数据,即使该列不存在也是如此

时间:2014-04-25 09:04:54

标签: sql-server sql-delete

所以,这是您可以使用的测试查询:

select top 10 * into #tmp FROM A
delete from #tmp WHERE xxx_id in (select xxx_id FROM B)

实际上,所有这10条记录都被删除了。问题是为什么删除这10条记录?

注意:xxx_id只是表A中的一列,它不存在于表B中。但删除声明"工作"反正。

以下是此行为的演示:http://sqlfiddle.com/#!6/963f9/1/1

更新

我在MSDN中找到答案:http://social.msdn.microsoft.com/Forums/en-US/418722dc-a7bf-44c5-a2f6-e8d1cd00dbdc/in-clause-ignores-error-in-subquery-possible-bug?forum=transactsql 实际上,MSSQL试图在子查询中将xxx_id隐藏到表B,如果没有找到,它会试图将其盲目地放到表A。所以,查询等于:

delete from #tmp WHERE xxx_id = xxx_id

并删除了所有数据。

2 个答案:

答案 0 :(得分:3)

这是众所周知的行为。我并不是说这不是意料之外的事。

问题在于SQL Server尝试将名称绑定到对象,这是id对查询做的第一件事。使用子查询,它首先尝试将列绑定到子查询中的表;如果它不成功,它会将列绑定到外部查询中的表。

这实际上是一直使用表别名的绝佳理由。

答案 1 :(得分:0)

要检查从A中删除哪种行,您可以查询

SELECT *
FROM A
WHERE xxx_id IN (SELECT xxx_id FROM B)

要检查子查询中的值(SELECT xxx_id FROM B),可以查询

SELECT xxx_id
FROM A, B

等于

SELECT A.xxx_id,
FROM A, B

现在你应该知道原因了。