簡體   English   中英

什么是檢查SQL Server中是否存在觸發器的最便攜方法?

[英]What is the most portable way to check whether a trigger exists in SQL Server?

我正在尋找最便攜的方法來檢查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版本。

還有首選的“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及更高版本

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 (它是一個觸發器)。

假設它是DML觸發器:

IF OBJECT_ID('your_trigger', 'TR') IS NOT NULL
BEGIN
    PRINT 'Trigger exists'
END
ELSE
BEGIN
    PRINT 'Trigger does not exist'
END

對於其他類型的對象(表,視圖,鍵,等等......),請參閱:“類型”下的http://msdn.microsoft.com/en-us/library/ms190324.aspx

除了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 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中被強制為唯一?

由於根據定義將觸發器應用於特定表格,將搜索限制為僅限於相關表格會不會更有效率?

我們有一個包含超過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

如果我告訴tou任何不正確的,請告訴我。

編輯:我沒有在其他版本的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企業版(64位)在Windows NT 6.1(Build 7601:Service Pack 1)上(管理程序) )

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM