Como alterar a ordem de disparo dos gatilhos?

12

Realmente raramente uso gatilhos. Então, eu encontrei um problema na primeira vez. Eu tenho muitas tabelas com gatilhos (2 ou mais para cada tabela). Gostaria de saber e alterar a ordem dos disparadores de disparos para cada tabela. É possível obter essa informação?

ADICIONADO:

Aqui está um bom artigo sobre mssqltips que eu encontrei.

garik
fonte

Respostas:

12

Você pode usar a seguinte instrução para listar todos os gatilhos em cada tabela.

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

Depois de descobrir todos os gatilhos. Você pode alterar manualmente a ordem usando sp_settriggerorder

texto alternativo

CoderHawk
fonte
2
"Isafter" não indica apenas que o gatilho é definido como APÓS <ação> em vez de INSTEAD OF <ação>, em vez de ditar algo sobre a ordem de execução de dois ou mais gatilhos do mesmo tipo?
David Spillett
@ David - sim! você está certo
CoderHawk 10/01
12

No IIRC, você não pode garantir exatamente a ordem em que os gatilhos (com a mesma definição do que reagir e quando) serão acionados para uma determinada ação contra uma tabela, para um determinado número de gatilhos.

Você pode, no entanto, se houver três ou menos, pois pode usar sp_settriggerorder para definir o primeiro a ser o primeiro, o último a ser o último e o do meio a ter a ordem "indefinida".

Se seus gatilhos são sensíveis à ordem executada, isso geralmente indica que seu design está ficando mais complexo do que o necessário (geralmente devido ao crescimento orgânico) e pode se beneficiar de alguma refatoração.

David Spillett
fonte
+1 você está certo, eu tenho que refatorar esse código (é complexo e tem links cruzados ...), mas estou na primeira etapa - investigação.
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
fonte
1
Isso parece muito liso. @garik, isso funciona no seu ambiente? (BTW, o comentário SQL começando também deve fazer parte do bloco de código.)
Nick Chammas
1
@ Nick você está certo. Estou procurando por alguns minutos.
garik
@ Nick por padrão, essas propriedades estão vazias. então, se executar, por exemplo exec sp_settriggerorder @triggername = 'tr_xxx' , @order = 'Last' , @stmttype= 'DELETE', podemos ver o resultado ('X') no resultado da consulta de Jackson. Obrigado Jackson.
garik