SQL Server 2005: T-SQL para deshabilitar temporalmente un desencadenador


44

¿Es posible desactivar un desencadenante para un lote de comandos y luego habilitarlo cuando el lote está listo?

Estoy seguro de que podría soltar el gatillo y volver a agregarlo, pero me preguntaba si había otra manera.

57
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

seguido por el inverso:

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

  0

Gracias! Creo que mi ingenio de SQL Server 2005 se muestra muy bien en este sitio. 23 sep. 082008-09-23 20:15:46

  0

Sin preocupaciones; ser un DBA durante mucho tiempo y estas cosas se vuelven automáticas :) 23 sep. 082008-09-23 20:16:41

  0

es decir, si usa la opción para modificar un disparador y el script contiene 'ALTER TRIGGER [dbo]. [trgWhatever] ON [dbo]. [tblWhatever]' entonces usted necesita 'DISABLE TRIGGER [dbo]. [trgWhatever] ON [dbo]. [tblWhatever]' y 'ENABLE TRIGGER [dbo]. [trgWhatever] ON [dbo]. [tblWhatever]' 22 sep. 152015-09-22 14:45:41

  0

NOTA - Me sale un error 'Sintaxis incorrecta cerca de 'DESACTIVAR'. ' a menos que coloque un ';' entre 'PRINT 'Some message'; DISABLE TRIGGER [dbo] ..... ' 23 sep. 152015-09-23 15:22:06


15

Sin embargo, es casi siempre una mala idea hacer esto. Te meterás con la integridad de la base de datos. No lo hagas sin considerar las ramificaciones y consultar con el dbas si los tienes.

Si sigue el código de Matt, asegúrese de recordar volver a activar el gatillo. Y recuerde que el activador está desactivado para todos insertando, actualizando o borrando de la tabla mientras está apagado, no solo para su proceso, por lo que si debe hacerse, hágalo durante las horas en que la base de datos esté menos activa (y preferiblemente en modo de usuario único).

Si necesita hacer esto para importar una gran cantidad de datos, entonces considere que la inserción masiva no desencadena los desencadenadores. Pero luego su proceso posterior a la inserción masiva tendrá que solucionar cualquier problema de integridad de datos que introduzca al activar los desencadenantes.

  0

Grandes puntos. La razón por la que necesitaba esto era cuando se copiaban datos de un entorno de producción a un entorno de prueba, algunas de las cuales se restablecían con el activador, pero las columnas relacionadas en otra tabla no lo seguían. 23 sep. 082008-09-23 21:12:18


30

A veces para completar una base de datos vacía desde un origen de datos externo o solucionar un problema en la base de datos Necesito desactivar TODOS los desencadenadores y restricciones. para hacerlo utilizo el siguiente código:

Para desactivar todas las restricciones y disparadores:

sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all" 
sp_msforeachtable "ALTER TABLE ? DISABLE TRIGGER all" 

Para habilitar todas las restricciones y disparadores:

exec sp_msforeachtable @command1="print '?'", @command2="ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all" 
sp_msforeachtable @command1="print '?'", @command2="ALTER TABLE ? ENABLE TRIGGER all" 

me encontré con que la solución hace algún tiempo en SQLServerCentral, pero necesitaba modificar la parte de restricciones de habilitación ya que la original no funcionó por completo


9

Para extender la respuesta de Matt, este es un ejemplo dado en MSDN.

USE AdventureWorks; 
GO 
DISABLE TRIGGER Person.uAddress ON Person.Address; 
GO 
ENABLE Trigger Person.uAddress ON Person.Address; 
GO 

4

Otro enfoque es efectivamente desactivar el gatillo sin llegar a su desactivación, utilizando una variable de estado adicional que se incorpora en el gatillo.

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 

Para el estado de una variable podía leer algún tipo de registro de control de bloqueo en una tabla (mejor si se limita al contexto de la sesión actual), utilice CONTEXT_INFO() o utilice la presencia de una tabla temporal en particular nombre (que ya está limitada al ámbito de sesión):

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 

continuación para desactivar todos los disparadores:

select 1 as A into #Common_DisableTableTriggers; 
-- do work 
drop table #Common_DisableTableTriggers; -- or close connection 

Una desventaja potencialmente importante es que el gatillo está permanentemente slowe d abajo dependiendo de la complejidad del acceso de la variable de estado.

Editar: Agregando una referencia a este 2008 post by Samuel Vanga sorprendentemente similar.


2
ALTER TABLE table_name DISABLE TRIGGER TRIGGER_NAME 
-- Here your SQL query 
ALTER TABLE table_name ENABLE TRIGGER TRIGGER_NAME 

2
No

la mejor respuesta para la programación por lotes, pero para otros la búsqueda de esta pregunta en busca de una manera rápida y fácil de desactivar temporalmente un disparador, esto se puede lograr en SQL Server Management Studio.

  1. expanda la carpeta disparadores en la tabla
  2. haga clic con el gatillo
  3. desactivar

enter image description here

Siga el mismo proceso para volver a habilitar.