Come posso estrarre la lista dei trigger disabilitati per una o più tabelle, o per l'intero database?

Recentemente, ho avuto la necessità di disabilitare temporaneamente (per alcune ore) tutti i trigger definiti su una tabella. La successiva abilitazione, però, doveva tenere conto dei trigger già disabilitati all'origine, che avevo necessità di conoscere prima di eseguire il comando:

ALTER TABLE <nome_tabella> DISABLE TRIGGER ALL;

...in caso contrario, avrei rischiato di abilitare un trigger che in origine era disabilitato!

Ipotizziamo il seguente scenario: la tabella Production.Product, nel database di esempio AdventureWorks, possiede due oggetti trigger, uno attivo per le operazioni di INSERT ed un altro per le operazioni di UPDATE; il secondo trigger però (quello sull'ON UPDATE) risulta essere disabilitato. Il seguente frammento di codice in linguaggio T-SQL riproduce lo scenario appena descritto.

USE [AdventureWorks];
GO

IF OBJECT_ID('Production.TR_INS_Production_Product') IS NOT NULL
  DROP TRIGGER Production.TR_INS_Production_Product;
GO

IF OBJECT_ID('Production.TR_UPD_Production_Product') IS NOT NULL
  DROP TRIGGER Production.TR_UPD_Production_Product;
GO

CREATE TRIGGER Production.TR_INS_Production_Product ON Production.Product
FOR INSERT
AS
BEGIN
  PRINT('Hello, I am TR_INS_Production_Product');
END;
GO

CREATE TRIGGER Production.TR_UPD_Production_Product ON Production.Product
FOR UPDATE
AS
BEGIN
  PRINT('Hello, I am TR_UPD_Production_Product');
END;
GO

ALTER TABLE Production.Product
  DISABLE TRIGGER TR_UPD_Production_Product;
GO

I seguenti batch T-SQL, con compatibilità rispettivamente SQL Server 2005, 2008 (R2), 2012 ("Denali") e SQL Server 2000 permettono di ottenere la lista dei trigger disabilitati per la tabella Production.Product.

Soluzione per SQL Server 2005, 2008 (R2) e 2012 ("Denali")

Lista trigger disabilitati per la tabella Production.Product.

SELECT
  s.name AS [Schema Name]
  ,o.name AS [Table Name]
  ,t.name AS [Trigger Name]
  ,CASE
     WHEN (t.is_disabled = 1)
     THEN 'Disable'
     ELSE 'Enable'
   END AS [Trigger Status]    
FROM
  sys.triggers AS t
JOIN
  sys.objects AS o on o.[object_id]=t.[parent_id]
JOIN
  sys.schemas AS s on o.[schema_id]=s.[schema_id]
WHERE
  (s.name = 'Production')
  AND (o.name = 'Product')
  AND (is_disabled = 1);
GO

L'output è illustrato in figura 1, filtrando la query per lo schema Production e per la tabella Product otteniamo il trigger TR_UPD_Production_Product.

Disable trigger

Figura 1 – Trigger disabilitati, definiti sulla tabella Production.Product

Con SQL Server 2000, però, non abbiamo a disposizione la catalog view sys.triggers, dovremo quindi interrogare la proprietà ExecIsTriggerDisabled di ogni oggetto trigger utilizzando la funzione OBJECTPROPERTY.

Soluzione per SQL Server 2000

Lista trigger disabilitati per la tabella Product.

SELECT
  t.[name] AS [Table Name]
  ,tr.[name] AS [Trigger Name]
  ,CASE
     WHEN (1 = OBJECTPROPERTY(tr.[id], 'ExecIsTriggerDisabled'))
     THEN 'Disable'
     ELSE 'Enable'
     END [Trigger Status]
FROM
  sysobjects t
JOIN
  sysobjects tr ON t.[id] = tr.parent_obj
WHERE
  ((t.xtype = 'U') OR (t.xtype = 'V'))
  AND (t.name = 'Product')
  AND (tr.xtype = 'TR')
  AND (objectproperty(tr.[id], 'ExecIsTriggerDisabled') = 1);
GO

L'output è illustrato in figura 2.

Disable trigger on SQL Server 2000

Figura 2 – Trigger disabilitati, definiti sulla tabella Product (compatibilità SQL Server 2000)

Conclusioni

Gli ultimi due statement T-SQL permettono di individuare i trigger disabilitati su una determinata tabella nel DB correntemente selezionato. Togliendo il filtro per tabella, è possibile ottenere tutti i trigger disabilitati nel DB corrente.