¿Cuál es la manera más portable para comprobar si un desencadenador existe en SQL Server?

StackOverflow https://stackoverflow.com/questions/636452

Pregunta

Estoy buscando la la mayoría de los portátiles método para comprobar la existencia de un disparo en MS SQL Server.Que necesita para funcionar al menos en SQL Server 2000, 2005 y preferiblemente de 2008.

La información no parece estar en INFORMATION_SCHEMA, pero si es que en alguna parte, yo prefiero usar a partir de allí.

Yo sé de este método:

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

end

Pero no estoy seguro de si funciona en todas las versiones de SQL Server.

¿Fue útil?

Solución

Esto funciona en SQL Server 2000 y por encima de

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

Tenga en cuenta que el ingenuo conversar no funciona de forma fiable:

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

...porque si el objeto no existe en absoluto, OBJECTPROPERTY devuelve NULL, y NULL es (por supuesto) no <> 1 (o cualquier otra cosa).

En SQL Server 2005 o posterior, puede utilizar COALESCE para lidiar con eso, pero si necesita compatibilidad con SQL Server 2000, tendrás que estructura su instrucción para lidiar con los tres posibles valores de retorno: NULL (el objeto no existe en absoluto), 0 (existe pero no es un trigger), o 1 (es un trigger).

Otros consejos

También está el " sys.triggers " preferido; vista de catálogo:

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

o llame al proceso almacenado sp_Helptrigger:

exec sp_helptrigger 'MyTableName'

Pero aparte de eso, supongo que eso es todo :-)

Marc

Actualización (para Jakub Januszkiewicz):

Si necesita incluir la información del esquema, también puede hacer algo como esto:

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

Suponiendo que es un desencadenador DML:

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

Para otros tipos de objetos (tablas, vistas, claves, lo que sea ...), consulte: http : //msdn.microsoft.com/en-us/library/ms190324.aspx en 'tipo'.

Probado y no funciona en SQL Server 2000:

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

Probado y funciona bien en SQL Server 2000 y SQL Server 2005:

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

Además de la excelente respuesta de marc_s:

si la verificación de existencia está destinada antes de soltar o modificar el disparador de alguna manera, use un bock TSQL try/Catch directo, como el medio más rápido.

Por ejemplo:

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;

El mensaje de error será

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

Luego, simplemente verifique si el Resultado ejecutado devolvió filas o no, lo que es fácil en SQL directo y en las API programáticas (C #, ...).

¿Se obliga a los nombres de los disparadores a ser únicos en el servidor SQL?

Como los desencadenantes se aplican por definición a una tabla específica, ¿no sería más eficiente restringir la búsqueda solo a la tabla en cuestión?

Tenemos una base de datos con más de 30k tablas, todas las cuales tienen al menos un disparador y pueden tener más (diseño de base de datos incorrecto, muy probablemente, pero tenía sentido hace años y no se escalaba bien)

Yo uso

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

Usaría esta sintaxis para verificar y soltar el disparador

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 está tratando de encontrar un disparador DDL con ámbito de servidor en SQL Server 2014, debe probar sys.server_triggers.

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

Si le dije algo incorrecto, hágamelo saber.

Editar: No busqué este dm en otras versiones de SQL Server.

Generado por 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  
...

Para select @@version

  

Microsoft SQL Server 2008 R2 (RTM) - 10.50.1797.0 (X64) 1 de junio de 2011   15:43:18 Copyright (c) Microsoft Corporation Enterprise Edition   (64 bits) en Windows NT 6.1 (compilación 7601: Service Pack 1)   (Hipervisor)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top