子查询内的列名拼写错误,但没有“无效的列名”错误
我有一张桌子,我们称之为A
。我想从该表中删除 ID 为 1 和 2 的行。为此,我创建了一个表变量 @B
,其中包含值 1 和 2,但我将该列命名为 PK
。
现在我这样做:
DELETE FROM A
WHERE ID IN (
SELECT ID
FROM @B
)
注意我的(故意的)编程错误。在子选择中,我使用了错误的列名。不小心它与表 A 中使用的名称相同。
这应该会导致“无效的列名”错误,对吧?但事实并非如此。它执行。不仅如此,表 A 中的所有数据都被删除。就好像不再有谓词一样。
我已经创建了一个完整的演示脚本:
-- 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;
有人可以向我解释一下这里发生了什么吗?以前有人见过这种行为吗?这可能是一个错误吗?
I have a table, let's call it A
. I want to delete rows with IDs 1 and 2 from that table. For that, I created a table variable @B
, containing values 1 and 2 but that column I will name 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.
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. 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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在子查询
... (select id from @b)
中,列id
不是完全限定的。因此根据 SQL 规范,RDBMS 将首先查看表@b
中是否存在 id 列。如果没有,它将“向上”搜索,直到在表a
中找到 id 列。该查询实际上等同于:语法正确,语义错误。
In the subquery
... (select id from @b)
the columnid
is not fully qualified. So according to SQL specs, the RDBMS will first see if id column exists in table@b
. If it does not, it will search "upwards" until it finds the id column in tablea
. The query is effectively identical to:Syntactically correct, semantically wrong.