Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Instruction SQL Server 2008 MERGE - comment désactiver le déclencheur INSTEAD OF INSERT pour autoriser la MERGE

L'optimiseur de requête effectue une analyse statique de votre lot T-SQL et dès qu'il voit l'instruction MERGE, il valide les exigences. Il ne prendra PAS en compte les instructions DDL qui affectent les déclencheurs avant l'instruction MERGE.

Vous pouvez contourner ce problème en utilisant GO pour diviser les instructions en lots séparés, mais s'il s'agit d'un seul SP (pas d'instructions GO), vous avez deux choix

  • mettre le MERGE dans un SP de support que le principal appelle ; ou
  • utiliser SQL dynamique

SQL dynamique

Créons une table avec un déclencheur

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

Essayez ensuite de FUSIONNER sur la table

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
;

Pas bon..

Nous utilisons donc du SQL dynamique

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
;

Procédure d'assistance

Créons une procédure qui effectuera la MERGE (une procédure de production aurait probablement une variable de table, utiliserait une table #temp ou prendrait certains paramètres)

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

N'y allez pas...

Même pour le créer, vous devez désactiver les déclencheurs - désactivez donc le déclencheur et créez à nouveau le proc - cela fonctionnera cette fois-ci.

Enfin, vous pouvez exécuter ce batch qui fonctionne

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