TSQL 合并:基于元数据的不同删除行为

问题描述 投票: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
的其余部分分开格式化。

一种选择是将

MERGE...OUTPUT
放入 CTE,然后用
INSERT
WHERE
移开。

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

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

    when matched and source.state in (0, -1)
    then delete

    output $action, deleted.*
)
insert somewhereElse (ColumnsHere)
select ColumnsHere
from mergeOuput
where $action = 'DELETE' AND state = -1;

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

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

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

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