【问题标题】:MERGE - Multiple WHEN MATCHED cases with updateMERGE - 多个 WHEN MATCHED 案例与更新
【发布时间】:2016-01-15 06:25:55
【问题描述】:

当我启动此请求时,我收到 SQL Server 编号错误 10714。 我知道我不能在 WHEN MATHED 中使用多个更新,但我不知道该怎么做。

MERGE INTO Photo p
USING TmpPhoto tp
ON p.ProductNumberID = tp.ProductNumberID and p.SHA1 = tp.SHA1
WHEN MATCHED AND p.Rank = tp.Rank THEN
    UPDATE SET p.VerifiedDate = getDate()
WHEN MATCHED AND p.Rank != tp.Rank AND tp.Rank != 1 THEN
    UPDATE SET p.VerifiedDate = getDate(), p.Rank = tp.Rank, p.Active = 0
WHEN MATCHED AND p.Rank != tp.Rank AND tp.Rank = 1 THEN
    UPDATE SET p.VerifiedDate = getDate(), p.Rank = tp.Rank, p.Active = 1
WHEN NOT MATCHED THEN
    INSERT (ProductNumberID, Code, Extension, Rank, CreatedDate, VerifiedDate, FCTH, SHA1, Active)
    VALUES (tp.ProductNumberID, tp.Code, tp.Extension, tp.Rank, getdate(), getdate(), tp.FCTH, tp.SHA1, 0)
    OUTPUT inserted.NumberID as PhotoNumberID, inserted.ProductNumberID, inserted.SHA1, inserted.Rank INTO InsertedPhotos;

【问题讨论】:

标签: sql sql-server merge


【解决方案1】:

