次の方法で共有


CREATE TRIGGER (Transact-SQL)

DML トリガー、DDL トリガー、またはログオン トリガーを作成します。トリガーとは、特殊な種類のストアド プロシージャであり、データベース サーバーでイベントが発生したときに自動的に実行されます。DML トリガーは、ユーザーがデータ操作言語 (DML) イベントを介してデータを変更しようとしたときに実行されます。DML イベントは、テーブルやビューに対する INSERT、UPDATE、または DELETE ステートメントによって発生するイベントです。これらのトリガーは、テーブル行が影響を受けるかどうかにかかわらず、有効なイベントが発生したときに起動されます。

DDL トリガーは、さまざまなデータ定義言語 (DDL) イベントに対応して実行されます。本来、これらのイベントは、Transact-SQL の CREATE、ALTER、DROP ステートメント、および DDL に類似した処理を実行するシステム ストアド プロシージャに対応するものです。ログオン トリガーは、ユーザー セッションの確立時に発生する LOGON イベントに応答して起動されます。トリガーは、Transact-SQL ステートメントから直接作成できます。また、Microsoft .NET Framework 共通言語ランタイム (CLR) で作成され、SQL Server インスタンスにアップロードされたアセンブリのメソッドを使用して、トリガーを作成することもできます。SQL Server では、特定のステートメントに対して複数のトリガーを作成できます。

セキュリティに関する注意セキュリティに関する注意

上位の特権の下では、トリガー内の悪意のあるコードを実行できます。この脅威を緩和する方法の詳細については、「トリガのセキュリティの管理」を参照してください。

トピック リンク アイコンTransact-SQL 構文表記規則

構文

Trigger on an INSERT, UPDATE, or DELETE statement to a table or view (DML Trigger)
CREATE TRIGGER [ schema_name . ]trigger_name 
ON { table | view } 
[ WITH <dml_trigger_option> [ ,...n ] ]
{ FOR | AFTER | INSTEAD OF } 
{ [ INSERT ] [ , ] [ UPDATE ] [ , ] [ DELETE ] } 
[ WITH APPEND ] 
[ NOT FOR REPLICATION ] 
AS { sql_statement  [ ; ] [ ,...n ] | EXTERNAL NAME <method specifier [ ; ] > }

<dml_trigger_option> ::=
    [ ENCRYPTION ]
    [ EXECUTE AS Clause ]

<method_specifier> ::=
    assembly_name.class_name.method_name

Trigger on a CREATE, ALTER, DROP, GRANT, DENY, REVOKE, or UPDATE STATISTICS statement (DDL Trigger)
CREATE TRIGGER trigger_name 
ON { ALL SERVER | DATABASE } 
[ WITH <ddl_trigger_option> [ ,...n ] ]
{ FOR | AFTER } { event_type | event_group } [ ,...n ]
AS { sql_statement  [ ; ] [ ,...n ] | EXTERNAL NAME < method specifier >  [ ; ] }

<ddl_trigger_option> ::=
    [ ENCRYPTION ]
    [ EXECUTE AS Clause ]

<method_specifier> ::=
    assembly_name.class_name.method_name

Trigger on a LOGON event (Logon Trigger)
CREATE TRIGGER trigger_name 
ON ALL SERVER 
[ WITH <logon_trigger_option> [ ,...n ] ]
{ FOR| AFTER } LOGON  
AS { sql_statement  [ ; ] [ ,...n ] | EXTERNAL NAME < method specifier >  [ ; ] }

<logon_trigger_option> ::=
    [ ENCRYPTION ]
    [ EXECUTE AS Clause ]

<method_specifier> ::=
    assembly_name.class_name.method_name

