[英]Typo in a column name inside a sub-query, but no "Invalid column name" error
I have a table, let's call it A
.我有一张桌子,我们称之为A
。 I want to delete rows with IDs 1 and 2 from that table.我想从该表中删除 ID 为 1 和 2 的行。 For that, I created a table variable @B
, containing values 1 and 2 but that column I will name PK
.为此,我创建了一个表变量@B
,其中包含值 1 和 2 但我将该列命名为PK
。
Now I do this:现在我这样做:
DELETE FROM A
WHERE ID IN (
SELECT ID
FROM @B
)
Notice my (deliberate) programming error.请注意我的(故意的)编程错误。 In the sub-select, I have used a wrong column name.在子选择中,我使用了错误的列名。 Accidentally it is the same name used in table A.不小心它与表 A 中使用的名称相同。
This should result in an 'invalid column name' error, right?这应该会导致“无效的列名”错误,对吗? Except it does not.除了它没有。 It executes.它执行。 Not only that, all data from table A gets deleted.不仅如此,表 A 中的所有数据都被删除。 As if there is no more predicate.好像没有更多的谓词。
I have created a full demo script:我创建了一个完整的演示脚本:
-- What happened to my data???
IF OBJECT_ID('tempdb..#JustATable') IS NOT NULL
DROP TABLE #JustATable
CREATE TABLE #JustATable (
PK INT NOT NULL PRIMARY KEY IDENTITY(1, 1),
ID INT NOT NULL,
NOTE VARCHAR(100) NOT NULL
)
INSERT INTO #JustATable (ID, NOTE)
SELECT database_id, DB_NAME(database_id)
FROM sys.databases;
SELECT NULL [inserted all the rows from sys.databases into the temptable], *
FROM #JustATable;
DECLARE @JustATableVariable TABLE (
PK INT NOT NULL PRIMARY KEY IDENTITY(1, 1),
ID_2 INT NOT NULL,
NOTE VARCHAR(100) NOT NULL
)
INSERT INTO @JustATableVariable (ID_2, NOTE)
SELECT database_id, DB_NAME(database_id)
FROM sys.databases
WHERE database_id = 2;
SELECT NULL [this is my table variable data], *
FROM @JustATableVariable;
DELETE FROM #JustATable
WHERE ID IN (
SELECT ID_2
FROM @JustATableVariable
);
SELECT NULL [I have just removed tempdb from the temptable], *
FROM #JustATable;
DELETE FROM #JustATable
WHERE ID IN (
SELECT ID /* this is the wrong column name but the same name as used in the temptable column */
FROM @JustATableVariable
);
SELECT NULL [wait...where is my data?], *
FROM #JustATable;
Can someone explain to me what is going on here?有人可以向我解释这里发生了什么吗? Has anyone seen this behavior before?有没有人见过这种行为? Could this be a bug?这可能是一个错误吗?
In the subquery ... (select id from @b)
the column id
is not fully qualified.在子查询... (select id from @b)
列id
不是完全限定的。 So according to SQL specs, the RDBMS will first see if id column exists in table @b
.因此根据 SQL 规范,RDBMS 将首先查看表@b
中是否存在 id 列。 If it does not, it will search "upwards" until it finds the id column in table a
.如果没有,它将“向上”搜索,直到在表a
中找到 id 列。 The query is effectively identical to:该查询实际上等同于:
delete from a where id in (select a.id from @b)
Syntactically correct, semantically wrong.语法正确,语义错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.