MERGE с OUTPUT, похоже, не правильно делает

8

Я добавляю внешний ключ в таблицу и удаляю все строки, которые нарушают 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;

Однако эта команда, похоже, вставляет КАЖДУЮ строку из ModifiedTable в ModifiedTable_invalid, а не только те, которые были удалены командой MERGE. Что происходит, и как мне заставить его поместить только удаленные строки в ModifiedTable_invalid?

thecoop
источник

Ответы:

11

При обновлении строки она будет отображаться в псевдотаблицах inserted(значение после обновления) и deleted(значение до обновления). Если это кажется странным, считайте, что обновление логически является удалением, за которым следует вставка (хотя обновление может выполняться физически не таким образом).

При использовании с 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';

Обновленные строки будут иметь $action= 'UPDATE'.

Также см. Пост Адама Маханича об использовании OUTPUT с оператором MERGE для некоторых других хороших примеров.

Кевин Физель
источник
Такое поведение не имеет смысла для меня. Почему строки, которые не были удалены, появляются в DELETED.*?
Thecoop
3
@thecoop - позволяет получить доступ к значениям «до» и «после» для обновления. Концептуально вы можете рассматривать обновление как удаление, за которым следует вставка, даже если это часто не так, как это происходит на самом деле.
Мартин Смит