ヘッダーをスキップ

Oracle Database 2日で開発者ガイド
11g リリース1(11.1)

E05694-03
目次
目次
索引
索引

戻る 次へ

5 トリガーの使用

この章では、データベースの表、ビューまたはイベントと関連付けられたストアド・プロシージャのコードであるデータベース・トリガーについて説明します。

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

トリガーの設計

トリガーはデータベースで指定したイベントが発生した際に、自動的に起動されるストアド・プロシージャのコードです。トリガーは表、ビューまたはイベントと関連付けられます。プロシージャおよびファンクションとは異なり、トリガーは直接的に起動できません。そのかわり、Oracle Databaseはユーザーまたはアプリケーションに関係なくトリガーされたイベントが発生したときに、トリガーを暗示的に起動します。トリガーを起動したイベントが失敗した場合、オペレーションが正常に処理されないエラーを発生させないかぎり、トリガーが活動していることに気づかないでしょう。

トリガーを正しく使用することで、より効率的なデータベースを使用でき、より堅固でセキュアなアプリケーションを構築およびデプロイできます。これらの利点は、トリガーが次の機能を提供することで実現可能になります。

データベースに固有で、そのためにすべてのクライアント・アプリケーションに共通の低いレベルのビジネス・ルールを強化するトリガーを使用できます。たとえば、hrスキーマのemployees表にアクセスするいくつかのクライアント・アプリケーションがあると思います。この表に対するトリガーが、表に追加されるすべてのデータが正しい形式であることを確認する場合、このビジネス・ロジックはすべてのクライアント・アプリケーションで再生産およびメンテナンスを行う必要がありません。これは、トリガーがクライアント・アプリケーションによって回避できず、トリガーに格納されたビジネス・ロジックが自動的に使用されるためです。

各トリガーには次の一般的な書式が含まれます。

TRIGGER trigger_name
  triggering_statement
  [trigger_restriction]
BEGIN
 triggered_action;
END;

トリガーには4つの主要な部分があります。

トリガーのタイプ

Oracle Databaseのトリガーには5つの異なるタイプがあります。

トリガーのタイミング

トリガーはトリガー中の文でBEFOREまたはAFTER句を使用できます。BEFOREおよびAFTERで、トリガーを起動するイベントの前または後のどちらにトリガーを実行するかを指定します。文および行トリガーでは、BEFOREトリガーはセキュリティを強化でき、データベースへの変更を行う前にビジネス・ルールを有効にします。一方、AFTERトリガーはロギング・アクションに非常に役立ちます。

INSTEAD OFトリガーはBEFOREまたはAFTERオプションを使用しません。デフォルトでは、これらのオプションはAFTERの行レベルのトリガーとして同一のセマンティクスを使用します。

システムおよびユーザー・イベント・トリガーでは、明らかな例外を除いて、BEFORE句およびAFTER句を使用できます。これらの例外は、AFTERSTARTUPSUSPENDおよびLOGONに有効な場合、およびBEFORESHUTDOWNおよびLOGOFFに有効な場合のみです。

参照:

  • 『Oracle Database SQL言語リファレンス』

 

トリガー設計のガイドラインおよび制限

アプリケーションのトリガーを計画する際に次のガイドラインおよび制限を検討する必要があります。

トリガーの作成および使用

この項では、様々なタイプのトリガーの作成および使用方法を示します。

この項には、次のトピックが含まれます。

文トリガーの作成

文トリガーは、INSERTUPDATEまたはDELETEなどの特定の文に関連しています。これらは特定の表で実行されるので、これらの操作のロギングに対して文トリガーを使用できます。

例5-1は、ログ表の作成方法を示しています。

例5-1    EVALUATIONS表のログ表の作成

evaluations_log表にはevaluations表で各INSERTUPDATEまたはDELETEを持つエントリが格納されます。

CREATE TABLE evaluations_log (log_date DATE 
                            , action VARCHAR2(50));

例5-2では、evaluations表が変更されるたびにevaluations_logに書き込むトリガーを作成します。

例5-2    文トリガーおよび述語を使用した操作のロギング

トリガーeval_change_triggerは、evaluations表に対するすべての変更を追跡し、これらの変更が行われた後に新しい行を追加することによってevaluations_log表で変更を追跡します。この例では、使用可能な3つの文からトリガーを起動する文を決定するために、トリガーの本体で条件述語INSERTINGUPDATINGまたは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表に追加する必要があるかどうかをチェックします。

