T-SQL MERGE不变的目标

时间:2016-06-27 13:56:37

标签: sql-server merge

我将此格式用于MERGE子句:

DECLARE @Table (ColA int, ColB int, ID int)

INSERT @Table
SELECT changes.ColA,changes.ColB,Changes.Identity
FROM
(
  MERGE Target
  USING @SourceTable SOURCE
  ON Target.ID=Source.ID
  WHEN MATCHED AND target.ColA<>soruce.ColA or target.ColB<>source.ColB THEN 
    UPDATE SET
      Target.ColA=source.ColA,
      Target.ColB=source.ColB
  WHEN NOT MATCHED BY TARGET
    INSERT(ColA,ColB)
    VALUES(Source.ColA,Source.ColB)
  WHEN NOT MATCHED BY SOURCE THEN
    DELETE
  OUTPUT INSERTED.ColA,INSERTED.ColB,SOURCE.Identity
) AS changes(ColA,ColB,SOURCE.Identity)

然后我使用@Table作为其他JOINS的来源。如果TARGET表没有插入/更新,那么@Table为空,这导致整个查询的剩余部分出现问题,因为没有任何内容可以加入。

有没有办法捕获SOURCE行,即使它们未被TARGET方操纵?

我需要使用MERGE在INSERT / UPDATES上检索Identity列。

2 个答案:

答案 0 :(得分:0)

  1. 最好将IF @@ROWCOUNT > 0条件添加到脚本的其余部分,并在没有更新记录时跳过它。

  2. 如果无论Target表格中的更新内容,@SourceTable中的所有记录都需要进一步处理,最好只使用@SourceTable代替OUTPUT条款。 MERGE语句中的OUTPUT语句中的数据不是Target的{​​{1}}。

  3. 如果您想将@SourceTable中的记录过滤到OUTPUT子句,即使不需要更新Target表,您也可以对记录执行“虚拟更新”没有值会实际改变:

  4. DECLARE @Table (ColA int, ColB int, ID int)
    INSERT @Table
    SELECT changes.ColA,changes.ColB,Changes.Identity
    FROM (MERGE Target
    USING (SELECT * FROM @SourceTable ) SOURCE
    ON Target.ID=Source.ID
    WHEN MATCHED /* AND target.ColA<>soruce.ColA or target.ColB<>source.ColB             */
                 /* Remove condition and update even when no value would actually change */
    THEN UPDATE SET Target.ColA=source.ColA,Target.ColB=source.ColB
    WHEN NOT MATCHED BY TARGET INSERT(ColA,ColB) VALUES(Source.ColA,Source.ColB)
    WHEN NOT MATCHED BY SOURCE THEN DELETE
    OUTPUT INSERTED.ColA,INSERTED.ColB,SOURCE.Identity) AS changes(ColA,ColB,SOURCE.Identity)
    

答案 1 :(得分:0)

您可以通过捕获合并语句的OUTPUT来捕获未修改的源记录。您需要引入虚拟更新:

DECLARE @dummy INT = 0;
MERGE ...
  WHEN MATCHED THEN 
    UPDATE @dummy = @dummy
...
  OUTPUT INSERTED.ColA,INSERTED.ColB,SOURCE.Identity