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をサポートする必要がある場合は、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) (ハイパーバイザー)