合并 - 多个匹配案例与更新

时间:2015-10-16 13:17:21

标签: sql sql-server merge

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

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;

4 个答案:

答案 0 :(得分:3)

简化版本(VerifiedDate总是更新,排名总是更新,因为如果等于它保持不变,唯一改变的字段是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;

答案 1 :(得分:2)

如果可以,请在CASE子语句中使用UPDATE表达式来模仿具有多个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中,这似乎是一个无操作。但是,我不确定它是否会被视为触发器的修改列。您始终可以测试以查看触发器中是否实际更改了行,以避免此方法可能导致的任何问题。

答案 2 :(得分:1)

您是否考虑过在进行更新时使用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;

答案 3 :(得分:1)

为什么不尝试使用CASE声明,

PSCustomObject