我正在寻找最便携的方法来检查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(它存在但不是触发器),或<=>(它是触发器)。

其他提示

还有首选的<!> quot; sys.triggers <!>;目录视图:

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

或调用sp_Helptrigger存储过程:

exec sp_helptrigger 'MyTableName'

但除此之外,我猜是关于它的: - )

马克

更新(对于Jakub Januszkiewicz):

如果您需要包含架构信息,您还可以执行以下操作:

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 :“type”下的//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 bock,作为最快的方法。

例如:

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.

然后只需检查Executed Result是否返回行,这在直接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]

如果您在SQL Server 2014上尝试查找服务器范围的DDL触发器,则应尝试使用sys.server_triggers。

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

如果我告诉任何不正确的事,请告诉我。

编辑: 我没有在其他版本的SQL Server上检查此dm。

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)2011年6月1日   15:43:18版权所有(c)Microsoft Corporation Enterprise Edition   Windows NT 6.1(Build 7601:Service Pack 1)上的(64位)   (管理程序)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top