Каков наиболее переносимый способ проверить, существует ли триггер в SQL Server?

Я ищу большинство портативных метод проверки наличия триггера в MS SQL Server. Он должен работать по крайней мере в SQL Server 2000, 2005 и желательно 2008.

информация, похоже, не находится в INFORMATION_SCHEMA, но если она где-то там, я бы предпочел использовать ее оттуда.

Я знаю этот метод:

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

end

но я не уверен, работает ли он во всех версиях SQL Server.

9 ответов


это работает на SQL Server 2000 и выше

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

обратите внимание, что наивный converse не работает надежно:

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

...потому что, если объект вообще не существует,OBJECTPROPERTY возвращает NULL и NULL - Это (конечно) не <> 1 (или что-нибудь еще).

в SQL Server 2005 или более поздней версии можно использовать COALESCE чтобы справиться с этим, но если вам нужно поддерживать SQL Server 2000, вам придется структурировать свой оператор, чтобы иметь дело с тремя возможные возвращаемые значения: NULL (объект не существует), 0 (Она существует, но не является триггером), или 1 (это триггер).


есть также предпочтительный " sys.триггеры " вид каталога:

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

или вызовите хранимый proc sp_Helptrigger:

exec sp_helptrigger 'MyTableName'

но кроме этого, я думаю, что об этом: -)

Марк

обновление (для Якуба Янушкевича):

Если вам нужно включить информацию о схеме, вы также можете сделать что-то вроде этого:

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

предполагая, что это триггер DML:

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

для других типов объектов (таблицы, представления, ключи, что угодно...), см: http://msdn.microsoft.com/en-us/library/ms190324.aspx под "тип".


протестировано и не работает на SQL Server 2000:

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

протестировано и работает нормально на SQL Server 2000 и SQL Server 2005:

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

В дополнение к отличному ответу marc_s:

Если наличие проверить предназначен до падения или изменения триггера каким-либо образом, используйте прямой TSQL try/Catch бок, как самое быстрое средство.

например:

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;

сообщение об ошибке будет

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

затем просто проверьте, вернул ли выполненный результат строки или нет, что легко в прямом sql, а также программных API (C#,...).


имена триггеров должны быть уникальными в SQL server?

поскольку триггеры по определению применяются к определенной таблице, не было бы более эффективным ограничить поиск только соответствующей таблицей?

у нас есть база данных с более чем 30K таблицами в ней, все из которых имеют по крайней мере один триггер и могут иметь больше (плохой дизайн БД - вполне вероятно, но это имело смысл много лет назад и не масштабировалось хорошо)

Я использую

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

Я бы использовал этот синтаксис для проверки и сброса триггера

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]

Если вы пытаетесь найти триггер DDL с областью действия сервера в SQL Server 2014, вы должны попробовать sys.server_triggers.

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

Если я сказал tou что-нибудь неправильное, пожалуйста, дайте мне знать.

изменить: Я не проверял этот dm на других версиях SQL Server.


создается с помощью Среда 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  
...

на select @@version

Microsoft SQL Server 2008 R2 (RTM) - 10.50.1797.0 (X64) Июнь 1 2011 15: 43: 18 Авторское право (c) Microsoft Corporation Enterprise Edition (64-разрядная версия) в Windows NT 6.1 (сборка 7601: пакет обновления 1) (Гипервизор)