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

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

Вопрос

Я ищу то, что самый портативный метод проверки наличия триггера в 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.

Это было полезно?

Решение

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

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

Обратите внимание, что наивное обращение не работает надежно:

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

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

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

Другие советы

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

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

или вызовите хранимую процедуру 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?

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

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

Я использую

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

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

Редактировать:Я не проверял наличие этого 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 (окончательная первоначальная версия) - 10.50.1797.0 (X64) 1 июня 2011 г.   15:43:18 Copyright (c) Microsoft Corporation Enterprise Edition   (64-разрядная версия) в Windows NT 6.1 (сборка 7601: пакет обновления 1)   (Гипервизор)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top