sql >> Base de Datos >  >> RDS >> Sqlserver

Declaración MERGE de SQL Server 2008:cómo deshabilitar el disparador INSTEAD OF INSERT para permitir la MERGE

El Optimizador de consultas realiza un análisis estático de su lote de T-SQL y, tan pronto como ve la instrucción MERGE, valida los requisitos. NO tendrá en cuenta ninguna declaración DDL que afecte los activadores antes de la declaración MERGE.

Puede solucionar esto usando GO para dividir las declaraciones en lotes separados, pero si está en un solo SP (sin declaraciones GO), tiene dos opciones

  • poner el MERGE en un SP de soporte al que llama el principal; o
  • usar SQL dinámico

SQL dinámico

Vamos a crear una tabla con un disparador

create table tg1(i int)
;
create trigger tg1_tg on tg1 instead of insert as 
select 1
GO

Luego intenta FUSIONAR en la mesa

alter table tg1 disable trigger tg1_tg
;
merge tg1 as target
using (select 1 union all select 3) as source (X) on target.i = source.x
when matched then
    delete
when not matched by target then
    insert (i) values (x)
output $action, inserted.*, deleted.*
;
alter table tg1 enable trigger tg1_tg
;

No es bueno..

Así que usamos SQL dinámico

alter table tg1 disable trigger tg1_tg
;
exec ('
merge tg1 as target
using (select 1 union all select 3) as source (X) on target.i = source.x
when matched then
    delete
when not matched by target then
    insert (i) values (x)
output $action, inserted.*, deleted.*
;')
alter table tg1 enable trigger tg1_tg
;

Procedimiento de soporte

Vamos a crear un procedimiento que realice la FUSIÓN (un proceso de producción probablemente tendría una variable de tabla, usaría una tabla #temp o tomaría algunos parámetros)

create proc tg1_MERGE as
merge tg1 as target
using (select 1 union all select 3) as source (X) on target.i = source.x
when matched then
    delete
when not matched by target then
    insert (i) values (x)
output $action, inserted.*, deleted.*
;
GO

No vayas...

Incluso para crearlo, debe deshabilitar los disparadores, así que deshabilite el disparador y cree el proceso nuevamente, funcionará esta vez.

Finalmente, puede ejecutar este lote que funciona

alter table tg1 disable trigger tg1_tg
;
exec tg1_MERGE
;
alter table tg1 enable trigger tg1_tg
;