引数

  • schema_name
    DML トリガーが属しているスキーマの名前を指定します。DML トリガーのスコープは、そのトリガーが作成されたテーブルまたはビューのスキーマです。DDL トリガーまたはログオン トリガーに対しては schema_name を指定できません。

  • trigger_name
    トリガーの名前を指定します。trigger_name は、識別子の規則に従う必要があります。ただし、trigger_name の先頭に # または ## を指定することはできません。

  • table |view
    DML トリガーを実行するテーブルまたはビューを指定します。これらはトリガー テーブルまたはトリガー ビューとも呼ばれます。テーブルまたはビューの完全修飾名の指定は省略可能です。ビューは INSTEAD OF トリガーでのみ参照できます。DML トリガーは、ローカルまたはグローバルの一時テーブルに対しては定義できません。

  • DATABASE
    DDL トリガーのスコープを現在のデータベースに適用します。これを指定すると、現在のデータベースで event_type または event_group が発生するたびにトリガーが起動します。

  • ALL SERVER
    DDL トリガーまたはログオン トリガーのスコープを現在のサーバーに適用します。これを指定すると、現在のサーバーの任意の場所で event_type または event_group が発生するたびにトリガーが起動します。

  • WITH ENCRYPTION
    CREATE TRIGGER ステートメントのテキストを暗号化します。WITH ENCRYPTION を使用すると、トリガーを SQL Server レプリケーションの一部としてパブリッシュできなくなります。WITH ENCRYPTION は、CLR トリガーに対しては指定できません。

  • EXECUTE AS
    トリガーを実行するセキュリティ コンテキストを指定します。これにより、トリガーが参照するデータベース オブジェクトの権限を検証するときに、SQL Server インスタンスが使用するユーザー アカウントを制御できます。

    詳細については、「EXECUTE AS 句 (Transact-SQL)」を参照してください。

  • FOR | AFTER
    AFTER を指定した場合は、トリガー元の SQL ステートメントで指定したすべての処理が正常に実行された場合のみ、DML トリガーが起動されます。このトリガーの実行前には、連鎖して行われるすべての参照操作と制約チェックも完了している必要があります。

    指定したキーワードが FOR だけの場合は、AFTER が既定値になります。

    AFTER トリガーは、ビューに対しては定義できません。

  • INSTEAD OF
    トリガーを起動する SQL ステートメントの代わりに (INSTEAD OF)、DML トリガーを実行します。したがって、トリガーを起動するステートメントの操作は無効になります。DDL トリガーまたはログオン トリガーでは INSTEAD OF を指定できません。

    テーブルまたはビューでは、INSERT、UPDATE、または DELETE の各ステートメントに定義できる INSTEAD OF トリガーは 1 つだけですが、ビューに別のビューを作成して、各ビューに独自の INSTEAD OF トリガーを定義することは可能です。

    INSTEAD OF トリガーは、WITH CHECK OPTION を使用する更新可能なビューでは使用できません。WITH CHECK OPTION が指定されている更新可能なビューに INSTEAD OF トリガーを追加した場合、SQL Server ではエラーが発生します。ユーザーは、INSTEAD OF トリガーを定義する前に、ALTER VIEW を使用して WITH CHECK OPTION を削除する必要があります。

  • { [ DELETE ] [ , ] [ INSERT ] [ , ] [ UPDATE ] }
    テーブルまたはビューに対して DML トリガーが試行されたとき、そのトリガーを有効にするデータ変更ステートメントを指定します。少なくとも 1 つのオプションを指定する必要があります。これらのオプションは、トリガー定義において、どのような順序や組み合わせでも指定できます。

    INSTEAD OF トリガーの場合、目的のテーブルに連鎖的な ON DELETE 参照操作を指定している参照関係があるときは、DELETE オプションを指定できません。同様に、目的のテーブルに連鎖的な ON UPDATE 参照操作を指定している参照関係があるときは、UPDATE オプションを指定できません。

  • event_type
    実行後に DDL トリガーを起動する Transact-SQL 言語イベントの名前を指定します。DDL トリガーで使用できるイベントの一覧については、「DDL イベント」を参照してください。

  • event_group
    Transact-SQL 言語イベントの定義済みグループの名前を指定します。DDL トリガーは、event_group に属する Transact-SQL 言語イベントの実行後に起動します。DDL トリガーで使用できるイベント グループの一覧については、「DDL イベント グループ」を参照してください。

    event_group は、対応するイベントの種類を sys.trigger_events カタログ ビューに追加した場合、CREATE TRIGGER が終了した後でマクロとしても動作します。

  • WITH APPEND
    既存のトリガーに対して、新しいトリガーを追加します。WITH APPEND は、INSTEAD OF トリガーと共に使用したり、AFTER トリガーが明示的に指定されている場合は使用できません。旧バージョンとの互換性上の理由から、WITH APPEND を使用できるのは、FOR が指定されている場合 (INSTEAD OF と AFTER のどちらも指定されていない場合) だけです。WITH APPEND は、EXTERNAL NAME が指定されている場合、つまり、トリガーが CLR トリガーの場合は指定できません。

    重要な注意事項重要

    WITH APPEND は、次期バージョンの Microsoft SQL Server では削除される予定です。新しい開発作業では、WITH APPEND の使用は避け、現在このオプションを使用しているアプリケーションは修正するようにしてください。

  • NOT FOR REPLICATION
    トリガーに関係するテーブルがレプリケーション エージェントによって変更されるときに、トリガーを実行しないことを示します。詳細については、「NOT FOR REPLICATION を使用した制約、ID、およびトリガの制御」を参照してください。

  • sql_statement
    トリガーの条件と動作を指定します。トリガーの条件では、試行した DML イベント、DDL イベント、またはログオン イベントによってトリガー動作が実行されるかどうかを判定するための補足の条件を指定します。

    Transact-SQL ステートメントで指定されたトリガー動作は、操作が試行されると有効になります。

    トリガーには、いくつかの例外を除き、任意の数と種類の Transact-SQL ステートメントを含めることができます。詳細については、「解説」を参照してください。トリガーは、データ変更またはデータ定義ステートメントに基づいてデータをチェックまたは変更するものであり、ユーザーに値は返されません。トリガー内の Transact-SQL ステートメントには、フロー制御言語が主に使用されます。

    DML トリガーでは、deleted および inserted 論理 (概念) テーブルが使用されます。論理テーブルは、トリガーが定義されるテーブル、つまり、ユーザー操作の対象となるテーブルと構造的に類似しています。deleted および inserted テーブルには、ユーザー操作によって変更される行の古い値または新しい値が格納されます。たとえば、deleted テーブルのすべての値を取得するには、次のように指定します。

    SELECT *
    FROM deleted
    

    詳細については、「inserted テーブルと deleted テーブルの使用」を参照してください。

    DDL トリガーおよびログオン トリガーでは、EVENTDATA (Transact-SQL) 関数を使用して、トリガー起動イベントに関する情報を取得できます。詳細については、「EVENTDATA 関数の使用」を参照してください。

    SQL Server では、テーブルやビューの INSTEAD OF トリガーによって、text、ntext、または image 型の列を更新できます。

    重要な注意事項重要

    ntext、text、および image の各データ型は、将来のバージョンの Microsoft SQL Server で削除される予定です。新しい開発作業では、これらのデータ型の使用は避け、現在これらのデータ型を使用しているアプリケーションは修正するようにしてください。代わりに、nvarchar(max)varchar(max)varbinary(max) を使用してください。AFTER トリガーと INSTEAD OF トリガーでは両方とも、inserted および deleted テーブルの varchar(MAX)、nvarchar(MAX)、および varbinary(MAX) 型のデータがサポートされます。

  • < method_specifier >
    CLR トリガーに対して、トリガーにバインドするアセンブリのメソッドを指定します。このメソッドは引数を受け取らず、void を返す必要があります。class_name は、有効な SQL Server 識別子で、アセンブリの表示設定が指定されたアセンブリ内にクラスとして存在する必要があります。このクラスの名前が名前空間で修飾されており、名前空間の部分がピリオド (.) で分けられている場合は、このクラス名を角かっこ ([ ]) または引用符 (" ") で区切る必要があります。入れ子にされたクラスは使用できません。

    注意

    既定では、CLR コードを実行する SQL Server の機能はオフになっています。マネージ コード モジュールを参照するデータベース オブジェクトを作成、変更、削除することはできますが、sp_configure によって clr enabled Option が有効化されていない場合、これらの参照は SQL Server インスタンスでは実行されません。

