什么是检查SQL Server中是否存在触发器的最便捷的方法?

我正在寻找最便携的方法来检查在MS SQL Server中的触发器的存在。 它至less需要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 ,而NULL (当然)不是<> 1 (或其他)。

在SQL Server 2005或更高版本中,可以使用COALESCE来处理这个问题,但是如果您需要支持SQL Server 2000,则必须构造语句来处理三个可能的返回值: NULL (该对象不存在), 0 (它存在但不是一个触发器),或1 (这是一个触发器)。

还有一些首选的“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 

对于其他types的对象(表,视图,键,无论…),请参阅:“types”下的http://msdn.microsoft.com/en-us/library/ms190324.aspx

经过testing,在SQL Server 2000上不起作用:

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

在SQL Server 2000和SQL Server 2005上testing并正常工作:

 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中被强制为唯一的吗?

由于触发器是根据定义应用于特定的表,所以将search限制在仅有的表中是不是更有效率?

我们有一个超过30k表的数据库,其中至less有一个触发器,可能会有更多(糟糕的数据库devise – 很可能,但它在几年前是有道理的,并没有很好地扩展)

我用

 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 Windows Server 2008 R2(RTM) – 10.50.1797.0(X64)Jun 1 2011 15:43:18在Windows NT 6.1(Build 7601:Service Pack 1)上的Microsoft Corporation企业版(64位) )