T-SQL MERGE使用UPDATE SET CASE语句 - 如果没有ELSE会发生什么?

3

我正在编写一条TSQL MERGE语句,用于处理常见的UPDATE和INSERT组合。如果一个参数设置为True,那么只有几个选择的列应该被更新。例如:

...
UPDATE SET
    TARGET.[SomeColumn] =
        CASE
        WHEN @someParameter = 1 THEN SOURCE.[SomeColumn]
    END,
...

根据我找到的所有文档,ELSE是可选的(与大多数语言相同),但如果在此处省略,我不明白会发生什么。当然我可以执行以下操作:
...
UPDATE SET
    TARGET.[SomeColumn] =
        CASE
        WHEN @someParameter = 1 THEN SOURCE.[SomeColumn]
        ELSE TARGET.[SomeColumn] --This is the new line
    END,
...

但这似乎会在重写现有值时带来不必要的开销。

所以我的问题是,如果省略ELSE并将@someParameter设置为0(FALSE),会发生什么?它会失败,设置为NULL,保持原值不变,还是...?


4
如果省略了else,那么case语句会返回NULL,因此值被设置为NULL - Gordon Linoff
正如@GordonLinoff所说,如果不匹配WHEN语句,您将得到NULL,ELSE提供了一个捕获所有的方法,告诉它对于未匹配任何WHEN语句的情况该怎么做(记住,您可以有多个WHEN语句)。 - Bridge
@GordonLinoff 当你这样说时,就非常有道理。非常感谢您的及时回复。 - Jon Bellamy
@Bridge 谢谢确认。答案如此简单,我开始感到有点傻问它! - Jon Bellamy
3个回答

3
在 MSDN 上表示,CASE 中不包含 ELSE 就意味着返回 NULL。
然而,MERGE 提供了另一种方法来实现此功能,并且适用于多个列。
WHEN MATCHED AND @someParameter = 1 THEN
    UPDATE SET
        TARGET.[SomeColumn] = SOURCE.[SomeColumn],
        TARGET.[SomeColumn2] = SOURCE.[SomeColumn2]

这是一个很好的建议,在我的示例的简单性中完美地运作。我最初想以这种方式做,但实际上在我的情况下需要进行几个参数,并且当然,单个MERGE语句不能多次更新相同的记录。有时候我想,如果将INSERT和UPDATE分开来简化两者是否更好,但我总是尝试寻找一次完成所有任务的方法(如果可能的话)。 - Jon Bellamy

3

实际上,它在MERGEUPDATE中并不重要,尽管您不知道这一点。 相关的文档是关于CASE关键字的:

ELSE else_result_expression

      如果没有比较操作评估为TRUE,则返回该表达式。 如果省略此参数并且没有比较操作评估为TRUE,则CASE返回NULL


感谢指出这一部分。我已经阅读了同一页内容,但不知何故完全错过了那一部分!!! - Jon Bellamy

0

我知道这是一个老问题,但这是我为实施ETL作业准备的示例。似乎需要else语句才能正常工作。这是在具有时间表的SQL Server 2017中完成的。

-- match to target on id
merge into Flags with (tablock) as target
using #Flags as source
  on source.id = target.id
-- on match update row
when matched then
  update set
    -- flags 1-4 can't be switched back to false from a true state
    target.flag1 = (
      case when source.flag1 >= target.flag1
        then source.flag1 
        else target.flag1 
      end ),
    target.flag2 = (
      case when source.flag2 >= target.flag2
        then source.flag2 
        else target.flag2 
      end ),
    target.flag3 = (
      case when source.flag3 >= target.flag3
        then source.flag3 
        else target.flag3 
      end ),
    target.flag4 = (
      case when source.flag4 >= target.flag4
        then source.flag4 
        else target.flag4 
      end ),
    -- flag 5 can only be true if flag 4 is be false
    target.flag5 = (
      case when target.flag4 = 1 
          or source.flag4 = 1 
        then 0 
        when source.flag5 >= target.flag5
        then source.flag5
        else target.flag5 
      end ),
    -- flag 6 can only be true if flags 4 & 5 are both false
    target.flag6 = (
      case when (target.flag4 = 1 
          or target.flag5 = 1) or 
            (source.flag4 = 1 
          or source.flag5 = 1)
        then 0 
        when source.flag6 >= target.flag6
        then source.flag6
        else target.flag6 
      end ),
    -- flag 7 can only be true if flags 4-6 are all false
    target.flag7 = (
      case when (target.flag4 = 1 
          or target.flag5 = 1
          or target.flag6 = 1) or 
            (source.flag4 = 1 
          or source.flag5 = 1
          or source.flag6 = 1)
        then 0 
        when source.flag7 >= target.flag7
        then source.flag7
        else target.flag7 
      end ),
    -- normal updates
    target.flag8 = source.flag8,
    target.flag9 = source.flag9 
-- no match insert row
when not matched by target then
  insert (
    id,
    flag1,
    flag2,
    flag3,
    flag4,
    flag5,
    flag6,
    flag7,
    flag8,
    flag9
  ) values (
    source.id,
    source.flag1,
    source.flag2,
    source.flag3,
    source.flag4,
    source.flag5,
    source.flag6,
    source.flag7,
    source.flag8,
    source.flag9
 )
;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接