Je recherche la méthode la plus portable pour vérifier l'existence d'un déclencheur dans MS SQL Server. Il doit fonctionner sur au moins SQL Server 2000, 2005 et de préférence 2008.
Les informations ne semblent pas se trouver dans INFORMATION_SCHEMA, mais si elles se trouvent quelque part, je préférerais les utiliser à partir de là.
Je connais cette méthode:
if exists (
select * from dbo.sysobjects
where name = 'MyTrigger'
and OBJECTPROPERTY(id, 'IsTrigger') = 1
)
begin
end
Mais je ne sais pas si cela fonctionne sur toutes les versions de SQL Server.
Cela fonctionne sur SQL Server 2000 et supérieur
IF OBJECTPROPERTY(OBJECT_ID('{your_trigger}'), 'IsTrigger') = 1
BEGIN
...
END
Notez que l'inverse naïf ne fonctionne pas de manière fiable:
-- This doesn't work for checking for absense
IF OBJECTPROPERTY(OBJECT_ID('{your_trigger}'), 'IsTrigger') <> 1
BEGIN
...
END
... car si l'objet n'existe pas du tout, OBJECTPROPERTY
renvoie NULL
, et NULL
n'est (bien sûr) pas <> 1
(ou autre chose).
Sur SQL Server 2005 ou version ultérieure, vous pouvez utiliser COALESCE
pour y faire face, mais si vous devez prendre en charge SQL Server 2000, vous devrez structurer votre instruction pour gérer les trois valeurs de retour possibles: NULL
(l'objet n'existe pas du tout), 0
(il existe mais n'est pas un déclencheur), ou 1
(c'est un déclencheur).
Il y a aussi la vue de catalogue "sys.triggers" préférée:
select * from sys.triggers where name = 'MyTrigger'
ou appelez le proc stocké sp_Helptrigger:
exec sp_helptrigger 'MyTableName'
Mais à part ça, je suppose que c'est à peu près tout :-)
Marc
Mise à jour (pour Jakub Januszkiewicz):
Si vous devez inclure les informations de schéma, vous pouvez également faire quelque chose comme ceci:
SELECT
(list of columns)
FROM sys.triggers tr
INNER JOIN sys.tables t ON tr.parent_id = t.object_id
WHERE t.schema_id = SCHEMA_ID('dbo') -- or whatever you need
En supposant qu'il s'agit d'un déclencheur DML:
IF OBJECT_ID('your_trigger', 'TR') IS NOT NULL
BEGIN
PRINT 'Trigger exists'
END
ELSE
BEGIN
PRINT 'Trigger does not exist'
END
Pour d'autres types d'objets (tables, vues, clés, etc.), voir: http://msdn.Microsoft.com/en-us/library/ms190324.aspx sous 'type' .
En plus de l'excellente réponse de marc_s:
si le contrôle d'existence est prévu avant de supprimer ou de modifier le déclencheur d'une manière ou d'une autre, utilisez un bock TSQL try/Catch
direct, comme moyen le plus rapide.
Par exemple:
BEGIN TRY
DROP TRIGGER MyTableAfterUpdate;
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER() AS erno WHERE erno = 3701; -- may differ in SQL Server < 2005
END CATCH;
Le message d'erreur sera
Cannot drop the trigger 'MyTableAfterUpdate', because it does not exist or you do not have permission.
Ensuite, vérifiez simplement si le résultat exécuté a renvoyé des lignes ou non, ce qui est facile dans SQL direct ainsi que dans les API de programmation (C #, ...).
Testé et ne fonctionne pas sur SQL Server 2000:
select * from sys.triggers where name = 'MyTrigger'
Testé et fonctionne correctement sur SQL Server 2000 et SQL Server 2005:
select * from dbo.sysobjects
where name = 'MyTrigger' and OBJECTPROPERTY(id, 'IsTrigger')
Les noms de déclencheurs sont-ils forcés d'être uniques dans SQL Server?
Étant donné que les déclencheurs sont par définition appliqués à une table spécifique, ne serait-il pas plus efficace de limiter la recherche à la seule table en question?
Nous avons une base de données contenant plus de 30k tables, qui ont toutes au moins un déclencheur et peuvent en avoir plus (mauvaise conception de la base de données - très probablement, mais elle avait du sens il y a des années et n'était pas bien évolutive)
J'utilise
SELECT * FROM sys.triggers
WHERE [parent_id] = OBJECT_ID(@tableName)
AND [name] = @triggerName
J'utiliserais cette syntaxe pour vérifier et supprimer le déclencheur
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[SCHEMA_NAME].[TRIGGER_NAME]') AND type in (N'TR'))
DROP TRIGGER [SCHEMA_NAME].[TRIGGER_NAME]
Si vous essayez de trouver un déclencheur DDL de portée serveur sur SQL Server 2014, vous devez essayer sys.server_triggers.
IF EXISTS (SELECT * FROM sys.server_triggers WHERE name = 'your trigger name')
BEGIN
{do whatever you want here}
END
Si je vous dis quelque chose de incorrect, faites-le moi savoir.
Edit: je n'ai pas vérifié ce dm sur une autre version de SQL Server.
Généré par Sql Server Management Studio:
IF EXISTS (SELECT * FROM sys.triggers WHERE object_id = OBJECT_ID(N'[dbo].[RolesYAccesos2016_UsuariosCRM_trgAfterInsert]'))
DROP TRIGGER [dbo].[RolesYAccesos2016_UsuariosCRM_trgAfterInsert]
GO
CREATE TRIGGER [dbo].[RolesYAccesos2016_UsuariosCRM_trgAfterInsert]
ON [PortalMediadores].[dbo].[RolesYAccesos2016.UsuariosCRM]
FOR INSERT
AS
...
Pour select @@version
Microsoft SQL Server 2008 R2 (RTM) - 10.50.1797.0 (X64) 1er juin 2011 15:43:18 Copyright (c) Microsoft Corporation Enterprise Edition (64 bits) sur Windows NT 6.1 (Build 7601: Service Pack 1) (Hyperviseur )