Est-il possible de désactiver un déclencheur pour un lot de commandes, puis de l'activer lorsque le lot est terminé?
Je suis sûr que je pourrais laisser tomber le déclencheur et le rajouter, mais je me demandais s'il y avait une autre façon.
DISABLE TRIGGER { [ schema_name . ] trigger_name [ ,...n ] | ALL }
ON { object_name | DATABASE | ALL SERVER } [ ; ]
http://msdn.Microsoft.com/en-us/library/ms189748 (SQL.90) .aspx
suivi de l'inverse:
ENABLE TRIGGER { [ schema_name . ] trigger_name [ ,...n ] | ALL }
ON { object_name | DATABASE | ALL SERVER } [ ; ]
http://msdn.Microsoft.com/en-us/library/ms182706 (SQL.90) .aspx
Parfois, pour remplir une base de données vide à partir d'une source de données externe ou déboguer un problème dans la base de données, je dois désactiver TOUS les déclencheurs et contraintes. Pour ce faire, j'utilise le code suivant:
Pour désactiver toutes les contraintes et déclencheurs:
sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"
sp_msforeachtable "ALTER TABLE ? DISABLE TRIGGER all"
Pour activer toutes les contraintes et déclencheurs:
exec sp_msforeachtable @command1="print '?'", @command2="ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"
sp_msforeachtable @command1="print '?'", @command2="ALTER TABLE ? ENABLE TRIGGER all"
J'ai trouvé cette solution il y a quelque temps sur SQLServerCentral , mais j'avais besoin de modifier la partie des contraintes d'activation car celle d'origine ne fonctionnait pas complètement
Cependant, c'est presque toujours une mauvaise idée de le faire. Vous gâcherez l'intégrité de la base de données. Ne le faites pas sans considérer les ramifications et vérifier auprès du dbas si vous en avez.
Si vous suivez le code de Matt, n'oubliez pas de réactiver la gâchette. ET rappelez-vous que le déclencheur est désactivé pour tous ceux qui insèrent, mettent à jour ou suppriment de la table pendant qu'elle est désactivée, pas seulement pour votre processus, donc si cela doit être fait, faites-le pendant les heures où la base de données est la moins active (et de préférence en mode mono-utilisateur).
Si vous devez effectuer cette opération pour importer une grande quantité de données, considérez que l'insertion en bloc ne déclenche pas les déclencheurs. Mais ensuite, votre processus après l'insertion en bloc devra résoudre tous les problèmes d'intégrité des données que vous introduisez en ne déclenchant pas les déclencheurs.
Pour étendre la réponse de Matt, voici un exemple donné sur MSDN .
USE AdventureWorks;
GO
DISABLE TRIGGER Person.uAddress ON Person.Address;
GO
ENABLE Trigger Person.uAddress ON Person.Address;
GO
Une autre approche consiste à désactiver efficacement le déclencheur sans le désactiver réellement, en utilisant une variable d'état supplémentaire qui est incorporée au déclencheur.
create trigger [SomeSchema].[SomeTableIsEditableTrigger] ON [SomeSchema].[SomeTable]
for insert, update, delete
as
declare
@isTableTriggerEnabled bit;
exec usp_IsTableTriggerEnabled -- Have to use USP instead of UFN for access to #temp
@pTriggerProcedureIdOpt = @@procid,
@poIsTableTriggerEnabled = @isTableTriggerEnabled out;
if (@isTableTriggerEnabled = 0)
return;
-- Rest of existing trigger
go
Pour la variable d'état, on pourrait lire un certain type d'enregistrement de contrôle de verrouillage dans une table (mieux si limité au contexte de la session en cours), utiliser CONTEXT_INFO (), ou utiliser la présence d'un nom de table temporaire particulier (qui est déjà la portée de la session limité):
create proc [usp_IsTableTriggerEnabled]
@pTriggerProcedureIdOpt bigint = null, -- Either provide this
@pTableNameOpt varchar(300) = null, -- or this
@poIsTableTriggerEnabled bit = null out
begin
set @poIsTableTriggerEnabled = 1; -- default return value (ensure not null)
-- Allow a particular session to disable all triggers (since local
-- temp tables are session scope limited).
--
if (object_id('tempdb..#Common_DisableTableTriggers') is not null)
begin
set @poIsTableTriggerEnabled = 0;
return;
end
-- Resolve table name if given trigger procedure id instead of table name.
-- Google: "How to get the table name in the trigger definition"
--
set @pTableNameOpt = coalesce(
@pTableNameOpt,
(select object_schema_name(parent_id) + '.' + object_name(parent_id) as tablename
from sys.triggers
where object_id = @pTriggerProcedureIdOpt)
);
-- Else decide based on logic involving @pTableNameOpt and possibly current session
end
Puis pour désactiver tous les déclencheurs:
select 1 as A into #Common_DisableTableTriggers;
-- do work
drop table #Common_DisableTableTriggers; -- or close connection
Un inconvénient potentiellement majeur est que le déclencheur est définitivement ralenti en fonction de la complexité d'accès à la variable d'état.
Edit: Ajout d'une référence à ce incroyablement similaire 2008 post by Samuel Vanga .
ALTER TABLE table_name DISABLE TRIGGER TRIGGER_NAME
-- Here your SQL query
ALTER TABLE table_name ENABLE TRIGGER TRIGGER_NAME
Ce n'est pas la meilleure réponse pour la programmation par lots, mais pour d'autres qui trouvent cette question à la recherche d'un moyen rapide et facile de désactiver temporairement un déclencheur, cela peut être accompli dans SQL Server Management Studio.
Suivez le même processus pour réactiver.