説明

DML トリガー

DML トリガーは主に、ビジネス ルールとデータの整合性を設定するために使用します。SQL Server では、ALTER TABLE と CREATE TABLE ステートメントで宣言参照整合性 (DRI) を使用できます。ただし、DRI ではデータベース間の参照整合性は提供されません。参照整合性とは、テーブルの主キーと外部キー間の関係についての規則です。参照整合性を設定するには、ALTER TABLE と CREATE TABLE で、PRIMARY KEY と FOREIGN KEY 制約を使用します。トリガー テーブルに制約が存在する場合、これらは INSTEAD OF トリガーが実行された後、AFTER トリガーが実行される前にチェックされます。制約違反の場合は、INSTEAD OF トリガーの動作がロールバックされ、AFTER トリガーは起動しません。

テーブルで実行される最初と最後の AFTER トリガーを、sp_settriggerorder を使用して指定できます。1 つのテーブルで、INSERT、UPDATE、DELETE の各操作に対して指定できる最初の AFTER トリガーと最後の AFTER トリガーはそれぞれ 1 つだけです。同じテーブルに他の AFTER トリガーが指定されている場合、トリガーはランダムに実行されます。

ALTER TRIGGER ステートメントを使って最初と最後のトリガーを変更し、変更したトリガーに設定されていた最初と最後を示す属性を削除した場合は、sp_settriggerorder を使用して順序の値を再設定する必要があります。

