奇怪的情况。
如果我有这些表格:
CREATE TABLE t1 (id INT, title VARCHAR(20), someIntCol INT)
GO
CREATE TABLE t2 (id INT, t1Id INT, someData VARCHAR(20))
GO
并且做:
SELECT t1.*
FROM t1
WHERE t1.id IN (SELECT someIntCol FROM t2)
奇怪的是:解析器并不介意列someIntCol不存在
奇怪的是:如果我将someIntCol更改为someIntCol2,我会得到一个“无效的列名'someIntCol2'。”错误
任何人都可以解释一下吗?
仅供参考,这不是我的代码。我是从this链接
获得的答案 0 :(得分:6)
尝试:
SELECT t1.*
FROM t1
WHERE t1.id IN (SELECT t2.someIntCol FROM t2)
这将在执行时抛出异常。
由于someIntCol
中存在t1
,因此它正在使用主查询中的该数据项。
子查询能够使用主查询中的数据项。因此,为避免这种情况,请在输入数据项时指定表名:
SELECT [TableName].[ColumnName]
如果您在t1
和t2
这是一个MSDN,它可以让您更好地理解子查询的工作原理:
http://msdn.microsoft.com/en-us/library/aa213262(v=sql.80).aspx
答案 1 :(得分:4)
在SQL Server中,解析步骤仅在语义上检查语法,例如以数字开头的非转义列,例如[2ndColumn]
而不是2ndColumn
(解析失败),关键字等,以及制作确保查询可以解析。这是单击SSMS中的解析按钮时发生的过程。此过程不会针对基础数据验证查询。
因此我可以键入SELECT abc FROM DEF
,即使我没有任何名为abc的列,甚至没有名为DEF的表。
下一步是algebrizer,它是绑定的过程。此步骤(仅在解析查询时不会发生)确保查询的每个对象实际存在,并且在您引用不存在的对象时将失败。
验证这一点的另一种方法是告诉SQL Server只解析,而不是做任何其他事情:
SET PARSEONLY ON
SELECT abc FROM def
GO
上面的查询会说“命令已成功执行。”
SET PARSEONLY OFF
SELECT abc FROM def
GO
上面的查询会说“无效的对象名称'def'。”
在您的示例问题中,someIntCol列存在于查询范围内,因为您尚未从中指定特定的来源。结果并没有多大意义,但它仍然不是一个无效的查询。
答案 2 :(得分:1)
Parser不介意因为他在t1中“看到”列someIntCol。你没有指定从哪个表中取出someIntCol所以解析器“假设”你想要它来自t1。
答案 3 :(得分:0)
你能找到吗
SELECT t1.* FROM t1 WHERE t1.id IN (SELECT someIntCol FROM t2)
表T2没有列“someIntCol”。
所以解析器显示错误