让我们用不区分大小写的东西来说明正在发生的事情:
USE tempdb;
GO
CREATE TABLE dbo.main_table(column1 INT);
CREATE TABLE dbo.other_table(column2 INT);
INSERT dbo.main_table SELECT 1 UNION ALL SELECT 2;
INSERT dbo.other_table SELECT 1 UNION ALL SELECT 3;
SELECT column1 FROM dbo.main_table
WHERE column1 IN (SELECT column1 FROM dbo.other_table);
结果:
column1
-------
1
2
为什么这不会引发错误?SQL Server 正在查看您的查询,发现里面的 column1 不可能在 other_table 中,因此它正在推断和“使用”外部引用表中存在的 column1(就像您可以引用仅存在于没有表引用的外部表)。想想这个变化:
SELECT [column1] FROM dbo.main_table
WHERE EXISTS (SELECT [column1] FROM dbo.other_table WHERE [column2] = [column1]);
结果:
column1
-------
1
SQL Server 再次知道 where 子句中的 column1 在本地引用的表中也不存在,但它会尝试在外部范围内找到它。因此,在想象的世界中,您可能会认为查询实际上是在说:
SELECT m.[column1] FROM dbo.main_table AS m
WHERE EXISTS (SELECT m.[column1] FROM dbo.other_table AS o WHERE o.[column2] = m.[column1]);
(这不是我输入的方式,但如果我这样输入,它仍然有效。)
在某些情况下它没有逻辑意义,但这是查询引擎的方式,并且必须一致地应用规则。在你的情况下(没有双关语),你有一个额外的复杂性:区分大小写。SQL Server 没有FIELD
在您的子查询中找到它,但它确实在外部查询中找到了它。所以有几个教训:
- 始终使用表名或别名作为列引用的前缀(并始终在表引用前加上 schema)。
- 始终使用一致的大小写创建和引用您的表、列和其他实体。特别是在使用二进制或区分大小写的排序规则时。