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?

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.


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.