如何限制MERGE语句中OUTPUT子句的操作?

时间:2014-01-16 15:56:22

标签: sql sql-server merge

这是我的疑问:

MERGE INTO [payments_orders] o USING (
    SELECT 1 AS [order_id], 50.00 AS [amount] UNION ALL 
    SELECT 2 AS [order_id], 50.00 AS [amount]
) AS t ([order_id], [amount]) 
ON o.[payment_id] = 4 AND o.[order_id] = t.[order_id] 
WHEN MATCHED THEN UPDATE SET o.[amount] = t.[amount] 
WHEN NOT MATCHED THEN INSERT ([payment_id], [order_id], [amount]) 
VALUES (4, t.[order_id], t.[amount]) 
WHEN NOT MATCHED BY SOURCE AND o.[payment_id] = 4 THEN DELETE 
OUTPUT $ACTION AS [action], [deleted].[order_id];

我正在运行MERGE语句来插入或更新哪些订单记录与哪些付款记录以及分配方式相关联。

我想做什么最后添加WHERE $ACTION = 'DELETE';但这不起作用。显然你不能在WHERE子句中使用OUTPUT子句;这是“语法不正确。”

如何制作,以便此语句输出的唯一行是DELETE触发的行?

1 个答案:

答案 0 :(得分:4)

我遇到了同样的问题。到目前为止,我的解决方案(除非我想出另一个)是将伪值插入到插入行的临时表中,然后在合并语句完成后清理表。

CREATE TABLE #deleted_orders (order_id int)

MERGE INTO [payments_orders] o USING (
    SELECT 1 AS [order_id], 50.00 AS [amount] UNION ALL 
    SELECT 2 AS [order_id], 50.00 AS [amount]
) AS t ([order_id], [amount]) 
ON o.[payment_id] = 4 AND o.[order_id] = t.[order_id] 
WHEN MATCHED THEN UPDATE SET o.[amount] = t.[amount] 
WHEN NOT MATCHED THEN INSERT ([payment_id], [order_id], [amount]) 
VALUES (4, t.[order_id], t.[amount]) 
WHEN NOT MATCHED BY SOURCE AND o.[payment_id] = 4 THEN DELETE 
OUTPUT ISNULL([deleted].[order_id], -1) INTO #deleted_orders


DELETE FROM #deleted_orders WHERE order_id=-1

注意:您需要检查性能,并确定此更改是否会对您的用例造成可接受的性能影响。临时表可能会降低性能:请参阅“临时表”here for T-SQL

部分 编辑:我实际上最终做了一些不同的事情,但非常相似。它为您节省了最后的DELETE步骤

INSERT INTO #deleted_orders (order_id)
        SELECT mrg.order_id
        FROM ( MERGE INTO [payments_orders] o USING (
                    SELECT 1 AS [order_id], 50.00 AS [amount] UNION ALL 
                    SELECT 2 AS [order_id], 50.00 AS [amount]
                ) AS t ([order_id], [amount]) 
                ON o.[payment_id] = 4 AND o.[order_id] = t.[order_id] 
                WHEN MATCHED THEN UPDATE SET o.[amount] = t.[amount] 
                WHEN NOT MATCHED THEN INSERT ([payment_id], [order_id], [amount]) 
                VALUES (4, t.[order_id], t.[amount]) 
                WHEN NOT MATCHED BY SOURCE AND o.[payment_id] = 4 THEN DELETE 
                OUTPUT [deleted].[order_id] INTO #deleted_orders
OUTPUT $action as MergeAction, deleted.order_id) AS mrg 
WHERE mrg.MergeAction = 'DELETE'