例5-3    主キーFOR EACH ROWトリガーであるBEFOREオプションの生成

  1. 「Connections」ナビゲーション階層で、「Triggers」を右クリックします。

  2. ドロップダウン・リストから「New Trigger」を選択します。


    画像の説明

  3. 「Create Trigger」ウィンドウで、次のパラメータを設定します。

    • 「Name」new_evaluation_triggerに設定します。

    「Trigger」ペインで、「Trigger Type」TABLEに、次に「Table Owner」HRに、そして「Table Name」evaluationsに設定し、「Before」「Insert」および「Row Level」の順で選択します。

    「OK」をクリックします。


    画像の説明

  4. new_evaluationペインを次のコードを使用してオープンします。

    ペインのタイルがイタリック・フォントになっていることに注意してください。トリガーがデータベースに保存されていないことを示しています。

    CREATE OR REPLACE
    TRIGGER new_evaluation
      BEFORE INSERT ON evaluations
      FOR EACH ROW
    BEGIN
      NULL;
    END;
    
    
  5. 「File」メニューから「Save」を選択して新規のトリガーを保存します。または[Ctrl]を押しながら[S]キーを押します。

    Oracle Databaseにより、トリガーは保存前に自動的にコンパイルされます。

INSTEAD OFトリガーの作成

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を実装して、従業員の名前を更新します。

例5-4    INSTEAD OFトリガーを使用したビューからの値の更新

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トリガーの作成

LOGONおよびLOGOFFトリガーは、ログ表へ書き込むことで、データベースの使用者を監視します。

例5-5では、LOGONおよびLOGOFFイベントの追跡を続行するためにhr_users_log表を作成します。その後、これらのイベントをログ表に書き込むために、トリガーnote_hr_logon_trigger例5-6)およびnote_hr_logoff_trigger例5-7)を作成します。

例5-5    アクセス・ログ表、hr_users_logの作成

この表は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に割り当てるトリガーの変更方法を示しています。

例5-8    トリガーの変更

次のコードを使用して、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は、トリガーを一時的に無効にする方法を示しています。

例5-9    トリガーの無効化

ALTER TRIGGER eval_change_trigger DISABLE;

例5-10は、トリガーを再度有効にする方法を示しています。

例5-10    トリガーの有効化

ALTER TRIGGER eval_change_trigger ENABLE;

特定の表のすべてのトリガーを無効にする必要がある場合は、ALTER TABLE ... DISABLE ALL TRIGGERS文を使用する必要があります。表のすべてのトリガーを再度有効にするには、ALTER TABLE ... ENABLE ALL TRIGGERS文を使用します。

例5-11は、特定の表で定義されたすべてのトリガーを一時的に無効にする方法を示しています。

例5-11    表のすべてのトリガーの無効化

ALTER TABLE evaluations DISABLE ALL TRIGGERS;

例5-12は、特定の表で定義されたすべてのトリガーを再度有効にする方法を示しています。

例5-12    表のすべてのトリガーの有効化

ALTER TABLE evaluations ENABLE ALL TRIGGERS;

参照:

  • トリガーの有効化の詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。

  • トリガーの無効化の詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。

 

トリガーのコンパイル

CREATE TRIGGER文が実行されると、トリガーは完全にコンパイルされます。トリガーのコンパイルでエラーが生じた場合、DML文は失敗します。関連したコンパイル・エラーを表示するには、USER_ERRORSビューを使用します。

例5-13に、データベースに存在するトリガー・エラーを判断する方法を示します。

例5-13    トリガー・コンパイル・エラーの表示

SELECT * FROM USER_ERRORS WHERE TYPE = 'TRIGGER';

トリガーがコンパイルされると、基礎となるデータベース・オブジェクトに依存性を作成し、トリガーとオブジェクトが一致しないようにこれらのオブジェクトが削除または変更された場合はトリガーが無効になります。無効なトリガーは次の起動時に再コンパイルされます。

例5-14は、データベース内の他のオブジェクトにあるトリガー依存性を確認する方法を示しています。

例5-14    トリガー依存性の表示

SELECT * FROM ALL_DEPENDENCIES WHERE TYPE = 'TRIGGER';

手動でトリガーを再コンパイルするには、例5-15に示すようにALTER TRIGGER ... COMPILE文を使用する必要があります。

例5-15    トリガー・コンパイル・エラーの表示

ALTER TRIGGER update_name_view_trigger COMPILE;

参照:

  • トリガーのコンパイルの詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。

 

トリガーの削除

トリガーを削除する必要がある場合は、例5-16に示すようにDROP TRIGGER文を使用します。

例5-16    トリガーの削除

DROP TRIGGER eval_change_trigger;

トリガーの削除後、アプリケーションに必要のない依存オブジェクトを削除できます。

参照:

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

 


戻る 次へ
Oracle
Copyright © 2005, 2008, Oracle Corporation.

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