有人想尝试解释这个问题的机制......今天查询解析器的这个小怪癖几乎对我造成了重大损害。
创建一个包含100行的测试表,其中包含1-100。
create table test( JobID int primary key);
;with numbers as (
select 1 as n
union all
select n + 1 as n
from numbers
where n < 100
)
insert into test
select n from numbers
创建一个包含整数1-50的临时表:
select jobid as number into #deletions
from test
where jobid <= 50
现在使用IN
子句进行删除,但内部查询中的列名错误:
delete from test where JobID in (select JobID from #deletions)
最后一个删除声明,从外观上看,给出了删除50行的外观......
但是,JobID
中没有#deletions
,所以它会从外部查询中获取,并最终以某种方式删除测试中的所有行。
我的问题是,它究竟是如何解释内部查询... #deletions
只有50行,那么如何从外表中提取所有100个id?这种类型的错字/错误几乎对我今天造成了重大损害。
在我看来,这应该会产生某种解析/语法错误或某种模糊错误。
答案 0 :(得分:10)
如果使用表别名,则逻辑清晰。你以为你在写:
delete from test
where test.JobID in (select d.JobID from #deletions d);
这是有道理的,但它会产生语法错误,因为JobId
中不存在#deletions
。因此,SQL的范围规则进入下一级别以查找JobId
并将查询解释为:
delete from test
where test.JobID in (select test.JobID from #deletions d);
这将删除JobId
的所有非NULL值。
道德:始终使用合格的列名。