为什么COALESCE会为单个列返回多个无效列名错误?

时间:2014-08-20 15:13:03

标签: sql sql-server function sql-server-2012 coalesce

使用COALESCE编写SQL查询时,我注意到在特定情况下,它会为单个无效列名称抛出多个错误。

如果我编写以下查询并尝试执行它,我会收到一条错误消息,告诉我,简而言之,我是一个白痴,而且该列不存在。

DECLARE @a TABLE (Column1 INT, Column2 INT)

-- This will return one error, complaining about NeverHeardOfIt
SELECT 
    COALESCE
      (
        Column1, 
        Column2, 
        NeverHeardOfIt
      ) 
FROM @a
  

消息207,级别16,状态1,行8无效的列名称   'NeverHeardOfIt'。

但是,如果我稍微改变查询以在COALESCE语句中放置无效列,我将收到两个错误:

DECLARE @a TABLE (Column1 INT, Column2 INT)

-- This will return two errors, both complaining about NeverHeardOfIt
SELECT 
    COALESCE
      (
        Column1, 
        NeverHeardOfIt, 
        Column2
      ) 
FROM @a 
  

消息207,级别16,状态1,行7无效的列名称   '从来没有听说过'。

     

消息207,级别16,状态1,行7无效列   名字'NeverHeardOfIt'。

我测试了几种不同的场景,似乎只有当我合并三列或更多列时才会发生这种情况,并且无效列不是最后一列。显然,“修复”这很容易 - 不要引用无效列!但我很想知道为什么COALESCE()函数会两次抛出相同的错误。我能想到的最好的是,在引擎盖下,SQL正在编写多个语句,这些语句的内容如下:

  

如果第1列为NULL,请使用NeverHeardOfIt

     

如果NeverHeardOfIt为NULL,请使用Column2

     

如果Column2为NULL ...

如果是这种情况,那么当我执行它时,我可以看到函数如何/为什么会为它在幕后生成的每个'语句'返回错误。

有人知道这是否正确,或者知道另一个原因会导致两个错误吗?

1 个答案:

答案 0 :(得分:3)

我会将双错误消息视为一个错误,但是非常小。但是,原因是coalesce()(以及choose())真的是速记。所以:

coalesce(a, b, c)

真的:

(case when a is not null then a
      when b is not null then b
      else c
 end)

请注意,最后一个元素只出现一次 - 因此,当缺失的列结束时,您只会收到一个错误。

这似乎是一个神秘的细节,但它确实很重要。例如,如果其中一个值是子查询 - 并且子查询的运行成本很高 - 那么它在coalesce()的评估中运行两次。如果性能是一个问题而且一个或多个值是子查询,那么即使我更喜欢isnull(),在这些情况下表现更好。通常,我的偏见是使用ANSI标准函数。