MERGE mit OUTPUT scheint nicht das Richtige zu tun

8

Ich füge einer Tabelle einen Fremdschlüssel hinzu, entferne alle Zeilen, die gegen die FK verstoßen, und kopiere sie in eine ModifiedTable_invalid-Tabelle. Als Teil des Skripts habe ich den folgenden MERGE-Befehl:

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;

Dieser Befehl scheint jedoch JEDE Zeile aus ModifiedTable in ModifiedTable_invalid einzufügen, nicht nur diejenigen, die mit dem Befehl MERGE gelöscht wurden. Was ist los und wie kann ich nur die gelöschten Zeilen in ModifiedTable_invalid einfügen?

thecoop
quelle

Antworten:

11

Wenn Sie eine Zeile aktualisieren, wird sie sowohl in der insertedPseudotabelle (Wert nach dem Update) als auch im Wert deleted(Wert vor dem Update) angezeigt. Wenn dies seltsam erscheint, denken Sie daran, dass ein Update logischerweise eine Löschung gefolgt von einer Einfügung ist (obwohl das Update möglicherweise nicht physisch auf diese Weise durchgeführt wird).

Bei Verwendung mit MERGEkann die OUTPUTKlausel eine zusätzliche Spalte mit dem Namen enthalten $action. Das Hinzufügen dieser Spalte auf Ihre Anfrage wird zeigen , welche Maßnahmen ergriffen wurden ( 'INSERT', 'UPDATE'oder 'DELETE') für jede Zeile.

Zum Beispiel:

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

Aktualisierte Zeilen haben $action= 'UPDATE'.

Siehe auch Adam Machanics Beitrag über die Verwendung von OUTPUT mit der MERGE-Anweisung für einige andere schöne Beispiele.

Kevin Feasel
quelle
Dieses Verhalten macht für mich keinen Sinn. Warum werden nicht gelöschte Zeilen angezeigt DELETED.*?
Thecoop
3
@thecoop - Ermöglicht den Zugriff auf die Werte "vor" und "nach" für ein Update. Konzeptionell könnten Sie ein Update als Löschen gefolgt von einer Einfügung betrachten, obwohl dies häufig nicht der Fall ist.
Martin Smith