为什么不在子查询中出现“无效列名XYZ”错误;虽然列名不在子查询表中?

时间:2010-01-21 15:46:27

标签: sql sql-server sql-server-2005 tsql subquery

当我运行此查询时

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表中,但不存在于子查询中。

为什么会出现这种情况?这是子查询的东西吗?

感谢。

2 个答案:

答案 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

当使用当然可能的连接构造时,此查询将始终与原始查询一样好或更好 - 并且您还可以避免上述令人讨厌的问题。因为在这个构造中你自然会使用表名,当有问题时会更明显,比如等号两边的相同表名。子查询很糟糕,我正在对他们进行永久性的讨伐。

(也就是说,我知道很多人正在讨论别名,我上面用它来简化/压缩代码:))