MERGE with OUTPUT no parece estar haciendo lo correcto

8

Estoy agregando una clave foránea a una tabla, y eliminando cualquier fila que viole el FK, copiándola en una tabla ModifiedTable_invalid. Como parte del script, tengo el siguiente 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;

Sin embargo, este comando parece estar insertando CADA fila de ModifiedTable en ModifiedTable_invalid, no solo las eliminadas por el comando MERGE. ¿Qué está pasando y cómo consigo que solo coloque las filas eliminadas en ModifiedTable_invalid?

thecoop
fuente

Respuestas:

11

Cuando actualice una fila, aparecerá en las pseudo-tablas ( insertedvalor posterior a la actualización) y deleted(valor previo a la actualización). Si esto parece extraño, considere que una actualización es lógicamente una eliminación seguida de una inserción (aunque la actualización puede no realizarse físicamente de esa manera).

Cuando se usa con MERGE, la OUTPUTcláusula puede incluir una columna adicional llamada $action. La adición de esta columna a la consulta mostrará qué medidas se adoptan ( 'INSERT', 'UPDATE'o 'DELETE') para cada fila.

Por ejemplo:

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

Las filas actualizadas tendrán $action= 'UPDATE'.

También vea la publicación de Adam Machanic sobre el uso de OUTPUT con la declaración MERGE para algunos otros buenos ejemplos.

Kevin Feasel
fuente
Este comportamiento no tiene sentido para mí. ¿Por qué aparecerían las filas que no se han eliminado DELETED.*?
thecoop
3
@thecoop: le permite acceder a los valores "antes" y "después" para una actualización. Conceptualmente, puede considerar que una actualización es una eliminación seguida de una inserción, aunque a menudo no es así.
Martin Smith