AFTER トリガーは、トリガーを起動する SQL ステートメントが正常に実行された後にのみ実行されます。このステートメントの実行には、更新または削除されるオブジェクトに関連付けられている連鎖的なすべての参照操作と制約チェックの実行も含まれます。

テーブルに定義された INSTEAD OF トリガーによって、そのテーブルに対して、通常は INSTEAD OF トリガーを再起動するステートメントが実行された場合、トリガーの再帰呼び出しは行われません。代わりに、そのステートメントでは、テーブルに INSTEAD OF トリガーが存在しないものとして処理が行われ、制約操作と AFTER トリガーの実行が連鎖的に開始されます。たとえば、あるテーブルに INSTEAD OF INSERT トリガーが定義されており、そのトリガーによって同じテーブルに対して INSERT ステートメントが実行された場合、INSTEAD OF トリガーによって実行された INSERT ステートメントでは、そのトリガーは再度呼び出されません。トリガーによって INSERT が実行されると、制約動作の実行処理とそのテーブルに定義されている AFTER INSERT トリガーの起動処理が開始されます。

ビューに定義された INSTEAD OF トリガーによって、そのビューに対し、通常 INSTEAD OF トリガーを再起動するステートメントが実行された場合、そのトリガーの再帰呼び出しは行われません。代わりに、そのステートメントは、そのビューの基になるベース テーブルに対する変更として解決されます。この場合、ビューの定義では、更新可能なビューの制限をすべて満たしている必要があります。更新可能なビューの定義については、「ビューを使用したデータ変更」を参照してください。

たとえば、あるビューに INSTEAD OF UPDATE トリガーが定義されており、そのトリガーによって同じビューを参照する UPDATE ステートメントが実行された場合、INSTEAD OF トリガーによって実行された UPDATE ステートメントでは、そのトリガーは再度呼び出されません。トリガーによって実行された UPDATE ステートメントでは、ビューに INSTEAD OF トリガーが存在しないものとして処理が行われます。この UPDATE によって変更された列は、単一のベース テーブルに対して解決される必要があります。基になるベース テーブルを変更するたびに、制約の適用とそのテーブルに定義された AFTER トリガーの起動が連鎖的に開始されます。

特定の列に対する UPDATE または INSERT 操作のテスト

特定の列に対する UPDATE または INSERT による変更に基づいて、操作を実行するよう Transact-SQL トリガーを設定できます。これを行うには、トリガー内で UPDATE() または COLUMNS_UPDATED を使用します。UPDATE() では、1 つの列に対する UPDATE または INSERT の操作がテストされます。COLUMNS_UPDATED では、複数の列に対する UPDATE 操作や INSERT 操作がテストされ、どの列が挿入または更新されたかを示すビット パターンが返されます。

トリガーの制限

CREATE TRIGGER はバッチ内の最初のステートメントとして使用する必要があり、1 つのテーブルにのみ適用されます。

トリガーは現在のデータベース内でしか作成できませんが、他のデータベース内のオブジェクトを参照することができます。

トリガーを修飾するトリガー スキーマ名を指定する場合は、テーブル名を同じ方法で修飾します。

1 つのトリガー動作を、同じ CREATE TRIGGER ステートメント内の複数のユーザー操作 (たとえば、INSERT と UPDATE) に対して定義できます。

INSTEAD OF DELETE/UPDATE トリガーは、外部キーを持ち、DELETE/UPDATE 操作に対する連鎖操作が定義されているテーブルでは定義できません。

トリガーの内部では任意の SET ステートメントを指定できます。選択した SET オプションは、トリガーの実行中有効で、終了後は元の設定に戻ります。

トリガーが起動すると、ストアド プロシージャの場合と同様に、呼び出し側アプリケーションに結果が返されます。トリガーを実行しても結果がアプリケーションに返されないようにするには、結果を返す SELECT ステートメントや変数を割り当てるステートメントをトリガーから除外します。ユーザーに結果を返す SELECT ステートメントや変数を割り当てるステートメントを含むトリガーは、トリガー テーブルの変更が許可される各アプリケーションに結果を書き込む必要があるという点から、特殊な扱いが必要です。トリガー内で変数を割り当てる必要がある場合は、トリガーの先頭で SET NOCOUNT ステートメントを使用して、結果セットが返されないようにします。

