Sql server 检查SQL Server中是否存在触发器的最方便的方法是什么?
我正在寻找最可移植的方法来检查MS SQL Server中是否存在触发器。它至少需要在SQLServer2000、2005和2008上运行 信息似乎不在信息模式中,但如果它在某个地方,我更愿意从那里使用它 我确实知道这种方法:Sql server 检查SQL Server中是否存在触发器的最方便的方法是什么?,sql-server,triggers,information-schema,Sql Server,Triggers,Information Schema,我正在寻找最可移植的方法来检查MS SQL Server中是否存在触发器。它至少需要在SQLServer2000、2005和2008上运行 信息似乎不在信息模式中,但如果它在某个地方,我更愿意从那里使用它 我确实知道这种方法: if exists ( select * from dbo.sysobjects where name = 'MyTrigger' and OBJECTPROPERTY(id, 'IsTrigger') = 1 ) begin end 但
if exists (
select * from dbo.sysobjects
where name = 'MyTrigger'
and OBJECTPROPERTY(id, 'IsTrigger') = 1
)
begin
end
但我不确定它是否适用于所有SQL Server版本。还有首选的“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
已在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')
这适用于SQL Server 2000及更高版本
IF OBJECTPROPERTY(OBJECT_ID('{your_trigger}'), 'IsTrigger') = 1
BEGIN
...
END
请注意,naive converse无法可靠地工作:
-- This doesn't work for checking for absense
IF OBJECTPROPERTY(OBJECT_ID('{your_trigger}'), 'IsTrigger') <> 1
BEGIN
...
END
——这不适用于检查缺席情况
如果OBJECTPROPERTY(OBJECT_ID({your_trigger}'),'IsTrigger')1
开始
...
结束
…因为如果对象根本不存在,OBJECTPROPERTY
返回NULL
,而NULL
当然不是1
(或任何其他内容)
在SQL Server 2005或更高版本上,您可以使用
COALESCE
来处理此问题,但如果您需要支持SQL Server 2000,则必须构造语句以处理三个可能的返回值:NULL
(对象根本不存在)、0
(它存在但不是触发器)或1
(它是一个触发器)。假设它是一个DML触发器:
IF OBJECT_ID('your_trigger', 'TR') IS NOT NULL
BEGIN
PRINT 'Trigger exists'
END
ELSE
BEGIN
PRINT 'Trigger does not exist'
END
对于其他类型的对象(表、视图、键等等),请参见:在“类型”下。触发器名称在SQL server中是否强制唯一 根据定义,触发器应用于特定的表,因此将搜索限制为只搜索有问题的表不是更有效吗 我们有一个数据库,其中有超过30k个表,所有这些表都至少有一个触发器,并且可能有更多的触发器(数据库设计很糟糕——很可能是这样,但它在几年前就有了意义,而且扩展性不好) 我用
除了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;
然后只需检查执行的结果是否返回行,这在direct sql和编程API(C#,…)中都很简单。我将使用此语法检查并删除触发器
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\u触发器
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
...
对于选择@@version
Microsoft SQL Server 2008 R2(RTM)-10.50.1797.0(X64)2011年6月1日
15:43:18版权所有(c)微软公司企业版
Windows NT 6.1上的(64位)(版本7601:Service Pack 1)
(虚拟机监控程序)
FWIW,您的
select*from dbo.sysobjects,其中name='MyTrigger'和OBJECTPROPERTY(id,'IsTrigger')
不适用于我在SQL-2000上插入、删除trigger后的正常工作。行位于sysobjects
中,但id上的OBJECTPROPERTY(id,'IsTrigger')
(作为上述的一部分或单独使用其原始ID)给出0
。检查xtype='TR'
或type='TR'
有效。select*from sys.triggers,其中name='MyTrigger'
不适用于my(正确工作等)触发器,而wgw的IF OBJECTPROPERTY(OBJECT_ID('your_trigger}'),'IsTrigger'))=1
确实…MSSQL 2008 R2。@JakubJanuszkiewicz:运行此命令时,您的数据库是否正确???sys.triggers
始终在当前数据库中显示触发器-它不会显示所有数据库中的所有触发器…@marc-s:我在正确的数据库中。我发现了问题-sys.triggers
中的名称列只是一个问题名称(不带架构名称),而OBJECT\u ID(“…”)
需要一个架构限定名(至少如果架构是非默认名称,如果我理解正确的话)。因此在复制我的工作OBJECT\u ID('MySchema.MyTrigger')之后
toselect*from sys.triggers
,它不起作用。只使用“MyTrigger”进行过滤很好。@marc-s:顺便说一句,这也意味着,如果一个数据库的不同架构中有多个同名触发器,select*from sys.triggers
会给您一个假阳性结果。select*从sys.objects中,type='TR'和schema_id=(从sys.schemas中选择schema_id,其中name='YourSchema')和name='YourTrigger'
将获得正确的触发器。这在SQL Server 2000中不起作用,因为SQL Server 2005中引入了sys…catalog视图。这将检查任何对象类型,而不仅仅是触发器。它打印“触发器存在”,在SQL Server 2012中起作用:“不能使用对象ID查询非架构范围的对象,例如DDL触发器。”这些情况下的解决方法是使用@marc_s在其回答中描述的sys.triggers
视图。
IF EXISTS (SELECT * FROM sys.server_triggers WHERE name = 'your trigger name')
BEGIN
{do whatever you want here}
END
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
...