Question

Je recherche la méthode la plus portable pour vérifier l'existence d'un déclencheur dans MS SQL Server. Il doit fonctionner au moins sur SQL Server 2000, 2005 et de préférence 2008.

Les informations ne semblent pas figurer dans INFORMATION_SCHEMA, mais si elles s'y 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 suis pas sûr que cela fonctionne avec toutes les versions de SQL Server.

Était-ce utile?

La solution

Ceci fonctionne sur SQL Server 2000 et supérieur

IF OBJECTPROPERTY(OBJECT_ID('{your_trigger}'), 'IsTrigger') = 1
BEGIN
    ...
END

Notez que la conversation naïve 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

... parce que si l'objet n'existe pas du tout, OBJECTPROPERTY renvoie NULL, et <> 1 n'est (bien sûr) pas COALESCE (ni rien d'autre).

Sous SQL Server 2005 ou version ultérieure, vous pouvez utiliser 0 cette option, mais si vous devez prendre en charge SQL Server 2000, vous devez structurer votre instruction de manière à prendre en charge les trois valeurs de retour possibles: <= > (l'objet n'existe pas du tout), 1 (il existe mais ce n'est pas un déclencheur) ou <=> (c'est un déclencheur).

Autres conseils

Il existe également le & "sys.triggers &" préféré; vue catalogue:

select * from sys.triggers where name = 'MyTrigger'

ou appelez le proc sp_Helptrigger stocké:

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 procéder de la manière suivante:

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'agisse 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 les autres types d'objets (tables, vues, clés, etc.), voir: http : //msdn.microsoft.com/en-us/library/ms190324.aspx sous "type".

Testé et ne fonctionne pas sur SQL Server 2000:

select * from sys.triggers where name = 'MyTrigger'

Testé et fonctionne correctement sous SQL Server 2000 et SQL Server 2005:

select * from dbo.sysobjects
where name = 'MyTrigger' and OBJECTPROPERTY(id, 'IsTrigger')

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 bloc direct TSQL try/Catch, 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.

Il suffit ensuite de vérifier si le résultat exécuté renvoie des lignes ou non, ce qui est facile à utiliser dans SQL direct ainsi que dans les API de programmation (C #, ...).

Les noms de déclencheurs sont-ils forcés d'être uniques dans SQL Server?

Comme 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 30 000 tables, qui ont toutes au moins un déclencheur et peuvent en avoir plusieurs (mauvaise conception de base de données - très probablement, mais cela avait du sens il y a des années et n'a pas bien évolué)

j'utilise

SELECT * FROM sys.triggers 
WHERE [parent_id] = OBJECT_ID(@tableName) 
AND [name] = @triggerName

Je voudrais utiliser 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 avec périmètre d'application sur SQL Server 2014, vous devriez 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 d’erreur, merci de me le faire savoir.

Modifier: Je n'ai pas vérifié cette dm sur d'autres versions 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) 1 juin 2011   15:43:18 Droits d'auteur (c) Microsoft Corporation Enterprise Edition   (64 bits) sous Windows NT 6.1 (version 7601: Service Pack 1)   (Hyperviseur)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top