与 OUTPUT 合并似乎没有做正确的事情

the*_*oop 8 sql-server-2008 sql-server merge

我正在向表中添加外键,并删除任何违反 FK 的行,将它们复制到 ModifiedTable_invalid 表中。作为脚本的一部分,我有以下 MERGE 命令:

MERGE ModifiedTable t1
USING TargetTable tt
ON t1.JoinColumn = tt.JoinColumn
WHEN MATCHED THEN
    UPDATE SET t1.FkColumn = tt.FkSource
WHEN NOT MATCHED BY SOURCE THEN DELETE
OUTPUT DELETED.* INTO ModifiedTable_invalid;
Run Code Online (Sandbox Code Playgroud)

但是,此命令似乎将 ModifiedTable 中的每一行插入到 ModifiedTable_invalid 中,而不仅仅是那些被 MERGE 命令删除的行。这是怎么回事,我如何让它只将已删除的行放在 ModifiedTable_invalid 中?

Kev*_*sel 11

当您更新一行时,它将同时出现在inserted(更新后值)和deleted(更新前值)伪表中。如果这看起来很奇怪,请考虑更新在逻辑上是删除后插入(尽管更新可能不会在物理上以这种方式执行)。

使用 with 时MERGE,该OUTPUT子句可以包含一个名为的额外列$action。添加该列,您的查询将显示被带到哪个动作('INSERT''UPDATE',或'DELETE')的每一行。

例如:

insert into ModifiedTable_invalid(Id /* And other columns */)
select
    Id
    /* And other columns */
from
(
    merge ModifiedTable t1
    using TargetTable t2 on t1.JoinColumn = t2.JoinColumn
    when matched then update set t1.FkColumn = t2.FkSource
    when not matched by source then delete
    output 
        $action as DMLAction,
        deleted.Id as Id /* And other columns... */
) outputs
where
    DMLAction = 'DELETE';
Run Code Online (Sandbox Code Playgroud)

更新的行将具有$action= 'UPDATE'

另请参阅Adam Machanic 关于将 OUTPUT 与 MERGE 语句一起使用的帖子,了解其他一些不错的示例。

  • @thecoop - 它允许您访问更新的“之前”和“之后”值。从概念上讲,您可能认为更新是删除后插入,即使这通常不是它实际发生的方式。 (3认同)