web-dev-qa-db-fra.com

Quelle est la façon la plus portable de vérifier si un déclencheur existe dans SQL Server?

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.

48
Blorgbeard

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).

34
wqw

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
60
marc_s

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' .

9
BodzioM

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 #, ...).

2
Lorenz Lo Sauer

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')
2
EJM

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
1
Morvael

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]
1
Arvind Sedha

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.

1
Diego Grigol

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 )

0
Kiquenet