TRUNCATE TABLE ステートメントは実質的には DELETE ステートメントですが、個別の行の削除がログに記録されないため、トリガーはアクティブになりません。ただし、TRUNCATE TABLE ステートメントを実行する権限のあるユーザー以外は、このように DELETE トリガーが回避されてしまうことに注意を払う必要はありません。

ログに記録されるかどうかにかかわらず、WRITETEXT ステートメントによってトリガーがアクティブになることはありません。

次の Transact-SQL ステートメントは DML トリガーでは許可されません。

ALTER DATABASE

CREATE DATABASE

DROP DATABASE

LOAD DATABASE

LOAD LOG

RECONFIGURE

RESTORE DATABASE

RESTORE LOG

 

また、次の Transact-SQL ステートメントは、トリガーによって起動される操作の対象となるテーブルまたはビューに対して使用する場合は、DML トリガー内では使用できません。

CREATE INDEX (CREATE SPATIAL INDEX および CREATE XML INDEX を含む)

ALTER INDEX

DROP INDEX

DBCC DBREINDEX

ALTER PARTITION FUNCTION

DROP TABLE

ALTER TABLE (次の操作で使用する場合)

  • 列の追加、変更、または削除

  • パーティションの切り替え

  • PRIMARY KEY 制約や UNIQUE 制約の追加または削除

 

 

注意

SQL Server ではシステム テーブルに対するユーザー定義トリガーがサポートされないため、システム テーブルに対してはユーザー定義トリガーを作成しないことをお勧めします。

DDL トリガー

DDL トリガーでは、標準のトリガーと同様、イベントに応答してストアド プロシージャが実行されますが、標準のトリガーとは異なり、テーブルまたはビューの UPDATE、INSERT、DELETE ステートメントに応答して実行されることはありません。このトリガーは、主にデータ定義言語 (DDL) ステートメントに応答して起動します。このようなステートメントには、CREATE、ALTER、DROP、GRANT、DENY、REVOKE、UPDATE STATISTICS ステートメントなどがあります。DDL と同様の操作を実行する特定のシステム ストアド プロシージャも DDL トリガーを起動できます。

重要な注意事項重要

DDL トリガーをテストして、システム ストアド プロシージャの実行に対する応答を確認してください。たとえば、CREATE TYPE ステートメントおよび sp_addtype ストアド プロシージャと sp_rename ストアド プロシージャは、CREATE_TYPE イベントで作成される DDL トリガーを起動します。

DDL トリガーの詳細については、「DDL トリガ」を参照してください。

DDL トリガーは、ローカルまたはグローバルの一時テーブルおよびストアド プロシージャに影響するイベントに応答して起動されることはありません。

DML トリガーと異なり、DDL トリガーのスコープはスキーマに設定されません。このため、DDL トリガーに関するメタデータのクエリに、OBJECT_ID、OBJECT_NAME、OBJECTPROPERTY、OBJECTPROPERTYEX などの関数を使用することはできません。代わりに、カタログ ビューを使用してください。詳細については、「DDL トリガに関する情報の取得」を参照してください。

注意

サーバー スコープの DDL トリガーは、SQL Server Management Studio オブジェクト エクスプローラーの [Triggers] フォルダーに表示されます。このフォルダーは、[Server Objects] フォルダーにあります。データベース スコープの DDL トリガーは、[Database Triggers] フォルダーに表示されます。このフォルダーは対応するデータベースの [Programmability] フォルダーにあります。

ログオン トリガー

ログオン トリガーは、LOGON イベントに応答してストアド プロシージャを実行します。このイベントは、SQL Server インスタンスでユーザー セッションが確立されるときに発生します。ログオン トリガーは、ログインの認証段階が終了した後、ユーザー セッションが実際に確立されるまでの間に発生します。したがって、通常、エラー メッセージや PRINT ステートメントからのメッセージはユーザーに通知されますが、このトリガー内で発生したすべてのメッセージは SQL Server のエラー ログに記録されます。詳細については、「ログオン トリガー」を参照してください。

認証に失敗した場合は、ログオン トリガーが作動しません。

分散トランザクションはログオン トリガーではサポートされていません。分散トランザクションが含まれているログオン トリガーが起動されると、エラー 3969 が返されます。

ログオン トリガーの無効化

