使用MERGE删除数据或插入

时间:2016-08-31 22:46:11

标签: sql-server datatable sql-merge

从UI中我将数据表传递给存储过程。该参数的类型是用户定义的表字段,具有以下结构

Personkey int
ComponentKey varchar

此数据需要进入表格,并且应删除表格中但不在数据表中的数据。

示例表数据

PersonKey     ComponentKey
123           A1
456           B9

我的数据表有2行,一行匹配,一行新行

示例数据表数据

PersonKey    ComponentKey
123          A1
786          Z6

结果是应该删除456 / B9行,123 / A1行不应该发生任何事情,并且应该插入786 / Z6行。

我相信我可以使用MERGE语句,但我不确定如何形成它。

我明白,如果不匹配,我应该插入,但删除部分会在哪里进入?

MERGE Components
USING @passedInData
ON PersonKey = DatatblPersonKey AND ComponentKey = DatatblComponentKey

WHEN MATCHED THEN
-- DO nothing...

WHEN NOT MATCHED
INSERT (PersonKey, ComponentKey) VALUES (DatatblPersonKey, DatatblComponentey);

编辑:为了清楚起见,数据表可以包含许多行用于同一个人键,但组件键可能不同。

示例数据表数据

PersonKey    ComponentKey
123          Z6
123          C5

示例表数据

PersonKey     ComponentKey
123           A1
456           B9

插入上述数据表后的结果应为

PersonKey    ComponentKey
123          Z6
123          C5
456          B9

请注意,123 / A1已被删除,456 / B9仍在表格中。

1 个答案:

答案 0 :(得分:0)

默认的“WHEN NOT MATCHED”假设你真正的意思是“当目标没有匹配时”。您可以使用简单的命令“DELETE”为“WHEN NOT MATCHED BY SOURCE”做另一个声明。

执行此操作时要小心,因为它将根据您指定的比较删除目标中与源不匹配的所有记录。如果有必要为该操作执行目标的子集,则可以使用带有该过滤器的cte,然后将该cte作为目标进行合并。

编辑...演示如何连接我所说的内容:

DECLARE @databaseTable TABLE (PersonKey INT, ComponentKey VARCHAR(10));
INSERT INTO @databaseTable
VALUES
    (123, 'A1'),
    (456, 'B9');
DECLARE @appDataset TABLE (PersonKey INT, ComponentKey VARCHAR(10));
INSERT INTO @appDataset
VALUES
    (123, 'Z6'),
    (123, 'C5');

WITH cteTarget AS
    (
    SELECT  dt.PersonKey
        ,   dt.ComponentKey
    FROM @databaseTable AS dt
    JOIN (SELECT DISTINCT PersonKey FROM @appDataset) AS pk
        ON pk.PersonKey = dt.PersonKey
    )
MERGE cteTarget AS tgt
USING @appDataset AS src
    ON src.PersonKey = tgt.PersonKey
    AND src.ComponentKey = tgt.ComponentKey
WHEN NOT MATCHED BY SOURCE THEN
    DELETE
WHEN NOT MATCHED BY TARGET THEN
    INSERT
        (PersonKey
        ,ComponentKey)
    VALUES
        (src.PersonKey
        ,src.ComponentKey);

SELECT * FROM @databaseTable;