Qual é a maneira mais portátil para verificar se um gatilho existe no SQL Server?
-
10-07-2019 - |
Pergunta
Eu estou procurando o mais portátil método para verificar se há existência de um gatilho em MS SQL Server. Ele precisa trabalhar em pelo menos SQL Server 2000, 2005 e de preferência de 2008.
As informações não parece estar em INFORMATION_SCHEMA, mas se ele está em algum lugar, eu preferiria usá-lo de lá.
Eu sei deste método:
if exists (
select * from dbo.sysobjects
where name = 'MyTrigger'
and OBJECTPROPERTY(id, 'IsTrigger') = 1
)
begin
end
Mas eu não tenho certeza se ele funciona em todas as versões do SQL Server.
Solução
Isso funciona em SQL Server 2000 e acima
IF OBJECTPROPERTY(OBJECT_ID('{your_trigger}'), 'IsTrigger') = 1
BEGIN
...
END
Note que o inverso ingênuo não funciona de forma confiável:
-- This doesn't work for checking for absense
IF OBJECTPROPERTY(OBJECT_ID('{your_trigger}'), 'IsTrigger') <> 1
BEGIN
...
END
... porque se o objeto não existir, OBJECTPROPERTY
retornos NULL
e NULL
é (obviamente) não <> 1
(ou qualquer outra coisa).
No SQL Server 2005 ou mais tarde, você poderia usar COALESCE
Para lidar com isso, mas se você precisa para suportar o SQL Server 2000, você terá que estruturar sua declaração de lidar com os três valores de retorno possíveis: NULL
(o objeto não existe em tudo), 0
(ela existe, mas não é um gatilho), ou 1
(é um gatilho).
Outras dicas
Há também o "sys.triggers" catálogo vista preferida:
select * from sys.triggers where name = 'MyTrigger'
ou ligue para o sp_Helptrigger armazenados proc:
exec sp_helptrigger 'MyTableName'
Mas além disso, eu acho que é sobre ele: -)
Marc
Update (para Jakub Januszkiewicz):
Se você precisa incluir as informações de esquema, você também poderia fazer algo parecido com isto:
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
Assumindo que é um gatilho DML:
IF OBJECT_ID('your_trigger', 'TR') IS NOT NULL
BEGIN
PRINT 'Trigger exists'
END
ELSE
BEGIN
PRINT 'Trigger does not exist'
END
Para outros tipos de objetos (tabelas, vistas, chaves, o que quer ...), ver: http :. //msdn.microsoft.com/en-us/library/ms190324.aspx sob 'tipo'
Testado e não funciona no SQL Server 2000:
select * from sys.triggers where name = 'MyTrigger'
Testado e funciona ok no SQL Server 2000 e SQL Server 2005:
select * from dbo.sysobjects
where name = 'MyTrigger' and OBJECTPROPERTY(id, 'IsTrigger')
Além da excelente resposta por marc_s:
Se o Verificar existência é destinado antes de deixar cair ou modificar o gatilho, de alguma forma, usar um TSQL try/Catch
bock direta, como o meio mais rápido.
Por exemplo:
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;
A mensagem de erro será
Cannot drop the trigger 'MyTableAfterUpdate', because it does not exist or you do not have permission.
Em seguida, basta verificar se o resultado Executado voltou linhas ou não, que é fácil em sql directo, bem como as APIs programáticas (C #, ...).
são nomes de gatilho forçado a ser único no servidor SQL?
Como gatilhos são, por definição, aplicado a uma tabela específica não seria mais eficiente para restringir a pesquisa a apenas a tabela em questão?
Temos um banco de dados com mais de 30 mil mesas em que todos os que têm pelo menos um gatilho e pode ter mais (má concepção DB - muito provavelmente, mas fazia sentido anos atrás e não escala bem)
Eu uso
SELECT * FROM sys.triggers
WHERE [parent_id] = OBJECT_ID(@tableName)
AND [name] = @triggerName
Gostaria de usar essa sintaxe para verificar e soltar gatilho
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 você está tentando encontrar um servidor com escopo DDL gatilho no SQL Server 2014, você deve tentar sys.server_triggers.
IF EXISTS (SELECT * FROM sys.server_triggers WHERE name = 'your trigger name')
BEGIN
{do whatever you want here}
END
Se eu dissesse tou nada incorreto, por favor me avise.
Edit: Eu não verificar para este dm em outro versões do SQL Server.
Gerado 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) 01 de junho de 2011 15:43:18 Copyright (c) Microsoft Corporation Enterprise Edition (64 bits) no Windows NT 6.1 (Construir 7601: Service Pack 1) (Hypervisor)