所以,这是您可以使用的测试查询:
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
并删除了所有数据。
答案 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
现在你应该知道原因了。