插入目标表中不存在的记录,并删除源数据集中不存在的记录使用MERGE

时间:2013-05-06 10:50:02

标签: sql sql-server sql-server-2008 merge

我有一个表格,其中包含如下数据(Table 1

id          valueId     Value
----------- ----------- --------------------------------------------------
1           1           Value 1
1           1           Value 2
1           1           Value 3
1           2           Value 1
1           2           Value 2
1           2           Value 3

我有另一个数据集如下(DataSet

id          valueId     Value
----------- ----------- -------
1           1           Value 1
1           1           Value 2
1           1           Value 4

现在我需要插入Table 1中不存在的记录(你可以看到记录

id          valueId     Value
----------- ----------- -------
1           1           Value 4

不在Table 1中,该记录应该插入)并且需要删除Table 1中不在DataSet中的记录

id          valueId     Value
----------- ----------- -------
1           1           Value 3

,但不影响其他记录(其他记录表示id=1 and valueId=2)的记录。

我使用了以下使用MERGE编写的T-SQL,它插入了缺失的记录,但删除了DataSet

以外的所有记录
DECLARE @tmp_value AS TABLE
    (
      id INT ,
      valueId INT ,
      [Value] NVARCHAR(50)
    ) ;
INSERT  @tmp_value
        ( [id], [valueId], [Value] )
VALUES  ( 1, 1, N'Value 1' ),
        ( 1, 1, N'Value 2' ),
        ( 1, 1, N'Value 3' ),
        ( 1, 2, N'Value 1' ),
        ( 1, 2, N'Value 2' ),
        ( 1, 2, N'Value 3' ) ;

--SELECT  *
--FROM    @tmp_value AS TV ;
WITH    cte
          AS ( SELECT   1 AS id , 1 AS valueId , 'Value 1' AS [Value]
               UNION
               SELECT   1 AS id , 1 AS valueId , 'Value 2' AS [Value]
               UNION
               SELECT   1 AS id , 1 AS valueId , 'Value 4' AS [Value]
             )
    MERGE @tmp_value AS TV
        USING cte
        ON [cte].[id] = [TV].[id]
            AND [cte].[valueId] = [TV].[valueId]
            AND [cte].[Value] = [TV].[Value]
        WHEN NOT MATCHED 
            THEN INSERT VALUES   ( id , [valueId] , [Value] )
        WHEN NOT MATCHED BY SOURCE 
            THEN DELETE ;

SELECT  *
FROM    @tmp_value

预期结果:

id          valueId     Value
----------- ----------- --------------------------------------------------
1           1           Value 1
1           1           Value 2
1           1           Value 4
1           2           Value 1
1           2           Value 2
1           2           Value 3

1 个答案:

答案 0 :(得分:1)

更新:

DECLARE @tmp_value AS TABLE
    (
      id INT ,
      valueId INT ,
      [Value] NVARCHAR(50)
    ) ;
INSERT  @tmp_value
        ( [id], [valueId], [Value] )
VALUES  ( 1, 1, N'Value 1' ),
        ( 1, 1, N'Value 2' ),
        ( 1, 1, N'Value 3' ),
        ( 1, 2, N'Value 1' ),
        ( 1, 2, N'Value 2' ),
        ( 1, 2, N'Value 3' ) ;

--SELECT  *
--FROM    @tmp_value AS TV ;
WITH    cte
          AS ( SELECT   1 AS id , 1 AS valueId , 'Value 1' AS [Value]
               UNION
               SELECT   1 AS id , 1 AS valueId , 'Value 2' AS [Value]
               UNION
               SELECT   1 AS id , 1 AS valueId , 'Value 4' AS [Value]
              )
    MERGE @tmp_value AS TV
        USING cte
        ON [cte].[id] = [TV].[id]
            AND [cte].[valueId] = [TV].[valueId]
            AND [cte].[Value] = [TV].[Value]
        WHEN NOT MATCHED 
            THEN INSERT VALUES   ( id , [valueId] , [Value] )
        ;


WITH    cte
          AS ( SELECT   1 AS id , 1 AS valueId , 'Value 1' AS [Value]
               UNION
               SELECT   1 AS id , 1 AS valueId , 'Value 2' AS [Value]
               UNION
               SELECT   1 AS id , 1 AS valueId , 'Value 4' AS [Value]
             )
    MERGE @tmp_value AS TV
        USING cte
        ON ([cte].[id] = [TV].[id]
            AND [cte].[valueId] = [TV].[valueId]
           AND [cte].[Value] = [TV].[Value])
            or not( [TV].[id] in (select distinct id from cte)
            and [TV].[valueId] in (select distinct valueid from cte))
        WHEN NOT MATCHED 
            THEN INSERT VALUES   ( id , [valueId] , [Value] )
        WHEN NOT MATCHED BY Source 
            THEN DELETE ;

SELECT  *
FROM    @tmp_value