简体   繁体   English

子查询中的列名拼写错误,但没有“无效列名”错误

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM