¿Cómo cambiar el orden de disparo de los disparadores?

12

Realmente rara vez uso desencadenantes. Entonces encontré un problema por primera vez. Tengo muchas tablas con disparadores (2 o más para cada tabla). Me gustaría saber y cambiar el orden de los disparadores para cada tabla. ¿Es posible obtener esta información?

ADICIONAL:

Aquí hay un buen artículo completo sobre mssqltips que he encontrado.

Garik
fuente

Respuestas:

12

Puede usar la siguiente instrucción para enumerar todos los desencadenantes en cada tabla.

EXEC sp_MSForEachTable 'PRINT ''?'' 
EXEC sp_helptrigger ''?'''

Una vez que descubras todos los desencadenantes. Puede cambiar el orden manualmente usando sp_settriggerorder

texto alternativo

CoderHawk
fuente
2
¿"Isafter" no indica simplemente que el disparador se define como DESPUÉS de <acción> en lugar de INSTEAD OF <acción>, en lugar de dictar algo sobre el orden de ejecución de dos o más disparadores del mismo tipo?
David Spillett
@David: ¡sí! tienes razón
CoderHawk
12

IIRC no puede garantizar exactamente el orden que dispara (con la misma definición de a qué reaccionar y cuándo) dispara una acción dada contra una mesa, para un número determinado de disparadores.

Sin embargo, puede hacerlo si hay tres o menos, ya que puede usar sp_settriggerorder para establecer el primero en ser el primero, el último en ser el último y el que está en el medio para tener un orden "indefinido".

Si sus desencadenantes son sensibles al orden que se ejecuta en esto, a menudo indica que su diseño se está volviendo más complejo de lo necesario (generalmente debido al crecimiento orgánico) y puede beneficiarse de algunas refactorizaciones.

David Spillett
fuente
+1 tienes razón, tengo que refactorizar este código (es complejo y tiene enlaces cruzados ...), pero estoy en el primer paso: investigación.
garik
5
-- List tables with triggers and their firing order.  By Jackson Jarvis.
SELECT [tbl].[name] AS 'Table'
      ,[trg].[name] AS 'Trigger'
      ,CASE OBJECTPROPERTY([trg].[id] ,'ExecIsFirstInsertTrigger')
            WHEN 0 THEN ''
            ELSE 'X'
       END AS 'Insert First'
      ,CASE OBJECTPROPERTY([trg].[id] ,'ExecIsLastInsertTrigger')
            WHEN 0 THEN ''
            ELSE 'X'
       END AS 'Insert Last'
      ,CASE OBJECTPROPERTY([trg].[id] ,'ExecIsFirstUpdateTrigger')
            WHEN 0 THEN ''
            ELSE 'X'
       END AS 'Update First'
      ,CASE OBJECTPROPERTY([trg].[id] ,'ExecIsLastUpdateTrigger')
            WHEN 0 THEN ''
            ELSE 'X'
       END AS 'Update Last'
      ,CASE OBJECTPROPERTY([trg].[id] ,'ExecIsFirstDeleteTrigger')
            WHEN 0 THEN ''
            ELSE 'X'
       END AS 'Delete First'
      ,CASE OBJECTPROPERTY([trg].[id] ,'ExecIsLastDeleteTrigger')
            WHEN 0 THEN ''
            ELSE 'X'
       END AS 'Delete Last'
  FROM            [sysobjects] AS [trg] WITH (NOLOCK)
       INNER JOIN [sysobjects] AS [tbl] WITH (NOLOCK)
            ON  [trg].[parent_obj] = [tbl].[id]
  WHERE [trg].[TYPE] IN (N'TR')
  ORDER BY
       [tbl].[name] ASC
      ,[trg].[name] ASC
  ;
Jackson Jarvis
fuente
1
Esto se ve muy elegante. @garik, ¿funciona esto en tu entorno? (Por cierto, el comentario SQL inicial también debe ser parte del bloque de código).
Nick Chammas
1
@ Nick tienes razón. Estoy mirando alrededor por unos minutos.
garik
@Nick por defecto, estas propiedades están vacías. así que si se ejecuta, por ejemplo exec sp_settriggerorder @triggername = 'tr_xxx' , @order = 'Last' , @stmttype= 'DELETE', podemos ver el resultado ('X') en el resultado de la consulta de Jackson. Gracias Jackson.
garik