sql-server - update - triggers sql server
¿Cuál es la forma más portátil de verificar si existe un disparador en SQL Server? (9)
Estoy buscando el método más portátil para verificar la existencia de un desencadenador en MS SQL Server. Debe funcionar al menos SQL Server 2000, 2005 y preferiblemente 2008.
La información no parece estar en INFORMATION_SCHEMA, pero si está allí en alguna parte, preferiría usarla desde 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.
¿Los nombres de los ejecutores son forzados a ser únicos en el servidor SQL?
Como los factores desencadenantes se aplican por definición a una tabla específica, ¿no sería más eficaz restringir la búsqueda solo a la tabla en cuestión?
Tenemos una base de datos con más de 30k tablas en todas las cuales tienen al menos un disparador y pueden tener más (diseño de base de datos defectuoso, muy probablemente, pero tuvo sentido hace años y no se escalaron bien)
yo suelo
SELECT * FROM sys.triggers
WHERE [parent_id] = OBJECT_ID(@tableName)
AND [name] = @triggerName
Además de la excelente respuesta de marc_s:
si la comprobación de existencia está prevista antes de descartar o modificar el desencadenador de alguna manera, utilice un TSQL directo try/Catch
bock, como el más rápido significa.
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 arrojó filas o no, lo cual es fácil tanto en sql directo como en las API programáticas (C #, ...).
Esto funciona en SQL Server 2000 y superior
IF OBJECTPROPERTY(OBJECT_ID(''{your_trigger}''), ''IsTrigger'') = 1
BEGIN
...
END
Tenga en cuenta que el ingenuo converse no funciona de manera confiable:
-- This doesn''t work for checking for absense
IF OBJECTPROPERTY(OBJECT_ID(''{your_trigger}''), ''IsTrigger'') <> 1
BEGIN
...
END
... porque si el objeto no existe, OBJECTPROPERTY
devuelve NULL
, y NULL
es (por supuesto) no <> 1
(o cualquier otra cosa).
En SQL Server 2005 o posterior, podría usar COALESCE
para tratar con eso, pero si necesita soportar SQL Server 2000, tendrá que estructurar su declaración para tratar con los tres posibles valores de retorno: NULL
(el objeto no lo hace) existe en absoluto), 0
(existe pero no es un disparador), o 1
(es un disparador).
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 (Build 7601: Service Pack 1) (Hipervisor )
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'')
Si está tratando de encontrar un DDL Trigger con un 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 a tou algo incorrecto, por favor avíseme.
Editar: No revisé este dm en otras versiones de SQL Server.
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 ''type''.
También está la vista preferida del catálogo "sys.triggers":
select * from sys.triggers where name = ''MyTrigger''
o llame al proc almacenado sp_Helptrigger:
exec sp_helptrigger ''MyTableName''
Pero aparte de eso, creo que eso es todo :-)
Bagazo
Actualización (para Jakub Januszkiewicz):
Si necesita incluir la información del esquema, también podría 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
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]