SQL Serverにトリガーが存在するかどうかを確認する最もポータブルな方法は何ですか?

StackOverflow https://stackoverflow.com/questions/636452

質問

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

...オブジェクトがまったく存在しない場合、OBJECTPROPERTYNULLを返し、<> 1は(もちろん)COALESCE(またはその他)ではありません。

SQL Server 2005以降では、0を使用して対処できますが、SQL Server 2000をサポートする必要がある場合は、3つの可能な戻り値を処理するようにステートメントを構造化する必要があります。 >(オブジェクトがまったく存在しない)、1(存在するがトリガーではない)、または<=>(トリガーである)。

他のヒント

推奨される<!> quot; sys.triggers <!> quotもあります。カタログビュー:

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を参照してください。 ://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ブロックを使用します。

たとえば:

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.

次に、実行結果が行を返したかどうかを単純に確認します。これは、ダイレクトSQLおよびプログラムAPI(C#、...)で簡単です。

トリガー名はSQLサーバーで一意にする必要がありますか?

トリガーは定義により特定のテーブルに適用されるため、検索を問題のテーブルのみに制限するのは効率的ではないでしょうか?

3万個以上のテーブルを持つデータベースがあり、そのすべてに少なくとも1つのトリガーがあり、さらにトリガーがある場合があります(DBの設計が悪い-おそらく、それは数年前に意味があり、うまくスケールしませんでした)

使用

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 Copyright(c)Microsoft Corporation Enterprise Edition   (64ビット)Windows NT 6.1(ビルド7601:Service Pack 1)   (ハイパーバイザー)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top