| Oracle Database 概要 10gリリース2(10.2) B19215-02 |
|
この章では、データベース・トリガーについて説明します。データベース・トリガーとは、PL/SQLまたはJavaでデータベースに格納されているプロシージャであり、表またはビューが変更された場合、あるいはなんらかのユーザー・アクションやデータベース・システム・アクションが発生した場合に、暗黙的に実行(起動)されます。
この章の内容は、次のとおりです。
次の操作が発生した場合に起動するトリガーを記述できます。
INSERT、UPDATE、DELETE)
CREATEまたはALTER)
トリガーは、ストアド・プロシージャに似ています。データベースに格納されているトリガーには、1単位として実行可能なSQLやPL/SQL文を格納でき、また、トリガーは他のストアド・プロシージャを起動できます。ただし、トリガーとプロシージャとでは、起動する方法が異なります。プロシージャは、ユーザー、アプリケーションまたはトリガーによって明示的に実行されます。トリガーは、接続ユーザーや使用中のアプリケーションに関係なく、トリガー・イベントが発生した時点で暗黙的に起動されます。
図22-1に示すデータベース・アプリケーションには、データベースに格納された複数のトリガーを暗黙のうちに起動するSQL文がいくつか含まれています。データベースには、トリガーとそれに対応付けられている表が別々に格納されていることに注目してください。
また、トリガーはCプロシージャをコールアウトし、計算集中型の操作に使用できます。
トリガーを起動するイベントは、次のとおりです。
トリガーはOracleの標準機能を補い、高度にカスタマイズされたデータベース管理システムを提供します。たとえば、トリガーによって、表に対するDML操作を通常の業務時間内のみに制限できます。トリガーには、その他に次のような使用方法があります。
トリガーはデータベースのカスタマイズに使用すると便利ですが、必要な場合にのみ使用してください。トリガーを使用しすぎると相互依存性が複雑になるため、大規模アプリケーションのメンテナンスが困難になります。たとえば、トリガーが起動すると、そのトリガー・アクションに含まれるSQL文によって他のトリガーが起動され、トリガーが連鎖状態になることがあります。これにより、意図しない影響を生じるおそれがあります。図22-2に、この状態を示します。
トリガーと整合性制約を併用すると、任意の整合性規則を定義して規定できます。ただし、トリガーを使用してデータ入力に制約を適用するのは、次の場合に限定してください。
トリガーには次の3つの基本部分があります。
図22-3に、トリガーの各部分を示します。この図は、正確な構文を示すためのものではありません。トリガーの各部分については、この後で詳しく説明します。
トリガー・イベントまたはトリガーを実行する文とは、トリガーを起動させるSQL文、データベース・イベントまたはユーザー・イベントのことです。トリガー・イベントは、次に示すものの1つ以上からなります。
INSERT、UPDATEまたはDELETE文
CREATE、ALTERまたはDROP文
たとえば、図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表に対してINSERT、UPDATEまたは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は、文トリガーと行トリガーの両方に適用されます。
DML文によって起動されるBEFOREトリガーとAFTERトリガーは表にのみ定義でき、ビューには定義できません。ただし、ビューに対してINSERT、UPDATEまたはDELETE文を発行すると、そのビューの実表のトリガーが起動されます。DDL文によって起動されるBEFOREトリガーとAFTERトリガーは、データベースまたはスキーマにのみ定義でき、特定の表には定義できません。
|
関連項目
|
BEFOREトリガーは、トリガー文の実行前にトリガー・アクションを実行します。このタイプのトリガーは、次のような場合によく使用します。
BEFOREトリガーを使用することにより、トリガー・アクションで例外が発生した場合に、トリガー文で無駄な処理を実行して結果的にロールバックすることになるのを避けられます。
INSERTまたはUPDATE文を実行する前に、特定の列値を調べる場合。
AFTERトリガーは、トリガー文の実行後にトリガー・アクションを実行します。
これまでに説明したオプションを使用して、次の4タイプの行トリガーと文トリガーを作成できます。
トリガー文を実行する前にトリガー・アクションが実行されます。
トリガーを実行する文の影響を受ける各行が修正され、該当する整合性制約の検査の前に、トリガー条件に違反していないかぎりトリガー・アクションが実行されます。
トリガー文を実行し、遅延整合性制約を適用した後に、トリガー・アクションが実行されます。
トリガーを実行する文の影響を受ける各行が修正され、該当する整合性制約が適用された後で、トリガー制限に違反していないかぎり現在行に対してトリガー・アクションが実行されます。BEFORE行トリガーと異なり、AFTER行トリガーは、行をロックします。
ある表に対する1つの文に、同じタイプのトリガーを複数指定できます。たとえば、employees表のUPDATE文に対してBEFORE文トリガーを2つ指定できます。同じタイプのトリガーを複数指定することにより、同じ表に対してトリガーを持つ複数のアプリケーションをモジュール化してインストールできます。また、Oracleマテリアライズド・ビュー・ログはAFTER行トリガーを使用するため、Oracleによって定義されるAFTER行トリガーに加えて、ユーザー独自のAFTER行トリガーを設計できます。
各種DML文(INSERT、UPDATEまたはDELETE)に対して、前述のトリガーを必要な数だけ作成できます。
INSTEAD OFトリガーを使用すると、DML文(INSERT、UPDATEおよびDELETE)で直接変更できないビューを透過的に変更できるようになります。他のタイプのトリガーとは異なり、Oracleはトリガー文を実行するかわりにこのトリガーを起動するため、このようなトリガーをINSTEAD OFトリガーと呼びます。
通常のINSERT、UPDATEおよびDELETE文をビューに対して記述し、それに応じて基礎となる表が更新されるようにINSTEAD OFトリガーを起動させることができます。INSTEAD OFトリガーは、変更があったビューの行ごとにアクティブ化されます。
ビューを変更する操作では、次のように曖昧な結果を生じることがあります。
オブジェクト・ビューには、その他にも問題があります。たとえば、オブジェクト・ビューの主な使用方法は、マスターとディテールの関連を表すことです。この操作で結合が関係してくるのは避けられませんが、結合の変更は本質的に曖昧です。
その結果、変更可能なビューについては、たくさんの制限事項があります。INSTEAD OFトリガーは、それ以外の手段では変更できないリレーショナル・ビューのみでなく、オブジェクト・ビューに対しても使用できます。
INSTEAD OFトリガーを使用せずにデータを挿入、更新または削除でき、かつ後述の条件に一致する場合、このビューは本質的に変更可能です。ビューが本来は変更可能であっても、挿入、更新または削除する値の妥当性検査を実行する必要があります。この場合にも、INSTEAD OFトリガーを使用できます。変更される行の妥当性チェックがトリガー・コードによって実行され、有効であれば、基礎となる表に変更が伝播されます。
INSTEAD OFトリガーにより、OCIを使用してクライアント側のオブジェクト・ビューのインスタンスを変更することもできます。オブジェクト・ビューによって具体化されたオブジェクトを、クライアント側のオブジェクト・キャッシュ内で変更し、それを永続的な格納領域にフラッシュ・バックするには、オブジェクト・ビューが変更可能でない場合は、INSTEAD OFトリガーを指定する必要があります。ただし、単にオブジェクト・キャッシュ内のビュー・オブジェクトを確保して読み込む場合、これらのトリガーを定義する必要はありません。
|
関連項目
|
ビュー問合せに次の構成メンバーが含まれている場合、そのビューは本質的に変更不可能であるため、そのビューに対しては挿入、更新または削除を実行できません。
ビューに疑似列または式が含まれる場合、そのビューを更新する唯一の方法は、その疑似列または式を参照しないUPDATE文を使用することです。
ビュー内のネストした表の列の要素は、TABLE句で直接変更することはできません。ただし、ビューのネストした表の列にINSTEAD OFトリガーを定義すると、要素を変更できます。ネストした表のトリガーは、その表の要素が更新、挿入または削除すると起動し、基礎となる表に対する実際の変更を処理します。
トリガーを使用すると、データベース・イベントに関する情報を、サブスクライバに対して発行できます。アプリケーションは、他のアプリケーションからのメッセージにサブスクライブするのと同様に、データベース・イベントにサブスクライブできます。これらのデータベース・イベントは、次のとおりです。
システム・イベントのトリガーは、データベース・レベルまたはスキーマ・レベルで定義できます。DBMS_AQパッケージは、特定のアクションを実行するデータベース・トリガーの使用例です。たとえば、データベース停止トリガーは、データベース・レベルで次のように定義します。
CREATE TRIGGER register_shutdown ON DATABASE SHUTDOWN BEGIN ... DBMS_AQ.ENQUEUE(...); ... END;
DDL文またはログオン・イベントおよびログオフ・イベントのトリガーも、データベース・レベルまたはスキーマ・レベルで定義できます。DML文のトリガーは、表またはビューに定義できます。データベース・レベルで定義されたトリガーはすべてのユーザーに対して起動し、スキーマ・レベルまたは表レベルで定義されたトリガーは、トリガー・イベントがそのスキーマまたは表に関連する場合にのみ起動します。
イベントの発行では、Oracle Streamsのアドバンスト・キューイングのパブリッシュ/サブスクライブ・メカニズムが使用されます。キューは、各種サブスクライバに必要な主題を含むメッセージ・リポジトリの役割を果たします。トリガーは、特定のシステム・イベントまたはユーザー・イベントの発生時に、DBMS_AQパッケージを使用してメッセージをエンキューします。
各イベントでは、トリガー・テキスト内で属性を使用できます。たとえば、データベース起動および停止トリガーは、インスタンス番号およびデータベース名の属性を持ち、ログオン・トリガーおよびログオフ・トリガーは、ユーザー名の属性を持ちます。属性をイベント発生時に発行する場合は、トリガーの作成時に、その属性と同じ名前のファンクションを指定できます。属性値は、トリガーの起動時にファンクションまたはペイロードに渡されます。DML文のトリガーの場合は、:OLD列の値によって属性値が:NEW列の値に渡されます。
トリガーを起動できるシステム・イベントは、インスタンスの起動と停止およびエラー・メッセージに関連しています。起動および停止イベントに対して作成するトリガーは、データベースに対応付ける必要があります。エラー・イベントに対して作成するトリガーは、データベースまたはスキーマに対応付けることができます。
STARTUPトリガーは、インスタンスによってデータベースがオープンされるときに起動します。この属性には、システム・イベント、インスタンス番号およびデータベース名があります。
SHUTDOWNトリガーは、サーバーがインスタンスの停止操作を開始する直前に起動します。このトリガーを使用して、データベースの停止時にサブスクライバ・アプリケーションを完全に停止できます。インスタンスが異常停止する場合、このトリガーは起動しません。SHUTDOWNトリガーの属性には、システム・イベント、インスタンス番号およびデータベース名があります。
SERVERERRORトリガーは、特定のエラーの発生時、または、エラー番号を指定しなければ任意のエラーの発生時に起動します。このトリガーの属性には、システム・イベントとエラー番号があります。
DB_ROLE_CHANGEトリガーは、Data Guard構成でロール遷移(フェイルオーバーまたはスイッチオーバー)が発生したときに起動します。このトリガーでは、ロール遷移発生時にユーザーに通知されるため、新規プライマリ・データベースでクライアント接続を処理でき、アプリケーションは引き続き動作できます。
トリガーを起動できるユーザー・イベントは、ユーザー・ログオンとログオフ、DDL文およびDML文に関連しています。
LOGONトリガーおよびLOGOFFトリガーは、データベースまたはスキーマに対応付けることができます。その属性には、システム・イベントとユーザー名があり、USERIDとUSERNAMEについて簡単な条件を指定できます。
DDLトリガーは、データベースまたはスキーマに対応付けることができます。その属性には、システム・イベント、スキーマ・オブジェクトのタイプおよび名前があります。ここでは、スキーマ・オブジェクトの型と名前のみでなく、USERIDやUSERNAMEなどのファンクションについても簡単な条件を指定できます。DDLトリガーには、次のタイプのトリガーがあります。
BEFORE CREATEトリガーおよびAFTER CREATEトリガーは、データベースまたはスキーマ内でスキーマ・オブジェクトが作成されるときに起動します。
BEFORE ALTERトリガーおよびAFTER ALTERトリガーは、データベースまたはスキーマ内でスキーマ・オブジェクトが変更されるときに起動します。
BEFORE DROPトリガーおよびAFTER DROPトリガーは、データベースまたはスキーマからスキーマ・オブジェクトが削除されるときに起動します。
イベント発行用のDMLトリガーは、表に対応付けられます。指定したDML操作が発生する各行に対して起動するように、BEFOREトリガーまたはAFTERトリガーを使用できます。DML文に関連するイベントの発行には、INSTEAD OFトリガーを使用できません。かわりに、INSTEAD OFトリガーによってビューの基礎となる表に生じるDML操作について、BEFOREトリガーまたはAFTERトリガーを使用してイベントを発行できます。
イベント発行用のDMLトリガーの属性には、システム・イベントと、SELECTリストにユーザーが定義する列があります。これにより、スキーマ・オブジェクトの型と名前のみでなく、ファンクション(UID、USER、USERENVおよびSYSDATE)、疑似列および列についても、簡単な条件を指定できます。列には、接頭辞として新旧の値を示す:OLDと:NEWを使用できます。DML文のトリガーを次に示します。
BEFORE INSERTおよびAFTER INSERTトリガーは、表に挿入される行ごとに起動します。
BEFORE UPDATEおよびAFTER UPDATEトリガーは、表中で更新される行ごとに起動します。
BEFORE DELETEおよびAFTER DELETEトリガーは、表から削除される行ごとに起動します。
関連項目
トリガーには次の2つのモードがあります。
| トリガーのモード | 定義 |
|---|---|
|
使用可能 |
使用可能にされているトリガーは、トリガーを実行する文が発行され、トリガー条件(指定されている場合)の評価が |
|
|
使用禁止にされているトリガーは、トリガーを実行する文が発行され、トリガー条件(指定されている場合)の評価が |
使用可能なトリガーの場合、Oracleは次の処理を自動的に行います。
1つのSQL文は、最大4種類のトリガーを起動します。
トリガーを実行する文またはトリガー内の文によって、1つ以上の整合性制約のチェックが実施されます。またトリガーには、他のトリガーを起動する文を含めることもできます(連鎖的なトリガー)。
Oracleでは、次の実行モデルを使用して、複数のトリガーと制約チェックの適切な起動順序を維持します。
BEFORE文トリガーを実行します。
AFTER文トリガーを実行します。
実行モデルの定義は再帰的です。たとえば、あるSQL文によってBEFORE行トリガーを起動し、整合性制約をチェックできます。次に、このBEFORE行トリガーが実行する更新によって、整合性制約をチェックし、AFTER文トリガーを起動できます。このAFTER文トリガーによって、整合性制約がチェックされます。この場合、実行モデルでは、次の処理が再帰的に繰り返し実行されます。
元のSQL文が発行されます。
この再帰には、次の2つの例外があります。
DELETE CASCADEおよびDELETE SET NULLによって起動される文トリガーは、個々の規定文の前後ではなく、ユーザーのDELETE文の前後で起動されます。これにより、この種の文トリガーによる変更エラーの発生が防止されます。
実行モデルの重要なプロパティは、SQL文の結果として実行されるアクションとチェックがすべて成功する必要があることです。トリガー内で発生した例外を明示的に処理できない場合、元のSQL文によって実行されたすべてのアクションが、起動されたトリガーによって実行されたアクションを含めて、ロールバックされます。したがって、トリガーが整合性制約に違反することはありません。実行モデルは整合性制約を考慮し、宣言整合性制約に違反するトリガーを認めません。
たとえば、前述の使用例で整合性制約に違反があったとします。その違反の結果として、SQL文によるすべての変更、起動されたBEFORE行トリガーおよび起動されたAFTER文トリガーがロールバックされます。
トリガーが起動されると、トリガー・アクション内で参照される表は、他のユーザーのトランザクション内のSQL文によって変更されている最中である可能性があります。トリガー内で実行されるSQL文は、常に単独のSQL文と同じ規則に従います。起動されたトリガーが読取り(問合せ)または書込み(更新)の対象にする値が、まだコミットされていないトランザクションによって変更されたものである場合、起動されたトリガーの本体にあるSQL文は、次のガイドラインに従います。
PL/SQLトリガーは、ストアド・プロシージャと同じように、コンパイル済の形式で格納されます。CREATE TRIGGER文がコミットされると、Pコード(疑似コード)と呼ばれるコンパイル済PL/SQLコードがデータベースに格納され、トリガーのソース・コードは共有プールからフラッシュされます。
Oracleは、プロシージャの実行と同じ手順を使用してトリガーを内部的に実行します。両者の唯一の違いは、ユーザーがトリガー文を実行する権限を持っていれば、トリガーを起動する権限が付与されることです。この点を除けば、トリガーはストアド・プロシージャと同じ方法でチェックされ、実行されます。
プロシージャと同様に、トリガーも参照しているオブジェクトに依存します。トリガー・アクションで参照されるスキーマ・オブジェクトに対するトリガーの依存性は、Oracleによって自動的に管理されます。トリガーの依存性についての問題は、ストアド・プロシージャの依存性についての問題と同じです。トリガーは、ストアド・プロシージャと同様に扱われます。これらは、データ・ディクショナリに挿入されます。
|
![]() Copyright © 2006 Oracle Corporation. All Rights Reserved. |
|