ヘッダーをスキップ

Oracle Database 概要
10gリリース2(10.2)

B19215-02
目次
目次
索引
索引

戻る 次へ

22 トリガー

この章では、データベース・トリガーについて説明します。データベース・トリガーとは、PL/SQLまたはJavaでデータベースに格納されているプロシージャであり、表またはビューが変更された場合、あるいはなんらかのユーザー・アクションやデータベース・システム・アクションが発生した場合に、暗黙的に実行(起動)されます。

この章の内容は、次のとおりです。

トリガーの概要

次の操作が発生した場合に起動するトリガーを記述できます。

  1. 発行するユーザーを問わず、特定の表またはビューに対するDML文(INSERTUPDATEDELETE

  2. データベース内の特定または任意のスキーマやユーザーが発行するDDL文(主にCREATEまたはALTER

  3. データベース内の特定または任意のスキーマやユーザーが発行する、ログオンやログオフ、エラーまたは起動や停止などのデータベース・イベント

トリガーは、ストアド・プロシージャに似ています。データベースに格納されているトリガーには、1単位として実行可能なSQLやPL/SQL文を格納でき、また、トリガーは他のストアド・プロシージャを起動できます。ただし、トリガーとプロシージャとでは、起動する方法が異なります。プロシージャは、ユーザー、アプリケーションまたはトリガーによって明示的に実行されます。トリガーは、接続ユーザーや使用中のアプリケーションに関係なく、トリガー・イベントが発生した時点で暗黙的に起動されます。

図22-1に示すデータベース・アプリケーションには、データベースに格納された複数のトリガーを暗黙のうちに起動するSQL文がいくつか含まれています。データベースには、トリガーとそれに対応付けられている表が別々に格納されていることに注目してください。

図 22-1    トリガー


画像の説明

また、トリガーはCプロシージャをコールアウトし、計算集中型の操作に使用できます。

トリガーを起動するイベントは、次のとおりです。

トリガーの使用方法

トリガーはOracleの標準機能を補い、高度にカスタマイズされたデータベース管理システムを提供します。たとえば、トリガーによって、表に対するDML操作を通常の業務時間内のみに制限できます。トリガーには、その他に次のような使用方法があります。

トリガーの使用上の注意

トリガーはデータベースのカスタマイズに使用すると便利ですが、必要な場合にのみ使用してください。トリガーを使用しすぎると相互依存性が複雑になるため、大規模アプリケーションのメンテナンスが困難になります。たとえば、トリガーが起動すると、そのトリガー・アクションに含まれるSQL文によって他のトリガーが起動され、トリガーが連鎖状態になることがあります。これにより、意図しない影響を生じるおそれがあります。図22-2に、この状態を示します。

図 22-2    連鎖的なトリガー


画像の説明

トリガーと宣言整合性制約との比較

トリガーと整合性制約を併用すると、任意の整合性規則を定義して規定できます。ただし、トリガーを使用してデータ入力に制約を適用するのは、次の場合に限定してください。

トリガーの各部分

トリガーには次の3つの基本部分があります。

図22-3に、トリガーの各部分を示します。この図は、正確な構文を示すためのものではありません。トリガーの各部分については、この後で詳しく説明します。

図 22-3    REORDERトリガー


画像の説明

トリガー・イベントまたはトリガーを実行する文

トリガー・イベントまたはトリガーを実行する文とは、トリガーを起動させるSQL文、データベース・イベントまたはユーザー・イベントのことです。トリガー・イベントは、次に示すものの1つ以上からなります。

たとえば、図22-3のトリガーを実行する文は次のとおりです。

... UPDATE OF parts_on_hand ON inventory ... 

この文は、inventory表のparts_on_hand列を更新すると、トリガーが起動することを意味します。なお、トリガー・イベントがUPDATE文の場合は、どの列が更新されるとトリガーが起動されるかを示す列リストを指定できます。INSERT文とDELETE文では情報行全体が処理の対象になるため、それらの文には列のリストを指定できません。

トリガー・イベントには、次のように複数のSQL文を指定できます。

... INSERT OR UPDATE OR DELETE OF inventory ... 

この場合、inventory表に対してINSERTUPDATEまたはDELETE文を発行すると、トリガーが起動されます。複数のタイプのSQL文でトリガーが起動される場合は、条件述語を使用して、トリガーを実行する文のタイプを検出できます。これにより、トリガーを起動した文のタイプに応じて異なるコードを実行するトリガーを作成できます。

トリガー制限

トリガー制限にはブール式を指定します。トリガーが起動されるには、このブール式がtrueになる必要があります。トリガー制限の評価がfalseまたはunknownになった場合、トリガー・アクションは実行されません。この例では、次のようにしてトリガーを制限しています。

new.parts_on_hand < new.reorder_point 

この場合、引当可能部品の数量が現行の再発注数量より少なくなるまで、トリガーは起動しません。

トリガー・アクション

トリガー・アクションは、SQL文またはコードを含むプロシージャ(PL/SQLブロック、JavaプログラムまたはCコールアウト)です。これらのSQL文やコードは、次のイベントが発生すると実行されます。

ストアド・プロシージャと同様に、トリガー・アクションでは次のことが可能です。

トリガーが行トリガーの場合、トリガー・アクション内の文から、トリガーによって処理されている行の列値にアクセスできます。各列の古い値と新しい値には、相関名によってアクセスできます。

トリガーのタイプ

この項では、様々なタイプのトリガーについて説明します。

行トリガーと文トリガー

トリガーを定義するときに、次のようにトリガー・アクションの実行回数を指定できます。

行トリガー

行トリガーは、表がトリガーを実行する文の処理の影響を受けるたびに実行されます。たとえば、UPDATE文が表の複数の行を更新した場合、UPDATE文が処理する行ごとに1つずつ行トリガーが起動されます。トリガーを実行する文の影響を受ける行がなければ、行トリガーは実行されません。

トリガー・アクションのコードが、トリガーを実行する文によって供給されるデータまたは影響を受ける行数に依存する場合には、行トリガーが便利です。たとえば、図22-3は、トリガーを実行する文の影響を受ける各行の値を使用する行トリガーの一例です。

文トリガー

文トリガーは、トリガーを実行する文の影響を受ける表の行数とは関係なく、また、影響を受ける行がない場合にも、トリガーを実行する文の実行ごとに1回起動されます。たとえば、DELETE文が表の複数の行を削除すると、文レベルのDELETEトリガーが1回のみ起動されます。

トリガー・アクションのコードが、トリガーを実行する文によって供給されるデータや、影響を受ける行に依存しない場合には、文トリガーが便利です。文トリガーの使用例を次に示します。

BEFOREトリガーとAFTERトリガー

トリガーを定義するときに、トリガーのタイミングを指定できます。これは、トリガー・アクションを、トリガーを実行する文の前に実行するのか、後に実行するのかを指定するものです。 BEFOREAFTERは、文トリガーと行トリガーの両方に適用されます。

DML文によって起動されるBEFOREトリガーとAFTERトリガーは表にのみ定義でき、ビューには定義できません。ただし、ビューに対してINSERTUPDATEまたはDELETE文を発行すると、そのビューの実表のトリガーが起動されます。DDL文によって起動されるBEFOREトリガーとAFTERトリガーは、データベースまたはスキーマにのみ定義でき、特定の表には定義できません。

関連項目

 

BEFOREトリガー

BEFOREトリガーは、トリガー文の実行前にトリガー・アクションを実行します。このタイプのトリガーは、次のような場合によく使用します。

AFTERトリガー

AFTERトリガーは、トリガー文の実行後にトリガー・アクションを実行します。

トリガー・タイプの組合せ

これまでに説明したオプションを使用して、次の4タイプの行トリガーと文トリガーを作成できます。

ある表に対する1つの文に、同じタイプのトリガーを複数指定できます。たとえば、employees表のUPDATE文に対してBEFORE文トリガーを2つ指定できます。同じタイプのトリガーを複数指定することにより、同じ表に対してトリガーを持つ複数のアプリケーションをモジュール化してインストールできます。また、Oracleマテリアライズド・ビュー・ログはAFTER行トリガーを使用するため、Oracleによって定義されるAFTER行トリガーに加えて、ユーザー独自のAFTER行トリガーを設計できます。

各種DML文(INSERTUPDATEまたはDELETE)に対して、前述のトリガーを必要な数だけ作成できます。

関連項目

トリガーの適用例は、『Oracle Databaseアプリケーション開発者ガイド - 基礎編』を参照してください。 

INSTEAD OFトリガー

INSTEAD OFトリガーを使用すると、DML文(INSERTUPDATEおよびDELETE)で直接変更できないビューを透過的に変更できるようになります。他のタイプのトリガーとは異なり、Oracleはトリガー文を実行するかわりにこのトリガーを起動するため、このようなトリガーをINSTEAD OFトリガーと呼びます。

通常のINSERTUPDATEおよびDELETE文をビューに対して記述し、それに応じて基礎となる表が更新されるようにINSTEAD OFトリガーを起動させることができます。INSTEAD OFトリガーは、変更があったビューの行ごとにアクティブ化されます。

ビューの変更

ビューを変更する操作では、次のように曖昧な結果を生じることがあります。

オブジェクト・ビューには、その他にも問題があります。たとえば、オブジェクト・ビューの主な使用方法は、マスターとディテールの関連を表すことです。この操作で結合が関係してくるのは避けられませんが、結合の変更は本質的に曖昧です。

その結果、変更可能なビューについては、たくさんの制限事項があります。INSTEAD OFトリガーは、それ以外の手段では変更できないリレーショナル・ビューのみでなく、オブジェクト・ビューに対しても使用できます。

INSTEAD OFトリガーを使用せずにデータを挿入、更新または削除でき、かつ後述の条件に一致する場合、このビューは本質的に変更可能です。ビューが本来は変更可能であっても、挿入、更新または削除する値の妥当性検査を実行する必要があります。この場合にも、INSTEAD OFトリガーを使用できます。変更される行の妥当性チェックがトリガー・コードによって実行され、有効であれば、基礎となる表に変更が伝播されます。

INSTEAD OFトリガーにより、OCIを使用してクライアント側のオブジェクト・ビューのインスタンスを変更することもできます。オブジェクト・ビューによって具体化されたオブジェクトを、クライアント側のオブジェクト・キャッシュ内で変更し、それを永続的な格納領域にフラッシュ・バックするには、オブジェクト・ビューが変更可能でない場合は、INSTEAD OFトリガーを指定する必要があります。ただし、単にオブジェクト・キャッシュ内のビュー・オブジェクトを確保して読み込む場合、これらのトリガーを定義する必要はありません。

関連項目

 

変更不可能なビュー

ビュー問合せに次の構成メンバーが含まれている場合、そのビューは本質的に変更不可能であるため、そのビューに対しては挿入、更新または削除を実行できません。

ビューに疑似列または式が含まれる場合、そのビューを更新する唯一の方法は、その疑似列または式を参照しないUPDATE文を使用することです。

関連項目

「更新可能な結合ビュー」 

ネストした表に対するINSTEAD OFトリガー

ビュー内のネストした表の列の要素は、TABLE句で直接変更することはできません。ただし、ビューのネストした表の列にINSTEAD OFトリガーを定義すると、要素を変更できます。ネストした表のトリガーは、その表の要素が更新、挿入または削除すると起動し、基礎となる表に対する実際の変更を処理します。

関連項目

  • 『Oracle Databaseアプリケーション開発者ガイド - 基礎編』

  • CREATE TRIGGER文の詳細は、『Oracle Database SQLリファレンス』を参照してください。

 

システム・イベントとユーザー・イベントのトリガー

トリガーを使用すると、データベース・イベントに関する情報を、サブスクライバに対して発行できます。アプリケーションは、他のアプリケーションからのメッセージにサブスクライブするのと同様に、データベース・イベントにサブスクライブできます。これらのデータベース・イベントは、次のとおりです。

システム・イベントのトリガーは、データベース・レベルまたはスキーマ・レベルで定義できます。DBMS_AQパッケージは、特定のアクションを実行するデータベース・トリガーの使用例です。たとえば、データベース停止トリガーは、データベース・レベルで次のように定義します。

CREATE TRIGGER register_shutdown 
  ON DATABASE 
  SHUTDOWN 
    BEGIN 
    ...
    DBMS_AQ.ENQUEUE(...); 
    ... 
    END;     

DDL文またはログオン・イベントおよびログオフ・イベントのトリガーも、データベース・レベルまたはスキーマ・レベルで定義できます。DML文のトリガーは、表またはビューに定義できます。データベース・レベルで定義されたトリガーはすべてのユーザーに対して起動し、スキーマ・レベルまたは表レベルで定義されたトリガーは、トリガー・イベントがそのスキーマまたは表に関連する場合にのみ起動します。

イベントの発行

イベントの発行では、Oracle Streamsのアドバンスト・キューイングのパブリッシュ/サブスクライブ・メカニズムが使用されます。キューは、各種サブスクライバに必要な主題を含むメッセージ・リポジトリの役割を果たします。トリガーは、特定のシステム・イベントまたはユーザー・イベントの発生時に、DBMS_AQパッケージを使用してメッセージをエンキューします。

関連項目

  • 『Oracle Streamsアドバンスト・キューイング・ユーザーズ・ガイドおよびリファレンス』

  • 『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』

 

イベントの属性

各イベントでは、トリガー・テキスト内で属性を使用できます。たとえば、データベース起動および停止トリガーは、インスタンス番号およびデータベース名の属性を持ち、ログオン・トリガーおよびログオフ・トリガーは、ユーザー名の属性を持ちます。属性をイベント発生時に発行する場合は、トリガーの作成時に、その属性と同じ名前のファンクションを指定できます。属性値は、トリガーの起動時にファンクションまたはペイロードに渡されます。DML文のトリガーの場合は、:OLD列の値によって属性値が:NEW列の値に渡されます。

システム・イベント

トリガーを起動できるシステム・イベントは、インスタンスの起動と停止およびエラー・メッセージに関連しています。起動および停止イベントに対して作成するトリガーは、データベースに対応付ける必要があります。エラー・イベントに対して作成するトリガーは、データベースまたはスキーマに対応付けることができます。

ユーザー・イベント

トリガーを起動できるユーザー・イベントは、ユーザー・ログオンとログオフ、DDL文およびDML文に関連しています。

LOGONイベントおよびLOGOFFイベントのトリガー

LOGONトリガーおよびLOGOFFトリガーは、データベースまたはスキーマに対応付けることができます。その属性には、システム・イベントとユーザー名があり、USERIDUSERNAMEについて簡単な条件を指定できます。

DDL文のトリガー

DDLトリガーは、データベースまたはスキーマに対応付けることができます。その属性には、システム・イベント、スキーマ・オブジェクトのタイプおよび名前があります。ここでは、スキーマ・オブジェクトの型と名前のみでなく、USERIDUSERNAMEなどのファンクションについても簡単な条件を指定できます。DDLトリガーには、次のタイプのトリガーがあります。

DML文のトリガー

イベント発行用のDMLトリガーは、表に対応付けられます。指定したDML操作が発生する各行に対して起動するように、BEFOREトリガーまたはAFTERトリガーを使用できます。DML文に関連するイベントの発行には、INSTEAD OFトリガーを使用できません。かわりに、INSTEAD OFトリガーによってビューの基礎となる表に生じるDML操作について、BEFOREトリガーまたはAFTERトリガーを使用してイベントを発行できます。

イベント発行用のDMLトリガーの属性には、システム・イベントと、SELECTリストにユーザーが定義する列があります。これにより、スキーマ・オブジェクトの型と名前のみでなく、ファンクション(UIDUSERUSERENVおよびSYSDATE)、疑似列および列についても、簡単な条件を指定できます。列には、接頭辞として新旧の値を示す:OLD:NEWを使用できます。DML文のトリガーを次に示します。

トリガーの実行

トリガーには次の2つのモードがあります。

トリガーのモード  定義 

使用可能 

使用可能にされているトリガーは、トリガーを実行する文が発行され、トリガー条件(指定されている場合)の評価がTRUEである場合に、そのトリガー・アクションを実行します。  

使用禁止

 

使用禁止にされているトリガーは、トリガーを実行する文が発行され、トリガー条件(指定されている場合)の評価がTRUEであっても、そのトリガー・アクションを実行しません。  

使用可能なトリガーの場合、Oracleは次の処理を自動的に行います。

トリガーの実行モデルと整合性制約のチェック

1つのSQL文は、最大4種類のトリガーを起動します。

トリガーを実行する文またはトリガー内の文によって、1つ以上の整合性制約のチェックが実施されます。またトリガーには、他のトリガーを起動する文を含めることもできます(連鎖的なトリガー)。

Oracleでは、次の実行モデルを使用して、複数のトリガーと制約チェックの適切な起動順序を維持します。

  1. その文に適用されるすべてのBEFORE文トリガーを実行します。

  2. そのSQL文の影響を受ける各行をループします。

    1. その文に適用されるすべてのBEFORE行トリガーを実行します。

    2. 行をロックして変更し、整合性制約チェックを実施します。(トランザクションがコミットされるまでロックは解除されません)。

    3. その文に適用されるすべてのAFTER行トリガーを実行します。

  3. 遅延整合性制約チェックを完了します。

  4. その文に適用されるすべてのAFTER文トリガーを実行します。

実行モデルの定義は再帰的です。たとえば、あるSQL文によってBEFORE行トリガーを起動し、整合性制約をチェックできます。次に、このBEFORE行トリガーが実行する更新によって、整合性制約をチェックし、AFTER文トリガーを起動できます。このAFTER文トリガーによって、整合性制約がチェックされます。この場合、実行モデルでは、次の処理が再帰的に繰り返し実行されます。

元のSQL文が発行されます。

  1. BEFORE行トリガーが起動されます。

    1. BEFORE行トリガー内のUPDATE文により、AFTER文トリガーが起動します。

      i. AFTER文トリガーの文が実行されます。

      ii. AFTER文トリガーによって変更された表の整合性制約がチェックされます。

    2. BEFORE行トリガーの文が実行されます。

    3. BEFORE行トリガーによって変更された表の整合性制約がチェックされます。

  2. SQL文が実行されます。

  3. SQL文から整合性制約がチェックされます。

この再帰には、次の2つの例外があります。

実行モデルの重要なプロパティは、SQL文の結果として実行されるアクションとチェックがすべて成功する必要があることです。トリガー内で発生した例外を明示的に処理できない場合、元のSQL文によって実行されたすべてのアクションが、起動されたトリガーによって実行されたアクションを含めて、ロールバックされます。したがって、トリガーが整合性制約に違反することはありません。実行モデルは整合性制約を考慮し、宣言整合性制約に違反するトリガーを認めません。

たとえば、前述の使用例で整合性制約に違反があったとします。その違反の結果として、SQL文によるすべての変更、起動されたBEFORE行トリガーおよび起動されたAFTER文トリガーがロールバックされます。


注意

各種トリガーは特定の順序で起動されますが、同じ文に対する同じタイプのトリガーは、特定の順序で起動されるとはかぎりません。たとえば、1つのUPDATE文に対して定義されているBEFORE行トリガーすべてが、毎回同じ順序で起動されるとはかぎりません。同じタイプのトリガーが複数ある場合は、その起動順序に依存しないようアプリケーションを設計してください。 


トリガーのデータ・アクセス

トリガーが起動されると、トリガー・アクション内で参照される表は、他のユーザーのトランザクション内のSQL文によって変更されている最中である可能性があります。トリガー内で実行されるSQL文は、常に単独のSQL文と同じ規則に従います。起動されたトリガーが読取り(問合せ)または書込み(更新)の対象にする値が、まだコミットされていないトランザクションによって変更されたものである場合、起動されたトリガーの本体にあるSQL文は、次のガイドラインに従います。

PL/SQLトリガーの記憶域

PL/SQLトリガーは、ストアド・プロシージャと同じように、コンパイル済の形式で格納されます。CREATE TRIGGER文がコミットされると、Pコード(疑似コード)と呼ばれるコンパイル済PL/SQLコードがデータベースに格納され、トリガーのソース・コードは共有プールからフラッシュされます。

関連項目

PL/SQLコードのコンパイルと格納の詳細は、『Oracle Database PL/SQLユーザーズ・ガイドおよびリファレンス』を参照してください。 

トリガーの実行

Oracleは、プロシージャの実行と同じ手順を使用してトリガーを内部的に実行します。両者の唯一の違いは、ユーザーがトリガー文を実行する権限を持っていれば、トリガーを起動する権限が付与されることです。この点を除けば、トリガーはストアド・プロシージャと同じ方法でチェックされ、実行されます。

関連項目

ストアド・プロシージャの詳細は、『Oracle Database PL/SQLユーザーズ・ガイドおよびリファレンス』を参照してください。 

トリガーの依存性のメンテナンス

プロシージャと同様に、トリガーも参照しているオブジェクトに依存します。トリガー・アクションで参照されるスキーマ・オブジェクトに対するトリガーの依存性は、Oracleによって自動的に管理されます。トリガーの依存性についての問題は、ストアド・プロシージャの依存性についての問題と同じです。トリガーは、ストアド・プロシージャと同様に扱われます。これらは、データ・ディクショナリに挿入されます。

関連項目

第6章「スキーマ・オブジェクト間の依存性」 


戻る 次へ
Oracle
Copyright © 2006 Oracle Corporation.

All Rights Reserved.
目次
目次
索引
索引