Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 检查SQL Server中是否存在触发器的最方便的方法是什么?_Sql Server_Triggers_Information Schema - Fatal编程技术网

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

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 但

我正在寻找最可移植的方法来检查MS SQL Server中是否存在触发器。它至少需要在SQLServer2000、2005和2008上运行

信息似乎不在信息模式中,但如果它在某个地方,我更愿意从那里使用它

我确实知道这种方法:

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')之后
to
select*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  
...