MERGE 尝试多次更新或删除同一行

MERGE attempted to UPDATE or DELETE the same row more than once

我正在尝试使用从以下网站获得的合并语句加载标准 Kimball SCD2 维度: http://www.kimballgroup.com/2008/11/design-tip-107-using-the-sql-merge-statement-for-slowly-changing-dimension-processing/

除了处理新实体外,此合并语句是相同的。这将作为数据流中的直接插入处理。此问题仅涉及同一业务密钥的多个版本。

当我执行合并语句时SQL returns 错误:

Msg 8672, Level 16, State 1, Line 3
The MERGE statement attempted to UPDATE or DELETE the same row more than once. This happens when a target row matches more than one source row.
A MERGE statement cannot UPDATE/DELETE the same row of the target table multiple times. Refine the ON clause to ensure a target row matches at most one source row, or use the GROUP BY clause to group the source rows.

我正在使用 SQL Server 2012:

源数据集

目标数据集

这是我所期望的:

您可以在下面找到重现问题的脚本:

CREATE TABLE SANDBOX.EHN.SOURCE_SCD2 (
  BUSINESS_KEY  BIGINT
 ,DESCRIPTION_A VARCHAR(2)
 ,M_CRC         BIGINT
 ,StartDATE     DATE
 ,EndDATE       DATE )



CREATE TABLE SANDBOX.EHN.TARGET_SCD2 (
  BUSINESS_KEY  BIGINT
 ,DESCRIPTION_A VARCHAR(2)
 ,M_CRC         BIGINT
 ,StartDATE     DATE
 ,EndDATE       DATE )



 select *
 from SANDBOX.EHN.TARGET_SCD2

 truncate table SANDBOX.EHN.TARGET_SCD2

 INSERT INTO SANDBOX.EHN.SOURCE_SCD2 VALUES (1, 'B',  1,   '2015-05-16', '2015-06-01')
 INSERT INTO SANDBOX.EHN.SOURCE_SCD2 VALUES (1, 'C',  2,   '2015-06-01', '2015-06-11')
 INSERT INTO SANDBOX.EHN.SOURCE_SCD2 VALUES (1, 'D',  3,   '2015-06-11', '9999-12-31')

 INSERT INTO SANDBOX.EHN.TARGET_SCD2 VALUES (1,  'A', 0,    '2015-01-16', '9999-12-31')



INSERT INTO SANDBOX.EHN.TARGET_SCD2 
     SELECT BUSINESS_KEY
          ,DESCRIPTION_A
         ,M_CRC
         ,StartDATE
         ,EndDATE
FROM (
MERGE SANDBOX.EHN.TARGET_SCD2 D
USING SANDBOX.EHN.SOURCE_SCD2 UPD
ON(D.BUSINESS_KEY = UPD.BUSINESS_KEY )
    WHEN MATCHED AND D.EndDATE = '9999-12-31' 
    THEN UPDATE SET  D.EndDATE =  UPD.EndDATE
OUTPUT $Action Action_Out, UPD.BUSINESS_KEY
                         , UPD.DESCRIPTION_A
                    , UPD.M_CRC
                    , UPD.StartDATE
                    , UPD.EndDATE
)AS MERGE_OUT
WHERE MERGE_OUT.Action_Out = 'UPDATE'

你能帮我解决这个问题吗?

最后一次更新只用;

INSERT INTO SANDBOX.EHN.TARGET_SCD2 
     SELECT BUSINESS_KEY
          ,DESCRIPTION_A
         ,M_CRC
         ,StartDATE
         ,EndDATE
FROM (
MERGE SANDBOX.EHN.TARGET_SCD2 D
USING SANDBOX.EHN.SOURCE_SCD2 UPD
ON(D.BUSINESS_KEY = UPD.BUSINESS_KEY AND UPD.EndDATE = '9999-12-31')
    WHEN MATCHED AND D.EndDATE = '9999-12-31' 
    THEN UPDATE SET  D.EndDATE =  UPD.StartDATE
OUTPUT $Action Action_Out, UPD.BUSINESS_KEY
                         , UPD.DESCRIPTION_A
                         , UPD.M_CRC
                         , UPD.StartDATE
                         , UPD.EndDATE
)AS MERGE_OUT
WHERE MERGE_OUT.Action_Out = 'UPDATE'

如果您想要目标中的所有 SRC 行 table 那么我同意 Nick.McDermaid

对于所有行使用;

UPDATE TRG
  SET TRG.EndDate = SRC.StartDATE
FROM SANDBOX.EHN.TARGET_SCD2 TRG
JOIN  ( select SRC.BUSINESS_KEY, min(src.StartDATE)StartDATE
        from SANDBOX.EHN.SOURCE_SCD2 SRC
          group by SRC.BUSINESS_KEY
       )SRC
on  ( TRG.BUSINESS_KEY = SRC.BUSINESS_KEY
       AND SRC.StartDate > TRG.StartDate ) 
where 1 = 1


INSERT SANDBOX.EHN.TARGET_SCD2
SELECT * FROM SANDBOX.EHN.SOURCE_SCD2