TSQL - 带复合键的MERGE语句

ado*_*ntz 9 t-sql sql-server sql-server-2012

我有表OrderLines(OrderID int,LineIndex int,)和相同结构的表值参数定义一个订单的新订单行.

所以,如果我有以下OrderLines

1000   1   bread
1000   2   milk
1001   1   oil
1001   2   yogurt
1002   1   beef
1002   2   pork
Run Code Online (Sandbox Code Playgroud)

和以下TVP

1001   1   yogurt
Run Code Online (Sandbox Code Playgroud)

我想获得以下OrderLines

1000   1   bread
1000   2   milk
1001   1   yogurt
1002   1   beef
1002   2   pork
Run Code Online (Sandbox Code Playgroud)

即只触摸一个订单的行.

所以我写了这样的查询

MERGE
    [OrderLines] AS [Target]
USING
(
    SELECT
        [OrderID], [LineIndex], [Data]
    FROM
        @OrderLines
)
AS [Source] ([OrderID], [LineIndex], [Data])
ON ([Target].[OrderID] = [Source].[OrderID]) AND ([Target].[LineIndex] = [Source].[LineIndex])
WHEN MATCHED THEN
    UPDATE
    SET
        [Target].[Data] = [Source].[Data]
WHEN NOT MATCHED BY TARGET THEN
    INSERT
        ([OrderID], [LineIndex], [Data])
    VALUES
        ([Source].[OrderID], [Source].[LineIndex], [Source].[Data])
WHEN NOT MATCHED BY SOURCE THEN
    DELETE;
Run Code Online (Sandbox Code Playgroud)

并删除其他订单的所有其他(未提及)OrderLines.

我试过了

WHEN NOT MATCHED BY SOURCE AND ([Target].[OrderID] = [Source].[OrderID]) THEN
Run Code Online (Sandbox Code Playgroud)

但得到了句法错误.

我应该如何重写我的查询?

And*_*y M 12

只需使用相关的子集OrderLines作为目标:

WITH AffectedOrderLines AS (
    SELECT *
    FROM OrderLines
    WHERE OrderID IN (SELECT OrderID FROM @OrderLines)
)
MERGE
    AffectedOrderLines AS [Target]
USING
(
    SELECT
        [OrderID], [LineIndex], [Data]
    FROM
        @OrderLines
)
AS [Source] ([OrderID], [LineIndex], [Data])
ON ([Target].[OrderID] = [Source].[OrderID]) AND ([Target].[LineIndex] = [Source].[LineIndex])
WHEN MATCHED THEN
    UPDATE
    SET
        [Target].[Data] = [Source].[Data]
WHEN NOT MATCHED BY TARGET THEN
    INSERT
        ([OrderID], [LineIndex], [Data])
    VALUES
        ([Source].[OrderID], [Source].[LineIndex], [Source].[Data])
WHEN NOT MATCHED BY SOURCE THEN
    DELETE;
Run Code Online (Sandbox Code Playgroud)

而且这里有一个SQL小提琴测试.