ログオン トリガーでは、sysadmin 固定サーバー ロールのメンバーを含むすべてのユーザーがデータベース エンジンに接続できないようにすることができます。ログオン トリガーによって接続が阻止された場合、sysadmin 固定サーバー ロールのメンバーは、専用管理者接続を使用するか、データベース エンジンを最小構成モード (-f) で起動することによって接続できます。詳細については、「SQL Server Management Studio で専用管理者接続を使用する方法」および「SQL Server サービスのスタートアップ オプションの使用」を参照してください。

トリガーについての留意事項

結果の返却

今後のバージョンの SQL Server では、トリガーを使用して結果を返す機能が削除される予定です。結果セットを返すトリガーは、それと連動するように設計されていないアプリケーションでは予期しない動作を起こすことがあります。新しい開発作業では、トリガーを使用して結果セットを返すことを避け、現在この方法を使用しているアプリケーションについては変更を検討してください。トリガーが結果セットを返さないようにするには、disallow results from triggers オプションを 1 に設定します。

ログオン トリガーは、結果セットを返すことを常に禁止しているため、この動作は構成できません。ログオン トリガーが結果セットを生成すると、トリガーは実行に失敗し、トリガーを起動したログイン試行は拒否されます。

複数のトリガー

SQL Server では、各 DML イベント、DDL イベント、または LOGON イベントに対して複数のトリガーを作成できます。たとえば、既に UPDATE トリガーが作成されているテーブルに対して CREATE TRIGGER FOR UPDATE を実行すると、追加の更新トリガーが作成されます。以前のバージョンの SQL Server では、各テーブルにおいて、INSERT、UPDATE、DELETE の各データ修正イベントに許可されるトリガーは 1 つだけでした。

再帰トリガー

SQL Server では、ALTER DATABASE によって RECURSIVE_TRIGGERS 設定が有効になっていれば、トリガーの再帰呼び出しが行えます。

再帰トリガーでは、次の種類の再帰呼び出しが有効になります。

  • 間接再帰

    間接再帰では、アプリケーションでテーブル T1 が更新されると、この操作によってトリガー TR1 が起動し、テーブル T2 が更新されます。この再帰呼び出しでは、次にトリガー T2 が起動し、テーブル T1 が更新されます。

  • 直接再帰

    直接再帰では、アプリケーションでテーブル T1 が更新されると、この操作によってトリガー TR1 が起動し、テーブル T1 が更新されます。テーブル T1 が更新されると、トリガー TR1 が再び起動するという動作が続きます。

次の例では、間接トリガー再帰と直接トリガー再帰の両方を使用します。ここでは、テーブル T1 で 2 つの更新トリガー TR1 と TR2 が定義されているとします。トリガー TR1 によって、テーブル T1 が再帰的に更新されます。UPDATE ステートメントでは、TR1 と TR2 が 1 回ずつ実行されます。さらに、TR1 が実行されると、TR1 (再帰的) と TR2 が起動します。トリガーの inserted テーブルと deleted テーブルには、そのトリガーを呼び出した UPDATE ステートメントのみに対応する行が格納されています。

注意

この動作は、ALTER DATABASE によって RECURSIVE_TRIGGERS 設定が有効になっている場合にのみ実行されます。あるイベントに対して複数のトリガーが定義されている場合、それらの実行順序に決まりはありません。個々のトリガーは自己完結している必要があります。

RECURSIVE_TRIGGERS の設定を無効にすると、直接再帰のみが無効になります。間接再帰呼び出しを無効にするには、sp_configure を使用して、サーバー オプション nested triggers を 0 に設定します。

いずれかのトリガーで ROLLBACK TRANSACTION が実行されると、入れ子レベルにかかわらず、それ以降のトリガーは実行されません。

入れ子にされたトリガー

トリガーは 32 レベルまで入れ子にできます。トリガーによって、別のトリガーが存在するテーブルが変更された場合、この 2 番目のトリガーがアクティブになり、さらに別のトリガーを呼び出すことができます。この連鎖的なトリガーで無限ループが発生すると、入れ子レベルを超過した時点でトリガーは取り消されます。Transact-SQL トリガーで、CLR ルーチン、データ型、または集計を参照することによってマネージ コードが実行された場合、この参照は 32 レベルの入れ子制限の 1 レベルとしてカウントされます。マネージ コード内から呼び出されたメソッドは、この制限としてはカウントされません。

