如何不小心删除表中的所有行

Bre*_*een 6 sql sql-server

有人想要解释一下这个问题的机制...这个查询解析器的小怪癖几乎对我造成了重大损害.

创建一个包含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
Run Code Online (Sandbox Code Playgroud)

创建一个包含整数1-50的临时表:

select jobid as number into #deletions
from test 
where jobid <= 50
Run Code Online (Sandbox Code Playgroud)

现在使用IN子句进行删除,但内部查询中的列名错误:

delete from test where JobID in (select JobID from #deletions)
Run Code Online (Sandbox Code Playgroud)

从外观上看,最后一个删除语句给出了删除50行的外观......但是,没有JobID输入#deletions,所以它从外部查询中拉出来并最终以某种方式删除测试中的所有行.

我的问题是,它究竟是如何解释内部查询... #deletions只有50行,那么如何从外表中提取所有100个id?这种类型的错字/错误几乎对我今天造成了重大损害.

在我看来,这应该抛出某种解析/语法错误或某种歧义错误.

这是一个 SQL Fiddle Demo

Gor*_*off 10

如果使用表别名,则逻辑清晰.你以为你在写:

delete from test
    where test.JobID in (select d.JobID from #deletions d);
Run Code Online (Sandbox Code Playgroud)

这是有道理的,但它会产生语法错误,因为JobId它不存在#deletions.因此,SQL的范围规则进入下一级别,以查找JobId和解释查询:

delete from test
    where test.JobID in (select test.JobID from #deletions d);
Run Code Online (Sandbox Code Playgroud)

这将删除所有非NULL值JobId.

道德:始终使用合格的列名.