web-dev-qa-db-fra.com

SQL Server 2005: T-SQL pour désactiver temporairement un déclencheur

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.

50
Austin Salonen
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

62
Matt Rogish

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

33
kristof

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.

15
HLGEM

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
11
Daniel Imms

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 .

5
crokusek
ALTER TABLE table_name DISABLE TRIGGER TRIGGER_NAME
-- Here your SQL query
ALTER TABLE table_name ENABLE TRIGGER TRIGGER_NAME
4
ABHISHEK GANGULY

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.

  1. développer le dossier des déclencheurs sur la table
  2. faites un clic droit sur la gâchette
  3. désactiver

enter image description here

Suivez le même processus pour réactiver.

2
Jeff Puckett