入れ子にされたトリガーを無効にするには、sp_configure の nested triggers オプションを 0 (オフ) に設定します。既定の構成では、入れ子にされたトリガーは許可されています。nested triggers がオフの場合、ALTER DATABASE によって RECURSIVE_TRIGGERS がどのように設定されていても、recursive triggers は無効になります。

注意

SQL Server 2000 では、INSTEAD OF トリガー内で入れ子になった AFTER トリガーは、nested triggers サーバー構成オプションがオフになっていれば起動されません。SQL Server 2005 以降では、INSTEAD OF トリガー内で入れ子になっている最初の AFTER トリガーは、nested triggers サーバー構成オプションが 0 に設定されていても起動されます。ただし、この設定では、後続の AFTER トリガーは起動されません。アプリケーションに入れ子になったトリガーがないかどうかを調査し、nested triggers サーバー構成オプションが 0 に設定されている場合の動作に関して、アプリケーションがビジネス ルールに従っているかどうかを判断し、その後、適切な変更を加えることをお勧めします。

名前の遅延解決

SQL Server では、Transact-SQL のストアド プロシージャ、トリガー、バッチで、コンパイル時に存在しないテーブルを参照できます。この機能を名前の遅延解決といいます。ただし、Transact-SQL のストアド プロシージャ、トリガー、またはバッチで、ストアド プロシージャまたはトリガーで定義されているテーブルを参照する場合は、互換性レベルが 65 に設定されている場合にのみ作成時に警告が発生します。バッチが使用される場合は、コンパイル時に警告が発生します。参照されるテーブルが存在しない場合は、実行時にエラー メッセージが返されます。詳細については、「名前の遅延解決とコンパイル」を参照してください。

権限

DML トリガーを作成するには、トリガーを作成するテーブルまたはビューに対する ALTER 権限が必要です。

サーバー スコープ (ON ALL SERVER) の DDL トリガー、またはログオン トリガーを作成するには、サーバーに対する CONTROL SERVER 権限が必要です。データベース スコープ (ON DATABASE) の DDL トリガーを作成するには、現在のデータベースに対する ALTER ANY DATABASE DDL TRIGGER 権限が必要です。

A. DML トリガーを事前通知と組み合わせて使用する

次の DML トリガーでは、Customer テーブルでデータの追加または変更が試行されたときに、クライアントに対してメッセージを表示します。

USE AdventureWorks2008R2;
GO
IF OBJECT_ID ('Sales.reminder1', 'TR') IS NOT NULL
   DROP TRIGGER Sales.reminder1;
GO
CREATE TRIGGER reminder1
ON Sales.Customer
AFTER INSERT, UPDATE 
AS RAISERROR ('Notify Customer Relations', 16, 10);
GO

B. DML トリガーを電子メール メッセージと組み合わせて使用する

次の例では、Customer テーブルが変更されたときに、指定したユーザー (MaryM) に電子メールを送信します。

USE AdventureWorks2008R2;
GO
IF OBJECT_ID ('Sales.reminder2','TR') IS NOT NULL
    DROP TRIGGER Sales.reminder2;
GO
CREATE TRIGGER reminder2
ON Sales.Customer
AFTER INSERT, UPDATE, DELETE 
AS
   EXEC msdb.dbo.sp_send_dbmail
        @profile_name = 'AdventureWorks2008R2 Administrator',
        @recipients = 'danw@Adventure-Works.com',
        @body = 'Don''t forget to print a report for the sales force.',
        @subject = 'Reminder';
GO

C. DML AFTER トリガーを使用して、PurchaseOrderHeader テーブルと Vendor テーブルの間にビジネス ルールを設定する

CHECK 制約では、列レベルまたはテーブル レベルの制約が定義されている列だけを参照できるので、テーブル間にまたがる制約 (ここでは、ビジネス ルール) はすべてトリガーとして定義する必要があります。

次の例では、DML トリガーを作成します。このトリガーでは、PurchaseOrderHeader テーブルに新しい発注を挿入しようとしたときに、ベンダーの信用格付けが良好であるかどうかがチェックされます。ベンダーの信用格付けを取得するには、Vendor テーブルを参照する必要があります。信用格付けが低い場合は、メッセージが表示され、挿入は実行されません。

注意

複数の行を更新する DML AFTER トリガーの例については、「DML トリガーの複数行に関する注意点」を参照してください。DML INSTEAD OF INSERT トリガーの例については、「INSTEAD OF INSERT トリガー」を参照してください。

USE AdventureWorks2008R2;
GO
IF OBJECT_ID ('Purchasing.LowCredit','TR') IS NOT NULL
   DROP TRIGGER Purchasing.LowCredit;
