【问题标题】:When using multiple WHEN MATCHED statements, do they all execute, or does only one get executed?当使用多个 WHEN MATCHED 语句时,它们是全部执行,还是只执行一个?
【发布时间】:2013-05-26 16:57:03
【问题描述】:

如果我在一个 MERGE 语句中有多个 WHEN MATCHED 语句,如果它们为真,它们都会执行吗?

我的例子:

DECLARE @X bit = NULL;

--skipping the MERGE statement, straight to WHEN MATCHED

WHEN MATCHED AND A = 1
    @X = 0;
WHEN MATCHED AND B = 1
    @X = 1;

在 4 种可能性中,X 的状态是什么?

A|B|X
0|0|?
0|1|?
1|0|?
1|1|?

基本上,我很好奇每个 WHEN MATCHED 子句之后是否有隐含的 BREAK。

【问题讨论】:

    标签: sql sql-server database tsql merge


    【解决方案1】:

    我在MSDN documentation找到:

    当匹配然后

    指定 target_table 中与 ON 返回的行匹配并满足任何附加搜索条件的所有行都根据该子句进行更新或删除。

    MERGE 语句最多可以有两个 WHEN MATCHED 子句。如果指定了两个子句,则第一个子句必须伴随一个 AND 子句。对于任何给定的行,第二个 WHEN MATCHED 子句仅在第一个不是时才应用。如果有两个 WHEN MATCHED 子句,则一个必须指定一个 UPDATE 操作,一个必须指定一个 DELETE 操作。如果在子句中指定了 UPDATE,并且多于一行匹配 target_table based on 中的一行,则 SQL Server 返回错误。 MERGE 语句不能多次更新同一行,或者更新和删除同一行。

    所以看起来只有一个语句被执行,它们需要一个 DELETE 和另一个 UPDATE。

    【讨论】:

    • 这对于了解最大值 2 很有用;但是,它不再需要 DELETE 语句(如果确实如此)。我不知道他们为什么会这么说;这种行为在很多情况下都是不合适的。
    【解决方案2】:

    要回答您的问题,是的,它只会运行一场比赛然后中断。但是,如果您希望在更新中具有允许条件匹配的逻辑,CASE 语句对此非常有用。

    像这样的例子:

    MERGE INTO YourTable
    USING (VALUES (1, 1, NULL), (0, 0, NULL), (0, 1, NULL), (1, 0, NULL))
           T2 (a2,b2,c2)
    ON a = a2 AND b = b2
    WHEN MATCHED  THEN
        UPDATE SET c = 
          CASE 
            WHEN a = 1 THEN 0
            WHEN b = 1 THEN 1
            ELSE NULL
          END        
    WHEN NOT MATCHED THEN
        INSERT (a, b) VALUES (a2, b2);
    
    SELECT * FROM YourTable ORDER BY a,b;
    

    结果:

    A   B   C
    --------------
    0   0   (null)
    0   1   1
    1   0   0
    1   1   0
    

    【讨论】:

    • 从未听说过 SQLFiddle,这该死的有用。感谢您的全面回答。我的问题最终出现在存储过程中的其他地方,但这回答了我原来的问题,所以我会标记它。谢谢!
    • @Pheonixblade9 -- np,我同意,Fiddle 很棒。最好的问候。
    • 这样做的问题是您必须为要更改的每个字段重复 case 语句。
    【解决方案3】:

    嗯,答案是,你真的想这样做吗,因为如果你这样做,你会通​​过痛苦的慢行更新来改变一行的基于集合的更新,就像在一组行中你真的不知道记录上的哪些列发生了变化以记录为基础。

    因此,问题是您想获得性能吗?如果是这样,请确保您有涵盖

    的索引
    WHEN MATCHED TARGET.FIELD1 = SOURCE:FIELD1 AND TARGET.FIELD2 = SOURCE:FIELD2 ... 
    

    如果不是,您将不得不在合并后使用INSTEAD OF 触发器将光标悬停在您的更新上...

    不利于速度,但是,如果您需要记录谁做了什么,则可以工作......

    快乐编码

    沃尔特

    【讨论】:

      猜你喜欢
      • 2018-02-18
      • 2013-01-23
      • 1970-01-01
      • 2016-05-10
      • 1970-01-01
      • 1970-01-01
      • 2012-06-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多