子查询中列名的拼写错误,但没有 "Invalid column name" 错误
Typo in a column name inside a sub-query, but no "Invalid column name" error
我有一个table,暂且称它为A
。我想从 table 中删除 ID 为 1 和 2 的行。为此,我创建了一个 table 变量 @B
,其中包含值 1 和 2,但我将该列命名为 PK
.
现在我这样做:
DELETE FROM A
WHERE ID IN (
SELECT ID
FROM @B
)
注意我的(故意的)编程错误。在子select中,我使用了错误的列名。不小心它与 table A.
中使用的名称相同
这应该会导致 'invalid column name' 错误,对吧?除了它没有。它执行。不仅如此,来自 table 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;
谁能给我解释一下这是怎么回事?有没有人见过这种行为?这可能是一个错误吗?
在子查询 ... (select id from @b)
中,列 id
不是完全限定的。因此根据 SQL 规范,RDBMS 将首先查看 id 列是否存在于 table @b
中。如果没有,它将“向上”搜索,直到在 table a
中找到 id 列。该查询实际上等同于:
delete from a where id in (select a.id from @b)
语法正确,语义错误。
我有一个table,暂且称它为A
。我想从 table 中删除 ID 为 1 和 2 的行。为此,我创建了一个 table 变量 @B
,其中包含值 1 和 2,但我将该列命名为 PK
.
现在我这样做:
DELETE FROM A
WHERE ID IN (
SELECT ID
FROM @B
)
注意我的(故意的)编程错误。在子select中,我使用了错误的列名。不小心它与 table A.
中使用的名称相同这应该会导致 'invalid column name' 错误,对吧?除了它没有。它执行。不仅如此,来自 table 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;
谁能给我解释一下这是怎么回事?有没有人见过这种行为?这可能是一个错误吗?
在子查询 ... (select id from @b)
中,列 id
不是完全限定的。因此根据 SQL 规范,RDBMS 将首先查看 id 列是否存在于 table @b
中。如果没有,它将“向上”搜索,直到在 table a
中找到 id 列。该查询实际上等同于:
delete from a where id in (select a.id from @b)
语法正确,语义错误。