我今天遇到了一个奇怪的问题,我认为它会失败,但它以一种意想不到的方式取得了成功。这是对它的最小再现。
表格和数据:
CREATE TABLE Employee(ID int, Name varchar(max))
CREATE TABLE Engineer(ID int, Title varchar(max))
GO
INSERT INTO Employee(ID, Name) VALUES (1, 'Bobby')
INSERT INTO Employee(ID, Name) VALUES (2, 'Sue')
INSERT INTO Engineer(ID, Title) VALUES (1, 'Electrical Engineer')
INSERT INTO Engineer(ID, Title) VALUES (2, 'Network Engineer')
查询:
--Find all Engineers with same title as Bobby has
SELECT * FROM Engineer WHERE Title IN (select Title from Employee WHERE Name = 'Bobby')
这将返回Engineer表中的所有行(意外,我认为它会失败)。请注意,上述查询不正确。内部查询使用“Title”列,该列在“(Employee”)中选择的表中不存在。所以它必须在外部查询中绑定Engineer列中的Title值....它始终等于它自己,所以我认为返回所有行。
如果我完全限定列名,我也可以强制它,并且会按预期失败:
SELECT * FROM Engineer WHERE Title IN
(select Empl.Title from Employee Empl WHERE Name = 'Bobby')
此操作失败并显示“无效的列名称'标题'。”
显然,如果我要将Title列添加到Employee表中,它会改为使用Employee.Title
列值。
ALTER TABLE Employee ADD Title varchar(max)
GO
UPDATE Employee SET Title = 'Electrical Engineer' WHERE ID = 1
UPDATE Employee SET Title = 'Network Engineer' WHERE ID = 2
SELECT * FROM Engineer WHERE Title IN
(select Title from Employee WHERE Name = 'Bobby')
这只返回一行(如预期的那样)。
我有点理解这里发生了什么,我正在寻找的是一些链接到一些文档或一些关键字,可以帮助我完整地阅读和理解它(甚至是一些解释)。
答案 0 :(得分:0)
当然失败了。您的Employee表中没有名为Title的列。在确实有效的查询中,它是一个子查询,因此它从工程师中提取标题。
如果您养成了使用2部分命名而不仅仅是列名称来引用列的习惯,那么您可以完全避免这种情况。
但是在您的查询中,您应该开始学习如何使用连接而不是子查询来处理所有事情。你的代码就不那么容易混淆了。
答案 1 :(得分:0)
由于Title不合格,因此使用表工程师的标题
SELECT * FROM Engineer WHERE Title IN (select Title from Employee WHERE Name = 'Bobby')
在最后,它使用最近的标题(来自员工)。
如果您使用别名和2部分名称,那么您可以避免这种混乱。
至于文件。查找最近的列可能是一个未记录的功能。
答案 2 :(得分:0)
我找到了有关行为的文档:Qualifying Column Names in Subqueries
一般规则是语句中的列名由同一级别的FROM子句中引用的表隐式限定。如果子查询的FROM子句中引用的表中不存在列,则它将由外部查询的FROM子句中引用的表隐式限定。