当我运行此查询时
SELECT CustomerId FROM Stocks.dbo.Suppliers
它给了我这个错误。列名称'CustomerId'无效。此错误有效,因为Suppliers表中没有列CustomerId;但是当我在子查询中使用相同的查询时,它不会给出任何错误,例如
SELECT *
FROM SomeOtherDb.dbo.Customer
WHERE CustomerId In( SELECT CustomerId
FROM Stocks.dbo.Suppliers)
这里我期待同样的错误“列名无效”,但查询运行没有任何错误。
完全限定名称只是约定,两个dbs都在同一台服务器上。
CustomerId确实存在于SomeOtherDb.dbo.Customer表中,但不存在于子查询中。
为什么会出现这种情况?这是子查询的东西吗?
感谢。
答案 0 :(得分:13)
子查询从外部查询继承列。
我猜你的SomeOtherDb.dbo.Customer确实有一个CustomerId列(似乎也可能来自名称)。
这也可能意味着你没有使用子查询你想用它做什么 - 如果子查询中的表没有CustomerId列(看起来如此,否则运行时就不会出错)子查询本身,然后子查询选择并返回外部CustomerId,因为这是子查询中唯一的列,子查询是无用的。
答案 1 :(得分:1)
你的问题的答案(“为什么没有错误”)在上面,但是对于如何在将来避免这种类型的问题可能有一些帮助:不使用子查询来执行此操作,使用左连接:
SELECT C.*
FROM SomeOtherDb.dbo.Customer AS C
LEFT JOIN Stocks.dbo.Suppliers AS S ON C.CustomerId = S.CustomerId
WHERE S.CustomerID Is Null
当使用当然可能的连接构造时,此查询将始终与原始查询一样好或更好 - 并且您还可以避免上述令人讨厌的问题。因为在这个构造中你自然会使用表名,当有问题时会更明显,比如等号两边的相同表名。子查询很糟糕,我正在对他们进行永久性的讨伐。
(也就是说,我知道很多人正在讨论别名,我上面用它来简化/压缩代码:))