sql - 如何意外删除表中的所有行

标签 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

创建一个临时表,其中包含整数 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 行...... 但是,#deletions 中没有 JobID,因此它会从外部查询中提取该信息,并最终以某种方式删除测试中的所有行。

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

在我看来,这应该会引发某种解析/语法错误或某种歧义错误。

这是一个 SQL Fiddle Demo

最佳答案

如果使用表别名,逻辑就会清晰。您认为您正在写:

delete from test
    where test.JobID in (select d.JobID from #deletions d);

这是有道理的,但它会生成语法错误,因为 #deletions 中不存在 JobId。因此,SQL 的范围规则进入下一个级别来查找 JobId 并将查询解释为:

delete from test
    where test.JobID in (select test.JobID from #deletions d);

这将删除 JobId 的所有非 NULL 值。

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

关于sql - 如何意外删除表中的所有行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30439633/

相关文章:

sql - Oracle 脚本问题 - 创建触发器未终止

java - 安卓 SQLite : CursorIndexOutOfBoundsException when retrieving a row from a table?

sql - 如何在 SQL 中找到连续的事件周?

sql - 如何在 SQL Server 2012 中从 Hashbytes 函数 SHA2_256 加密数据类型转换为 varchar(256)

c# - 如何在 .NET 中异步查询数据库

SQL 首先选择某个值

sql - 如何从 Apache Drill 中的时间戳字段中提取日期部分?

mysql - SQL复杂的select语句

mysql - 如何删除最后出现的逗号,逗号本身可能不是 SQL 中字符串的最后一个字符

像 PEPSI 这样的 SQL SERVER PIVOT 按年划分,然后按月份划分等。(请参阅附图以获得清晰的想法)