Sql Server 2008 MERGE похож на операцию, но действует на разные таблицы - PullRequest
1 голос
/ 16 марта 2012

Я использовал операцию MERGE в SQL Server 2008, но теперь столкнулся с похожим сценарием, где мне нужно такое же поведение "обнаружения" (WHEN MATCHED, WHEN NOT MATCHED BY SOURCE, WHEN NOT MATCHED BY TARGET), но я хочу, чтобы результирующие операции выполнялись в разных таблицах, а не в источнике или цели.

Другими словами, у меня есть два набора результатов, beforeTable и afterTable, и я хочу сделатьчто-то вроде:

MERGE afterTable AS dest
USING beforeTable AS source 
ON (dest.ID = source.ID)
WHEN MATCHED THEN 
    --INSERT tblModifiedItems (ID) VALUES (ID)
WHEN NOT MATCHED BY TARGET THEN
    --INSERT tblRemovedItems (ID) VALUES (ID)
WHEN NOT MATCHED BY SOURCE THEN
    --INSERT tblAddedItems (ID) VALUES (ID)

В настоящее время я делаю это с тремя отдельными (хотя и очень простыми) запросами по двум таблицам, но подход MERGE позволил бы сделать это как одну операцию.Я просто не могу понять, можно ли использовать его для таргетинга на другие таблицы, отличные от двух сравниваемых.

Возможно ли это, и если да, то как?

[EDIT]

Причина, по которой я хочу это сделать, не связана с проблемами атомарности ВСТАВКИ в добавление / удаление / изменение (все это уже в транзакции).Это потому, что я хочу иметь возможность генерировать три набора данных в одном запросе или, по крайней мере, в одном операторе , что также делает цель очень ясной.

1 Ответ

2 голосов
/ 16 марта 2012

короткий ответ будет: нет, вы не можете.MERGE - это операция между исходной таблицей и таблицей назначения и все.Но я предлагаю обходной путь (всегда есть один).Вам придется написать еще немного кода, но это поможет.

Сделайте это:

DECLARE @AuxTable table(    
    id int,
    OLD_name varchar(50),
    new_name varchar(50)
    )

merge table2 as dest
using table1 as src
on (dest.id=src.id)
when not matched by target then
  insert (id, name) values (src.id, src.name)
when matched then
  UPDATE SET dest.NAME=src.name
when not matched by SOURCE then
   DELETE

  output inserted.id, DELETED.name, INSERTED.NAME
  into @AuxTable
  ;

  select * from @AuxTable

см. "output into @AuxTable"?Это вставит все измененные значения при слиянии в временную таблицу.Что вам нужно сделать, это запустить эту таблицу и создать строку для выполнения SQL в другой таблице.

Используйте эту логику:

  • WHEN OLD_NAME = NULL ->INSERT
  • КОГДА OLD_NAME! = NEW_NAME -> ОБНОВЛЕНИЕ
  • КОГДА NEW_NAME = NULL -> УДАЛИТЬ
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...