Question

So, here is the test query you could play with:

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

Actually, all these 10 records are deleted. The question is why are these 10 records deleted?

Note: xxx_id is one column in table A only, it doesn't exist in table B. But the delete statement "works" anyway.

Here's a demonstration of this behaviour: http://sqlfiddle.com/#!6/963f9/1/1

Update

I found the answer in MSDN: http://social.msdn.microsoft.com/Forums/en-US/418722dc-a7bf-44c5-a2f6-e8d1cd00dbdc/in-clause-ignores-error-in-subquery-possible-bug?forum=transactsql Actually, the MSSQL tried to blind the xxx_id to table B in subquery, if not found, it tries to blind it to table A. So, the query equals:

delete from #tmp WHERE xxx_id = xxx_id

and all data was deleted.

Was it helpful?

Solution

It's rather well-known behaviour. I'm not saying it's not somewhat unexpected.

The thing is that SQL Server tries to bind names to objects as one of first things id does with the query. With a subquery, it tries to bind columns to tables in the subquery first; if it don't succeed, it will bind columns to tables in outer query.

It's actually an excellent reason to always use aliases with tables.

OTHER TIPS

To check which kind of rows are deleted from A, you can query

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

To check what values are in sub query (SELECT xxx_id FROM B), you can query

SELECT xxx_id
FROM A, B

Which equals to

SELECT A.xxx_id,
FROM A, B

Now you should know the reason.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top