Как изменить порядок срабатывания триггеров?

12

На самом деле я редко использую триггеры. Итак, я столкнулся с проблемой в первый раз. У меня есть много таблиц с триггерами (2 или более для каждой таблицы). Я хотел бы знать и изменить порядок срабатывания триггеров для каждой таблицы. Можно ли получить эту информацию?

ДОБАВЛЕНО:

Вот хорошая статья о mssqltips, которую я нашел.

Гарик
источник

Ответы:

12

Вы можете использовать следующую инструкцию, чтобы перечислить все триггеры в каждой таблице.

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

Как только вы узнаете все триггеры. Вы можете вручную изменить порядок, используя sp_settriggerorder

альтернативный текст

CoderHawk
источник
2
Разве «isafter» просто указывает на то, что триггер определен как AFTER <action>, а не INSTEAD OF <action>, а не диктует что-либо о порядке выполнения двух или более триггеров одного типа?
Дэвид Спиллетт
@ Дэвид - да! Вы правы
CoderHawk
12

IIRC вы не можете точно гарантировать порядок, при котором триггеры (с тем же определением того, на что и когда реагировать) срабатывают для данного действия против таблицы, для любого заданного количества триггеров.

Вы можете, хотя, если их три или меньше, так как вы можете использовать sp_settriggerorder, чтобы установить первым быть первым, последним последним и тем, кто посередине имеет «неопределенный» порядок.

Если ваши триггеры чувствительны к порядку, который выполняется в этом, это часто указывает на то, что ваш дизайн становится более сложным, чем нужно (обычно из-за органического роста), и может извлечь выгоду из некоторого рефакторинга.

Дэвид Спиллетт
источник
+1 вы правы, я должен рефакторинг этого кода (он сложный и имеет перекрестные ссылки ...), но я на первом этапе - расследование.
Гарик
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
  ;
Джексон Джарвис
источник
1
Это выглядит довольно гладко. @garik, это работает в вашей среде? (Кстати, начальный комментарий SQL также должен быть частью блока кода.)
Ник Чаммас
1
@ Ник, ты прав. Я смотрю вокруг на несколько минут.
Гарик
@ Ник по умолчанию эти свойства пустые. поэтому, если выполнить, например, exec sp_settriggerorder @triggername = 'tr_xxx' , @order = 'Last' , @stmttype= 'DELETE'мы можем увидеть результат ('X') в результате запроса Джексона. Спасибо, Джексон.
Гарик