简化版(verifiedDate 始终更新,rank 始终更新,因为如果相等则保持不变,唯一更改的字段是 p.Active 使用CASE

MERGE INTO Photo p
USING TmpPhoto tp
    ON p.ProductNumberID = tp.ProductNumberID and p.SHA1 = tp.SHA1
    WHEN MATCHED 
     THEN
       UPDATE SET 
           p.VerifiedDate = getDate(),
           p.RANK = tp.RANK,
           p.Active = 
              (CASE
                WHEN p.Rank != tp.Rank AND tp.Rank != 1 THEN 0
                WHEN p.Rank != tp.Rank AND tp.Rank = 1 THEN 1
                ELSE p.Active END
             )
    WHEN NOT MATCHED THEN
        INSERT (ProductNumberID, Code, Extension, Rank, CreatedDate, VerifiedDate, FCTH, SHA1, Active)
        VALUES (tp.ProductNumberID, tp.Code, tp.Extension, tp.Rank, getdate(), getdate(), tp.FCTH, tp.SHA1, 0)
        OUTPUT inserted.NumberID as PhotoNumberID, inserted.ProductNumberID, inserted.SHA1, inserted.Rank INTO InsertedPhotos;

【讨论】:

  • 您刚刚忘记了 CASE 之后的 WHEN 字样(请参阅其他答案...)
  • 更新了我的答案。感谢您的关注
【解决方案2】:

如果可以,请在 UPDATE 子语句中使用 CASE 表达式来模拟具有多个 WHEN MATCHED 子句的行为。像这样的:

MERGE INTO Photo p
USING TmpPhoto tp
ON p.ProductNumberID = tp.ProductNumberID and p.SHA1 = tp.SHA1
WHEN MATCHED THEN
    UPDATE 
       SET p.VerifiedDate = getDate(),
           p.Rank = CASE 
                        WHEN p.Rank != tp.Rank AND tp.Rank != 1 THEN tp.Rank                       
                        ELSE p.Rank
                    END,
           p.Active = CASE
                          WHEN p.Rank = tp.Rank THEN p.Active 
                          WHEN tp.Rank != 1 THEN 0
                          ELSE 1
                      END
WHEN NOT MATCHED THEN
    INSERT (ProductNumberID, Code, Extension, Rank, CreatedDate, VerifiedDate, FCTH, SHA1, Active)
    VALUES (tp.ProductNumberID, tp.Code, tp.Extension, tp.Rank, getdate(), getdate(), tp.FCTH, tp.SHA1, 0)
    OUTPUT inserted.NumberID as PhotoNumberID, inserted.ProductNumberID, inserted.SHA1, inserted.Rank INTO InsertedPhotos;

它的作用是将关于更新哪些字段以及如何更新的逻辑转移到CASE 表达式中。请注意,如果不更新字段,则只需将其设置为自身。在 SQL Server 中,这似乎是一个空操作。但是,我不确定它是否会算作触发器的修改列。您可以随时测试该行是否在触发器中实际更改,以避免这种方法可能导致的任何问题。

【讨论】:

    【解决方案3】:

    您是否考虑过在更新时使用CASE 语句?

    这里的某个地方可能存在语法问题。让我知道这是否有效。

    MERGE INTO Photo p
    USING TmpPhoto tp
        ON p.ProductNumberID = tp.ProductNumberID
        AND p.SHA1 = tp.SHA1
    WHEN MATCHED THEN
        UPDATE SET p.VerifiedDate = GETDATE()
            , p.Rank = CASE
                WHEN p.Rank != tp.Rank THEN tp.Rank
                ELSE p.Rank
            END
            , p.Active = CASE
                WHEN p.Rank != tp.Rank AND tp.Rank != 1 THEN 0
                WHEN p.Rank != tp.Rank AND tp.Rank = 1 THEN 1
                ELSE p.Active
            END
    WHEN NOT MATCHED THEN
        INSERT (ProductNumberID, Code, Extension, Rank, CreatedDate, VerifiedDate, FCTH, SHA1, Active)
        VALUES (tp.ProductNumberID, tp.Code, tp.Extension, tp.Rank, getdate(), getdate(), tp.FCTH, tp.SHA1, 0)
        OUTPUT inserted.NumberID as PhotoNumberID, inserted.ProductNumberID, inserted.SHA1, inserted.Rank INTO InsertedPhotos;
    

    【讨论】:

      【解决方案4】:

      您为什么不尝试使用CASE 语句,

      MERGE INTO 
            Photo p
      USING 
            TmpPhoto tp  ON p.ProductNumberID = tp.ProductNumberID 
                         AND p.SHA1 = tp.SHA1
      WHEN 
          MATCHED AND p.Rank = tp.Rank 
      THEN
          UPDATE 
              SET    p.VerifiedDate = GETDATE(),
                     p.Rank = CASE 
                                  WHEN p.Rank != tp.Rank AND tp.Rank != 1 THEN tp.Rank
                                  WHEN p.Rank != tp.Rank AND tp.Rank  = 1 THEN tp.Rank
                                  ELSE p.Rank END,
                     p.Active = CASE 
                                  WHEN p.Rank != tp.Rank AND tp.Rank != 1 THEN 0
                                  WHEN p.Rank != tp.Rank AND tp.Rank  = 1 THEN 1
                                  ELSE p.Active END
      WHEN 
          NOT MATCHED
      THEN
          INSERT (ProductNumberID, Code, Extension, Rank, CreatedDate, VerifiedDate, FCTH, SHA1, Active)
          VALUES (tp.ProductNumberID, tp.Code, tp.Extension, tp.Rank, getdate(), getdate(), tp.FCTH, tp.SHA1, 0)
          OUTPUT inserted.NumberID as PhotoNumberID, inserted.ProductNumberID, inserted.SHA1, inserted.Rank INTO InsertedPhotos;
      

      【讨论】:

        猜你喜欢
        • 2017-02-13
        • 1970-01-01
        • 2012-12-05
        • 2016-05-10
        • 1970-01-01
        • 2018-02-18
        • 1970-01-01
        • 1970-01-01
        • 2017-01-24
        相关资源
        最近更新 更多