MERGE com OUTPUT não parece estar fazendo a coisa certa

8

Estou adicionando uma chave estrangeira a uma tabela e removendo as linhas que violam o FK, copiando-as para uma tabela ModifiedTable_invalid. Como parte do script, tenho o seguinte comando 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;

No entanto, esse comando parece estar inserindo TODAS as linhas de ModifiedTable em ModifiedTable_invalid, não apenas as excluídas pelo comando MERGE. O que está acontecendo e como faço para colocar apenas as linhas excluídas em ModifiedTable_invalid?

thecoop
fonte

Respostas:

11

Quando você atualiza uma linha, ela aparece nas pseudo-tabelas ( insertedvalor pós-atualização) e deleted(valor pré-atualização). Se isso parecer estranho, considere que uma atualização é logicamente uma exclusão seguida por uma inserção (embora a atualização possa não ser fisicamente executada dessa maneira).

Quando usada com MERGE, a OUTPUTcláusula pode incluir uma coluna extra denominada $action. Adicionando esta coluna para sua consulta vai mostrar que a ação foi tomada ( 'INSERT', 'UPDATE'ou 'DELETE') para cada linha.

Por exemplo:

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';

Linhas atualizadas terá $action= 'UPDATE'.

Veja também o post de Adam Machanic sobre o uso de OUTPUT com a instrução MERGE para outros exemplos interessantes.

Kevin Feasel
fonte
Esse comportamento não faz sentido para mim. Por que as linhas que não foram excluídas apareceriam DELETED.*?
Thecoop 5/11/12
3
@ thecoop - Permite acessar os valores "antes" e "depois" para uma atualização. Conceitualmente, você pode considerar uma atualização como uma exclusão seguida por uma inserção, mesmo que isso não aconteça com frequência.
Martin Smith