什么是检查SQL Server中是否存在触发器的最便携方法?
-
10-07-2019 - |
题
我正在寻找最便携的方法来检查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位) (管理程序)