Domanda

Sto cercando il metodo più portatile per verificare l'esistenza di un trigger in MS SQL Server. Deve funzionare almeno su SQL Server 2000, 2005 e preferibilmente 2008.

Le informazioni non sembrano essere in INFORMATION_SCHEMA, ma se sono lì da qualche parte, preferirei usarle da lì.

Conosco questo metodo:

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

end

Ma non sono sicuro che funzioni su tutte le versioni di SQL Server.

È stato utile?

Soluzione

Funziona su SQL Server 2000 e versioni successive

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

Nota che il contrario ingenuo non funziona in modo affidabile:

-- This doesn't work for checking for absense
IF OBJECTPROPERTY(OBJECT_ID('{your_trigger}'), 'IsTrigger') <> 1
BEGIN
    ...
END

... perché se l'oggetto non esiste affatto, OBJECTPROPERTY restituisce NULL e <> 1 è (ovviamente) non COALESCE (o qualsiasi altra cosa).

Su SQL Server 2005 o versioni successive, è possibile utilizzare 0 per gestirlo, ma se è necessario supportare SQL Server 2000, è necessario strutturare la propria istruzione per gestire i tre possibili valori restituiti: <= > (l'oggetto non esiste affatto), 1 (esiste ma non è un trigger) o <=> (è un trigger).

Altri suggerimenti

C'è anche il " preferito; sys.triggers " vista del catalogo:

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

o chiama il proc memorizzato sp_Helptrigger:

exec sp_helptrigger 'MyTableName'

Ma a parte questo, immagino che sia a questo proposito :-)

Marc

Aggiornamento (per Jakub Januszkiewicz):

Se devi includere le informazioni sullo schema, puoi anche fare qualcosa del genere:

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

Supponendo che sia un trigger DML:

IF OBJECT_ID('your_trigger', 'TR') IS NOT NULL
BEGIN
    PRINT 'Trigger exists'
END
ELSE
BEGIN
    PRINT 'Trigger does not exist'
END

Per altri tipi di oggetti (tabelle, viste, chiavi, qualunque cosa ...), vedere: http : //msdn.microsoft.com/en-us/library/ms190324.aspx in "tipo".

Testato e non funziona su SQL Server 2000:

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

Testato e funziona correttamente su SQL Server 2000 e SQL Server 2005:

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

Oltre all'ottima risposta di marc_s:

se il controllo dell'esistenza è previsto prima di rilasciare o modificare il trigger in qualche modo, utilizzare un blocco diretto TSQL try/Catch, come mezzo più veloce.

Ad esempio:

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;

Il messaggio di errore sarà

Cannot drop the trigger 'MyTableAfterUpdate', because it does not exist or you do not have permission.

Quindi controlla semplicemente se il risultato eseguito ha restituito righe o meno, il che è facile in sql diretto e nelle API programmatiche (C #, ...).

I nomi dei trigger sono obbligati a essere univoci in SQL Server?

Poiché i trigger vengono applicati per definizione a una tabella specifica, non sarebbe più efficace limitare la ricerca solo alla tabella in questione?

Abbiamo un database con oltre 30k tabelle al suo interno che hanno almeno un trigger e potrebbero averne di più (cattiva progettazione di DB - molto probabilmente, ma aveva senso anni fa e non si ridimensionava bene)

Uso

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

Userei questa sintassi per controllare e rilasciare il trigger

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]

Se stai cercando di trovare un trigger DDL con ambito server su SQL Server 2014, dovresti provare sys.server_triggers.

IF EXISTS (SELECT * FROM sys.server_triggers WHERE name = 'your trigger name')
BEGIN
    {do whatever you want here}
END

Se ti ho detto qualcosa di sbagliato, per favore fatemelo sapere.

Modifica: Non ho verificato questo dm su altre versioni di SQL Server.

Generato da 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  
...

Per select @@version

  

Microsoft SQL Server 2008 R2 (RTM) - 10.50.1797.0 (X64) 1 giugno 2011   15:43:18 Copyright (c) Microsoft Corporation Enterprise Edition   (64 bit) su Windows NT 6.1 (build 7601: Service Pack 1)   (Hypervisor)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top