Oracle Database 2日で開発者ガイド 11g リリース1(11.1) E05694-03 |
|
この章では、データベースの表、ビューまたはイベントと関連付けられたストアド・プロシージャのコードであるデータベース・トリガーについて説明します。
この章の内容は次のとおりです。
トリガーはデータベースで指定したイベントが発生した際に、自動的に起動されるストアド・プロシージャのコードです。トリガーは表、ビューまたはイベントと関連付けられます。プロシージャおよびファンクションとは異なり、トリガーは直接的に起動できません。そのかわり、Oracle Databaseはユーザーまたはアプリケーションに関係なくトリガーされたイベントが発生したときに、トリガーを暗示的に起動します。トリガーを起動したイベントが失敗した場合、オペレーションが正常に処理されないエラーを発生させないかぎり、トリガーが活動していることに気づかないでしょう。
トリガーを正しく使用することで、より効率的なデータベースを使用でき、より堅固でセキュアなアプリケーションを構築およびデプロイできます。これらの利点は、トリガーが次の機能を提供することで実現可能になります。
データベースに固有で、そのためにすべてのクライアント・アプリケーションに共通の低いレベルのビジネス・ルールを強化するトリガーを使用できます。たとえば、hr
スキーマのemployees
表にアクセスするいくつかのクライアント・アプリケーションがあると思います。この表に対するトリガーが、表に追加されるすべてのデータが正しい形式であることを確認する場合、このビジネス・ロジックはすべてのクライアント・アプリケーションで再生産およびメンテナンスを行う必要がありません。これは、トリガーがクライアント・アプリケーションによって回避できず、トリガーに格納されたビジネス・ロジックが自動的に使用されるためです。
各トリガーには次の一般的な書式が含まれます。
TRIGGER trigger_name triggering_statement [trigger_restriction] BEGIN triggered_action; END;
トリガーには4つの主要な部分があります。
INSERT
、UPDATE
およびDELETE
)、スキーマ・オブジェクトのDDL文(CREATE
、ALTER
およびDROP
)、システム・エラー、データベースの起動および終了、また他のシステム・アクションが含まれます。トリガーを実行する文はトリガーの制限の影響を受けます。
TRUE
と評価する場合のみ、データベースはトリガーされたアクションを実行するという意味です。
TRUE
と評価する際に両方に実行される一連の手順です。 Oracle Databaseのトリガーには5つの異なるタイプがあります。
DELETE
、INSERT
またはUPDATE
などのDML文と関連付けられています。 文トリガーは各DML文に対して一度起動します。たとえば、UPDATE
文トリガーは、表の影響を受ける行数に関係なく一度のみ実行します。
Oracle Databaseリリース11g R1から、特定のDML文と関連付けられたいくつかの異なるトリガーを所持できます。CREATE TRIGGER
文のFOLLOWS
およびPRECEDES
句を使用して、実行される順序を指定できます。
INSERT
、UPDATE
またはDELETE
文に影響を受ける各行に対して起動します。 行トリガーは文トリガーとして同一の方法で機能しますが、2つの追加の指定を使用します。行トリガーはトリガー中の文でFOR EACH ROW
句を使用します。また、行トリガーによって、行の値を参照し、トリガーの本体でイベントをトリガーに設定できます。これは特に、デフォルト値の挿入および無効な値の上書きに便利です。
INSTEAD OF
トリガーを実行します。INSERT
文がビューで使用されている場合、INSTEAD OF
トリガーを使用して、実表または他の表へのデータの挿入、データの挿入が不要な挿入要求のロギングなどの実際に発生する処理の密な制御を実行できます。 また、Oracle Databaseはビューに対して発行された挿入の処理ができない場合があります。生成された列の場合、値を正確に決定するトリガーを作成できます。たとえば、ビューが列定義last_name || ', ' || first_name
を使用していた場合、last_name
列中でカンマ文字の前の文字およびfirst_name
列中でカンマ文字の後の文字を更新する、INSTEAD OF
トリガーが記述されている可能性があります。
CREATE
、ALTER
、DROP
などのDDL文、ユーザーLOGON
およびLOGOFF
、特定のDMLアクション(分析および統計、監査、付与および権限の取消しなど)で使用できます。ユーザーがデータベースへ接続した時に起動するLOGON
トリガーは、ユーザーに対して環境を設定し、セキュアなアプリケーション・ロールと関連付けられたファンクションを実行するために一般的に使用されます。
参照:
CREATE TRIGGER
文の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。
トリガーはトリガー中の文でBEFORE
またはAFTER
句を使用できます。BEFORE
およびAFTER
で、トリガーを起動するイベントの前または後のどちらにトリガーを実行するかを指定します。文および行トリガーでは、BEFORE
トリガーはセキュリティを強化でき、データベースへの変更を行う前にビジネス・ルールを有効にします。一方、AFTER
トリガーはロギング・アクションに非常に役立ちます。
INSTEAD OF
トリガーはBEFORE
またはAFTER
オプションを使用しません。デフォルトでは、これらのオプションはAFTER
の行レベルのトリガーとして同一のセマンティクスを使用します。
システムおよびユーザー・イベント・トリガーでは、明らかな例外を除いて、BEFORE
句およびAFTER
句を使用できます。これらの例外は、AFTER
がSTARTUP
、SUSPEND
およびLOGON
に有効な場合、およびBEFORE
がSHUTDOWN
およびLOGOFF
に有効な場合のみです。
アプリケーションのトリガーを計画する際に次のガイドラインおよび制限を検討する必要があります。
BEFORE
句およびAFTER
句を正確に使用していることを確認します。BEFORE EACH ROW
トリガーは:NEW
値を変更できます。
COMMIT
、ROLLBACK
またはSAVEPOINT
を使用できません。これは、DDL文に暗黙的COMMIT
が含まれ、DDL文もトリガーでは使用できないためです。システム・トリガーのCREATE
、ALTER
、DROP TABLE
、ALTER...COMPILE
は、除きます。
この項では、様々なタイプのトリガーの作成および使用方法を示します。
この項には、次のトピックが含まれます。
文トリガーは、INSERT
、UPDATE
またはDELETE
などの特定の文に関連しています。これらは特定の表で実行されるので、これらの操作のロギングに対して文トリガーを使用できます。
例5-1は、ログ表の作成方法を示しています。
evaluations_log
表にはevaluations
表で各INSERT
、UPDATE
またはDELETE
を持つエントリが格納されます。
CREATE TABLE evaluations_log (log_date DATE , action VARCHAR2(50));
例5-2では、evaluations
表が変更されるたびにevaluations_log
に書き込むトリガーを作成します。
トリガーeval_change_trigger
は、evaluations
表に対するすべての変更を追跡し、これらの変更が行われた後に
新しい行を追加することによってevaluations_log
表で変更を追跡します。この例では、使用可能な3つの文からトリガーを起動する文を決定するために、トリガーの本体で条件述語INSERTING
、UPDATING
またはDELETING
が使用されていることに注意してください。
CREATE OR REPLACE TRIGGER eval_modification_trigger AFTER INSERT OR UPDATE OR DELETE ON evaluations DECLARE log_action evaluations_log.action%TYPE; BEGIN IF INSERTING THEN log_action := 'Insert'; ELSIF UPDATING THEN log_action := 'Update'; ELSIF DELETING THEN log_action := 'Delete'; ELSE DBMS_OUTPUT.PUT_LINE('This code is not reachable.'); END IF; INSERT INTO evaluations_log (log_date, action) VALUES (SYSDATE, log_action); END;
行トリガーは影響を受けるそれぞれの行に対して実行されます。
「順序の使用」で、evaluations_seq
順序をevaluations
表に対する主キー番号ジェネレータとして作成しました。Oracle Databaseでは、CREATE TABLE
文の一部として、主キーは自動的に作成されません。かわりに、INSERT
文を使用して主キーに対する一意の番号を生成するトリガーを設計する必要があります。
次のタスクでは、SQL Developer Connectionナビゲーション階層を使用して、トリガーnew_evaluation
を作成します。このトリガーは、同一の従業員の行が同一の期間に存在するかどうかに基づいて、新しい表をevaluations
表に追加する必要があるかどうかをチェックします。
「Trigger」ペインで、「Trigger Type」をTABLE
に、次に「Table Owner」をHR
に、そして「Table Name」をevaluations
に設定し、「Before」、「Insert」および「Row Level」の順で選択します。
「OK」をクリックします。
new_evaluation
ペインを次のコードを使用してオープンします。ペインのタイルがイタリック・フォントになっていることに注意してください。トリガーがデータベースに保存されていないことを示しています。
CREATE OR REPLACE TRIGGER new_evaluation BEFORE INSERT ON evaluations FOR EACH ROW BEGIN NULL; END;
Oracle Databaseにより、トリガーは保存前に自動的にコンパイルされます。
INSTEAD OF
トリガーでは、表示の基礎となる表に対する変更を実装できます。このようなトリガーは「ビューの作成」で作成した emp_locations
ビューで使用されます。emp_locations
の定義を確認します。
CREATE VIEW emp_locations AS SELECT e.employee_id, e.last_name || ', ' || e.first_name name, d.department_name department, l.city city, c.country_name country FROM employees e, departments d, locations l, countries c WHERE e.department_id = d.department_id AND d.location_id = l.location_id AND l.country_id = c.country_id ORDER BY last_name;
例5-4では、INSTEAD OF
トリガーupdate_name_view_trigger
を実装して、従業員の名前を更新します。
CREATE OR REPLACE TRIGGER update_name_view_trigger INSTEAD OF UPDATE ON emp_locations BEGIN -- allow only the following update(s) UPDATE employees SET first_name = substr( :NEW.name, instr( :new.name, ',' )+2), last_name = substr( :NEW.name, 1, instr( :new.name, ',')-1) WHERE employee_id = :OLD.employee_id; END;
LOGON
およびLOGOFF
トリガーは、ログ表へ書き込むことで、データベースの使用者を監視します。
例5-5では、LOGON
およびLOGOFF
イベントの追跡を続行するためにhr_users_log
表を作成します。その後、これらのイベントをログ表に書き込むために、トリガーnote_hr_logon_trigger
(例5-6)およびnote_hr_logoff_trigger
(例5-7)を作成します。
この表はhr
スキーマでのすべてのログオンおよびログイン・イベントのログです。
CREATE TABLE hr_users_log (user_name VARCHAR2(30), activity VARCHAR2(20), event_date DATE);例5-6 LOGONトリガーの作成
hr
スキーマに接続すると、このトリガーによりLOGON
イベント・レコードがhr_users_log
表に挿入されます。これはAFTER
トリガーであることに注意してください。
CREATE OR REPLACE TRIGGER note_hr_logon_trigger AFTER LOGON ON HR.SCHEMA BEGIN INSERT INTO hr_users_log VALUES (USER, 'LOGON', SYSDATE); END;例5-7 LOGOFFトリガーの作成
hr
スキーマへの接続が切断されると、このトリガーによりLOGOFF
イベント・レポートがhr_users_log
表に挿入されます。これはBEFORE
トリガーであることに注意してください。
CREATE OR REPLACE TRIGGER note_hr_logoff_trigger BEFORE LOGOFF ON HR.SCHEMA BEGIN INSERT INTO hr_users_log VALUES (USER, 'LOGOFF', SYSDATE); END;
new_evaluation_trigger
には空の本体があります。
例5-8は、evaluations_seq
順序の次の使用可能な値をevaluation_id
に割り当てるトリガーの変更方法を示しています。
次のコードを使用して、new_evaluation_trigger
を置換します。新規コードは太字フォントです。
CREATE OR REPLACE TRIGGER new_evaluation_trigger BEFORE INSERT ON evaluations FOR EACH ROW BEGIN :NEW.evaluation_id := evaluations_seq.NEXTVAL; END;
トリガーが参照するオブジェクトが使用不可能である場合またはトリガーが原因の遅延なしに大規模なデータのアップロードを実行する必要がある場合(リカバリ操作など)、トリガーを一時的に無効にする必要があります。
トリガーを無効にするには、ALTER TRIGGER ... DISABLE
文を使用する必要があります。トリガーを再度有効にするには、ALTER TRIGGER ... ENABLE
文を使用します。
例5-9は、トリガーを一時的に無効にする方法を示しています。
ALTER TRIGGER eval_change_trigger DISABLE;
例5-10は、トリガーを再度有効にする方法を示しています。
ALTER TRIGGER eval_change_trigger ENABLE;
特定の表のすべてのトリガーを無効にする必要がある場合は、ALTER TABLE ... DISABLE ALL TRIGGERS
文を使用する必要があります。表のすべてのトリガーを再度有効にするには、ALTER TABLE ... ENABLE ALL TRIGGERS
文を使用します。
例5-11は、特定の表で定義されたすべてのトリガーを一時的に無効にする方法を示しています。
ALTER TABLE evaluations DISABLE ALL TRIGGERS;
例5-12は、特定の表で定義されたすべてのトリガーを再度有効にする方法を示しています。
ALTER TABLE evaluations ENABLE ALL TRIGGERS;
CREATE TRIGGER
文が実行されると、トリガーは完全にコンパイルされます。トリガーのコンパイルでエラーが生じた場合、DML文は失敗します。関連したコンパイル・エラーを表示するには、USER_ERRORS
ビューを使用します。
例5-13に、データベースに存在するトリガー・エラーを判断する方法を示します。
SELECT * FROM USER_ERRORS WHERE TYPE = 'TRIGGER';
トリガーがコンパイルされると、基礎となるデータベース・オブジェクトに依存性を作成し、トリガーとオブジェクトが一致しないようにこれらのオブジェクトが削除または変更された場合はトリガーが無効になります。無効なトリガーは次の起動時に再コンパイルされます。
例5-14は、データベース内の他のオブジェクトにあるトリガー依存性を確認する方法を示しています。
SELECT * FROM ALL_DEPENDENCIES WHERE TYPE = 'TRIGGER';
手動でトリガーを再コンパイルするには、例5-15に示すようにALTER TRIGGER ... COMPILE
文を使用する必要があります。
ALTER TRIGGER update_name_view_trigger COMPILE;
トリガーを削除する必要がある場合は、例5-16に示すようにDROP TRIGGER
文を使用します。
DROP TRIGGER eval_change_trigger;
トリガーの削除後、アプリケーションに必要のない依存オブジェクトを削除できます。
|
![]() Copyright © 2005, 2008, Oracle Corporation. All Rights Reserved. |
|