【问题标题】:Using MERGE to delete data, or insert使用 MERGE 删除数据,或插入
【发布时间】:2016-08-31 22:46:11
【问题描述】:

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

Personkey int
ComponentKey varchar

这些数据需要入表,表中存在但datatable中没有的数据要删除。

示例表数据

PersonKey     ComponentKey
123           A1
456           B9

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

数据表数据示例

PersonKey    ComponentKey
123          A1
786          Z6

结果是456/B9行应该被删除,123/A1行什么都没有发生,786/Z6行应该被插入。

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

我知道 WHEN NOT MATCHED 我应该进行插入,但删除部分从哪里进入?

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 仍在表格中。

【问题讨论】:

    标签: sql-server datatable sql-merge


    【解决方案1】:

    默认的“WHEN NOT MATCHED”假定您真正的意思是“WHEN NOT MATCHED BY TARGET”。您可以使用简单的命令“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;
    

    【讨论】:

    • 我更新了我的问题,因为这种方法不起作用。
    • 您的执行可能没有奏效,但方法有效。我编辑了我的答案,以包括数据结构和问题的编码解决方案。同样,请记住,您必须小心定义您的目标到底是什么。
    • 值得一提的是,MERGE不能匹配值为NULL的列,所以如果src.ComponentKey和tgt.ComponentKey都是NULL,虽然这实际上是匹配,但SQL不会把它当作一个。避免这种情况的方法是确保在 USING 语句中的每一列都为 ISNULL。
    猜你喜欢
    • 2015-01-24
    • 1970-01-01
    • 2016-08-16
    • 1970-01-01
    • 2016-03-28
    • 1970-01-01
    • 1970-01-01
    • 2019-03-06
    • 1970-01-01
    相关资源
    最近更新 更多