SQL Server:可以合并插入或更新源表吗?

时间:2014-11-14 14:20:34

标签: sql-server tsql

我正在使用SQL Server 2008并在两个表之间同步数据,如下所示:

    MERGE into Stock as Target
    using StockHistory as Source on Target.SrNo = Source.SrNo
    When Matched then
            # Update record to target table
    When Not Matched then
            # Insert record to target table
    When Not Matched By Source Then
            # Update Source Table - Current Record

问题1:我想有条件地插入记录"当不匹配时"火。 例如如果源表列refSrNo_StockCompany为null,则它不应插入目标。

问题2:万一目标表"股票"与来源不匹配"当不按来源匹配时"火,它应该更新源表 - > IsSoldOut ='是'。

请建议我如何实现这一目标。

由于

1 个答案:

答案 0 :(得分:5)

对于问题1:只需在AND子句中添加WHEN NOT MATCHED条件:

WHEN NOT MATCHED AND Source.[refSrNo_StockCompany] IS NOT NULL THEN
    # Insert record to target table

对于问题2:不能直接完成,因为只能修改TARGET表。但是,它可以在第二步中间接完成。诀窍是使用OUTPUT子句将更新的记录捕获到临时表中(而不是使用$action来区分INSERT和UPDATE,我们从deleted抓取根据定义,在INSERT操作中永远不会填充的表)。然后,在源表上执行UPDATE时,将该列表用作JOIN,以过滤掉该列表中的任何内容。临时表中的记录是匹配后不需要更新的记录。源表中不在该临时表中的任何记录表示在WHEN NOT MATCHED BY SOURCE条件下匹配的所有记录。当然,通过WHEN NOT MATCHED子句插入的记录都会在临时表中显示为NULL个记录(因为deleted表中没有任何INSERT操作),并且这些可以很容易地从UPDATE过滤掉。

-- do this before the MERGE
CREATE TABLE #UpdatedRecords (SrNo INT);

BEGIN TRY
  BEGIN TRAN;

  MERGE ...
  -- add this to the end of the MERGE query
  OUTPUT DELETED.SrNo
  INTO  #UpdatedRecords (SrNo);

  -- optionally do this after the MERGE
  DELETE upd
  FROM   #UpdatedRecords upd
  WHERE  upd.SrNo IS NULL;

  -- do this after the MERGE
  UPDATE sh
  SET    sh.IsSoldOut = 'Yes'
  FROM StockHistory sh
  WHERE NOT EXISTS (
          SELECT upd.SrNo
          FROM   #UpdatedRecords upd
          WHERE  upd.SrNo = sh.SrNo
       );

  COMMIT TRAN;

END TRY
BEGIN CATCH
  ROLLBACK TRAN;
  DECLARE @Error NVARCHAR(4000) = ERROR_MESSAGE();
  RAISERROR(@Error, 16, 1);
END CATCH;

如果你想确保这两个语句的一致性是单个操作,就像使用MERGE时那样(有效),然后将MERGEUPDATE包装在一个{ {1}}和BEGIN TRAN