GO
-- This trigger prevents a row from being inserted in the Purchasing.PurchaseOrderHeader table
-- when the credit rating of the specified vendor is set to 5 (below average).

CREATE TRIGGER Purchasing.LowCredit ON Purchasing.PurchaseOrderHeader
AFTER INSERT
AS
IF EXISTS (SELECT *
           FROM Purchasing.PurchaseOrderHeader p 
           JOIN inserted AS i 
           ON p.PurchaseOrderID = i.PurchaseOrderID 
           JOIN Purchasing.Vendor AS v 
           ON v.BusinessEntityID = p.VendorID
           WHERE v.CreditRating = 5
          )
BEGIN
RAISERROR ('A vendor''s credit rating is too low to accept new purchase orders.', 16, 1);
ROLLBACK TRANSACTION;
RETURN 
END;

GO
-- This statement attempts to insert a row into the PurchaseOrderHeader table
-- for a vendor that has a below average credit rating.
-- The AFTER INSERT trigger is fired and the INSERT transaction is rolled back.

INSERT INTO Purchasing.PurchaseOrderHeader (RevisionNumber, Status, EmployeeID,
VendorID, ShipMethodID, OrderDate, ShipDate, SubTotal, TaxAmt, Freight)
VALUES(
2
,3
,261    
,1652   
,4  
,GETDATE()
,GETDATE()
,44594.55   
,3567.564   
,1114.8638);
GO

D. データベース スコープの DDL トリガーを使用する

次の例では、DDL トリガーを使用して、データベースのシノニムが削除されないようにします。

USE AdventureWorks2008R2;
GO
IF EXISTS (SELECT * FROM sys.triggers
    WHERE parent_class = 0 AND name = 'safety')
DROP TRIGGER safety
ON DATABASE;
GO
CREATE TRIGGER safety 
ON DATABASE 
FOR DROP_SYNONYM
AS 
   RAISERROR ('You must disable Trigger "safety" to drop synonyms!',10, 1)
   ROLLBACK
GO
DROP TRIGGER safety
ON DATABASE;
GO

E. サーバー スコープの DDL トリガーを使用する

次の例では、DDL トリガーを使用して、現在のサーバー インスタンスで CREATE DATABASE イベントが発生したときにメッセージを表示し、EVENTDATA 関数を使用して、対応する Transact-SQL ステートメントのテキストを取得します。

注意

DDL トリガーで EVENTDATA を使用するその他の例については、「EVENTDATA 関数の使用」を参照してください。

IF EXISTS (SELECT * FROM sys.server_triggers
    WHERE name = 'ddl_trig_database')
DROP TRIGGER ddl_trig_database
ON ALL SERVER;
GO
CREATE TRIGGER ddl_trig_database 
ON ALL SERVER 
FOR CREATE_DATABASE 
AS 
    PRINT 'Database Created.'
    SELECT EVENTDATA().value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]','nvarchar(max)')
GO
DROP TRIGGER ddl_trig_database
ON ALL SERVER;
GO

F. ログオン トリガーを使用する

次のログオン トリガーの例では、login_test ログインで既に 3 つのユーザー セッションが実行されている場合に、そのログインのメンバーとして SQL Server にログインを試行すると拒否されます。

USE master;
GO
CREATE LOGIN login_test WITH PASSWORD = '3KHJ6dhx(0xVYsdf' MUST_CHANGE,
    CHECK_EXPIRATION = ON;
GO
GRANT VIEW SERVER STATE TO login_test;
GO
CREATE TRIGGER connection_limit_trigger
ON ALL SERVER WITH EXECUTE AS 'login_test'
FOR LOGON
AS
BEGIN
IF ORIGINAL_LOGIN()= 'login_test' AND
    (SELECT COUNT(*) FROM sys.dm_exec_sessions
            WHERE is_user_process = 1 AND
                original_login_name = 'login_test') > 3
    ROLLBACK;
END;

G. トリガーを起動するイベントを表示する

次の例では、sys.triggers および sys.trigger_events カタログ ビューをクエリし、どの Transact-SQL 言語イベントでトリガー safety が起動されるかを特定します。safety は前の例で作成したものです。

SELECT TE.*
FROM sys.trigger_events AS TE
JOIN sys.triggers AS T
ON T.object_id = TE.object_id
WHERE T.parent_class = 0
AND T.name = 'safety'
GO

関連項目

参照

概念