基于源表的不同删除 OUTPUT 行为

问题描述 投票:0回答:1

我想要实现的是一个组合的合并语句,它根据相关元数据更新/删除/移动数据,有点像下面的(MWS在最后):

merge #data as target
using #metadata as source
on (...)

when matched and source.state = 1
then update ...

when matched and source.state = 0
then delete

when matched and source.state = -1
then delete output deleted... into *somewhere else*
;

这会产生以下错误:

WHEN MATCHED 类型的操作在 MERGE 语句的 DELETE 子句中不得出现多次。

翻译

有人可以详细说明该错误吗?我怎样才能达到预期的行为?

这是一个 MWS:

CREATE TABLE #data 
(
    id int IDENTITY(1,1),
    description nvarchar(100) NOT NULL,
    metadata int NULL
)

CREATE TABLE #anotherTable 
(
    id int identity(1,1),
    description nvarchar(100) NOT NULL
)

INSERT INTO #data (description)
VALUES (N'data'),
       (N'more data'),
       (N'example'),
       (N'unknown')

CREATE TABLE #metadata 
(
    id int IDENTITY(1,1),
    description nvarchar(100) NOT NULL,
    metadata int NOT NULL,
    state int NOT NULL DEFAULT -1
)

INSERT INTO #metadata (description, metadata, state)
VALUES (N'data', 10, 1),
       (N'more data', 11, 0),
       (N'example', 12, -1)

MERGE #data AS target
USING #metadata AS source
      ON (target.description = source.description)

WHEN NOT MATCHED BY SOURCE THEN 
    DELETE

WHEN MATCHED AND source.state = 1 THEN
    UPDATE SET target.metadata = source.metadata

WHEN MATCHED AND source.state = 0 THEN
    DELETE

WHEN MATCHED AND source.state = -1 THEN
    DELETE OUTPUT deleted.description INTO #anotherTable (description);


SELECT * FROM #data
SELECT * FROM #anotherTable
SELECT * FROM #metadata

DROP TABLE #data, #metadata, #anotherTable

感谢您的帮助!

sql-server t-sql merge sql-delete
1个回答
0
投票

不,您不能直接执行此操作。

OUTPUT
子句与您令人困惑的格式相反,实际上适用于 整个
MERGE
,您应该将其与
MERGE
的其余部分分开格式化。

您也不允许有多个

WHEN MATCHED
子句,除非一个有
AND
过滤器而一个没有(因此不超过两个)。您需要删除
state
上的过滤器,或预先过滤源。

一种选择是将

MERGE...OUTPUT
放入派生表(不是 CTE,因为不受支持),然后使用
INSERT
WHERE
关闭。

INSERT #anotherTable (description)
SELECT description
FROM (
    MERGE #data AS target
    USING #metadata AS source
        ON (target.description = source.description)

    WHEN NOT MATCHED BY SOURCE THEN 
        DELETE

    WHEN MATCHED AND source.state = 1 THEN
        UPDATE SET target.metadata = source.metadata

    WHEN MATCHED THEN
        DELETE
  
    OUTPUT $action as action, deleted.*, source.state
) MergeOutput
WHERE action = 'DELETE'
  AND state = -1;

db<>小提琴

上述解决方案仅适用于简单的

WHERE
过滤器,不能使用连接等。

另一种选择是仅插入到表变量中,然后过滤并从那里重新插入。

© www.soinside.com 2019 - 2024. All rights reserved.