この章の内容は、次のとおりです。
トリガーはデータベースに格納され、(有効な状態の場合)指定されたイベントに対して自動的に実行される(起動する)PL/SQLユニットです。
トリガーは次のような構造です。
TRIGGER trigger_name triggering_event [ trigger_restriction ] BEGIN triggered_action; END;
trigger_name
は、スキーマ内のトリガーで一意である必要があります。トリガーには、スキーマ内の別の種類のオブジェクト(表など)と同じ名前を指定できますが、混乱を防ぐネーミング規則を使用することをお薦めします。
トリガーが有効な状態の場合、trigger_restriction
がTRUE
または省略されると、triggering_event
によりデータベースはtriggered_action
を実行します。triggering_event
は、表、ビュー、スキーマ、またはデータベースのいずれかに関連付けられており、次のうちのいずれかとなります。
DML文(「データ操作言語(DML)文について」を参照)
DDL文(「データ定義言語(DDL)文について」を参照)
データベース処理(SERVERERROR
、LOGON
、LOGOFF
、STARTUP
またはSHUTDOWN
)
トリガーが無効の状態のとき、triggering_event
はデータベースにtriggered_action
を実行させません。これは、trigger_restriction
がTRUE
の場合や省略された場合も同様です。
デフォルトでは、トリガーは有効な状態で作成されます。有効なトリガーを無効化したり、無効なトリガーを有効化することができます。
サブプログラムとは異なり、トリガーを直接起動することはできません。トリガーは、ユーザーまたはアプリケーションによって生じるトリガー・イベントによってのみ起動します。正常に処理されないエラーが発生しないかぎり、トリガーが実行されていることに気づかない可能性があります。
単純なトリガーは、次のいずれかのタイミング・ポイントで起動できます。
イベントが影響する各行の後(行レベルのAFTER
トリガー)
複合トリガーは複数のタイミング・ポイントで起動できます。複合トリガーの詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。
INSTEAD
OF
トリガーはビューで定義され、トリガー・イベントはDML文です。DML文を実行するかわりに、Oracle DatabaseはINSTEAD
OF
トリガーを実行します。詳細は、「INSTEAD OFトリガーの作成」を参照してください。
システム・トリガーは、スキーマまたはデータベースで定義されます。スキーマで定義されたトリガーは、スキーマの所有者(現在のユーザー)に関連付けられた各イベントに対して起動します。データベースで定義されたトリガーは、すべてのユーザーに関連付けられた各イベントに対して起動します。
トリガーの1つの使用目的は、すべてのクライアント・アプリケーションに適用されるビジネス・ルールを実行することです。たとえば、EMPLOYEES
表に追加するデータが特定のフォーマットをもっていなければならず、多くのクライアント・アプリケーションがこの表にデータを追加できるとします。表のトリガーを使用すると、追加するすべてのデータが適切なフォーマットになります。任意のクライアントが表にデータを追加するたびにトリガーが実行されるため、クライアントはルールを回避することができず、ルールを実行するコードは、すべてのクライアント・アプリケーションではなくトリガーにのみ格納されて保持されます。トリガーの他の使用目的の詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。
参照: トリガーの詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。 |
トリガーを作成するには、SQL Developerのトリガーの作成ツールまたはDDL文のCREATE
TRIGGER
を使用します。ここでは、これらの方法を使用してトリガーを作成する方法について説明します。
デフォルトでは、トリガーは有効な状態で作成されます。無効な状態でトリガーを作成するには、DISABLE
句のあるCREATE
TRIGGER
文を使用します。
注意: トリガーを作成するには、適切な権限を所持する必要がありますが、ここでの説明では、この追加情報は必要ありません。 |
この項の内容は次のとおりです。
注意: このマニュアルのチュートリアルを行うには、ユーザーHR として、SQL DeveloperからOracle Databaseに接続している必要があります。 |
参照:
|
行レベルのトリガーが起動すると、PL/SQLランタイム・システムは2つの疑似レコードOLD
およびNEW
を作成および移入します。レコードのプロパティのすべてではなく、一部を持つため、疑似レコードと呼ばれます。
トリガーが処理している行では、次のようになります。
INSERT
トリガーの場合、OLD
には値が含まれず、NEW
には新しい値が含まれます。
UPDATE
トリガーの場合、OLD
には古い値が含まれ、NEW
には新しい値が含まれます。
DELETE
トリガーの場合、OLD
には古い値が含まれ、NEW
には値が含まれません。
疑似レコードを参照するには、例6-1のように、:OLD
または:NEW
と名前の前にコロンを付けます。
参照: OLD およびNEW 疑似レコードの詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。 |
このチュートリアルでは、CREATE
TRIGGER
文を使用してEVAL_CHANGE_TRIGGER
トリガーを作成する方法を示します。このトリガーは、INSERT
、UPDATE
またはDELETE
文によってEVALUATIONS
表が変更されるたびにEVALUATIONS_LOG
表に行を追加します。
このトリガーは、トリガー文が実行された後に行を追加し、条件述語INSERTING
、UPDATING
およびDELETING
を使用して、使用可能な3つのDML文のうち、トリガーを起動した文を判断します。
EVAL_CHANGE_TRIGGER
は、文レベルのトリガーで、AFTERトリガーです。
EVALUATIONS_LOGおよびEVAL_CHANGE_TRIGGERを作成するには、次の手順を実行します。
EVALUATIONS_LOG
表を作成します。
CREATE TABLE EVALUATIONS_LOG ( log_date DATE , action VARCHAR2(50));
EVAL_CHANGE_TRIGGER
を作成します。
CREATE OR REPLACE TRIGGER EVAL_CHANGE_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;
参照: 条件述部の詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。 |
(「チュートリアル: 順序の作成」で作成した)順序EVALUATIONS_SEQUENCE
は、(「表の作成」で作成した)EVALUATIONS
表の主キーを生成します。ただし、これらの主キーは自動的に表に挿入されません。
このチュートリアルでは、SQL Developerのトリガーの作成ツールを使用して、NEW_EVALUATION_TRIGGER
というトリガーを作成する方法を説明します。このトリガーはEVALUATIONS
表に行が挿入される前に起動し、EVALUATIONS_SEQUENCE
を使用して、その行の主キーに対する一意の番号を生成します。INSERT
文のトリガーの影響を受ける行ごとに、このトリガーは一度起動します。
NEW_EVALUATION_TRIGGER
は、行レベルのトリガーで、BEFOREトリガーです。
NEW_EVALUATIONトリガーを作成するには、次の手順を実行します。
「接続」フレームで、hr_connを展開します。
スキーマ・オブジェクト・タイプのリストで、「トリガー」を右クリックします。
選択肢のリストで、「新規トリガー」をクリックします。
「トリガーの作成」ウィンドウで、次の手順を実行します。
「名前」フィールドで、NEW_EVALUATION_TRIGGER
と入力してデフォルト値TRIGGER1
を上書きします。
ベース・オブジェクトでは、メニューからEVALUATIONS
を選択します。
INSERT
を「使用可能なイベント」から「選択済のイベント」に移動します。
(INSERT
を選択して「>」をクリックします。)
「文レベル」オプションを選択解除します。
「OK」をクリックします。
NEW_EVALUATION_TRIGGER
ペインが開き、トリガーを作成したCREATE
TRIGGER
文が表示されます。
CREATE OR REPLACE TRIGGER NEW_EVALUATION_TRIGGER BEFORE INSERT ON EVALUATIONS FOR EACH ROW BEGIN NULL; END;
NEW_EVALUATION_TRIGGER
ペインのタイトルがイタリック・フォントになっています。これは、トリガーがまだデータベースに保存されていないことを示しています。
CREATE
TRIGGER
文で、NULL
を次と置き換えます。
:NEW.evaluation_id := evaluations_sequence.NEXTVAL
「ファイル」メニューから、「保存」を選択します。
Oracle Databaseは、プロシージャをコンパイルして保存します。NEW_EVALUATION_TRIGGER
ペインのタイトルがイタリック・フォントではなくなります。
ビューは、問合せの出力を表形式で表します。表の変更と同時にビューも変更する場合、INSTEAD
OF
トリガーを作成する必要があります。このトリガーは、ビューを変更するかわりに基礎となる表を変更します。
たとえば、EMP_LOCATIONS
というビューを検討します。 NAME
列は、EMPLOYEES
表のLAST_NAME
およびFIRST_NAME
列から作成されています。
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;
ビューEMP_LOCATIONS
.NAME
(「CREATE VIEW文によるビューの作成」で作成)を更新するには、EMPLOYEES
.LAST_NAME
およびEMPLOYEES
.FIRST_NAME
を更新する必要があります。これは、例6-1
のINSTEAD
OFトリガーによって実行されます。
OLD
とNEW
は擬似レコードです。行レベルのトリガーが起動したときにPL/SQL実行時エンジンによって作成され、それぞれ値を入れられます。 OLD
およびNEW
は、トリガーによって処理されているレコードの元の値と新しい値をそれぞれ格納します。PL/SQLレコードの一部のプロパティを持たないため、疑似レコードと呼ばれます。
例6-1 INSTEAD OFトリガーの作成
CREATE OR REPLACE TRIGGER update_name_view_trigger INSTEAD OF UPDATE ON emp_locations BEGIN 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;
参照:
|
このチュートリアルでは、CREATE
TRIGGER
文を使用して、HR_LOGON_TRIGGER
とHR_LOGOFF_TRIGGER
の2つのトリガーを作成する方法を説明します。ユーザーHR
としてログオンした後、HR_LOGON_TRIGGER
はHR_USERS_LOG
表に行を追加します。ユーザーHR
としてログオフする前に、HR_LOGOFF_TRIGGER
はHR_USERS_LOG
表に行を追加します。
HR_LOGON_TRIGGER
およびHR_LOGOFF_TRIGGER
はシステム・トリガーです。HR_LOGON_TRIGGER
はAFTERトリガー、HR_LOGOFF_TRIGGER
はBEFOREトリガーです。
HR_USERS_LOG、HR_LOGON_TRIGGERおよびHR_LOGOFF_TRIGGERを作成するには、次の手順を実行します。
HR_USERS_LOG
表を作成します。
CREATE TABLE hr_users_log ( user_name VARCHAR2(30), activity VARCHAR2(20), event_date DATE );
hr_logon_trigger
を作成します。
CREATE OR REPLACE TRIGGER hr_logon_trigger AFTER LOGON ON HR.SCHEMA BEGIN INSERT INTO hr_users_log (user_name, activity, event_date) VALUES (USER, 'LOGON', SYSDATE); END;
hr_logoff_trigger
を作成します。
CREATE OR REPLACE TRIGGER hr_logoff_trigger BEFORE LOGOFF ON HR.SCHEMA BEGIN INSERT INTO hr_users_log (user_name, activity, event_date) VALUES (USER, 'LOGOFF', SYSDATE); END;
参照: システム・トリガーの詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。 |
トリガーを変更するには、SQL Developerの編集ツールを使用するか、OR
REPLACE
句を指定してCREATE
TRIGGER
DDL文を使用します。
編集ツールを使用してトリガーを変更するには、次の手順を実行します。
「接続」フレームで、hr_connを展開します。
スキーマ・オブジェクト・タイプのリストで、「トリガー」を展開します。
トリガーのリストで、変更するトリガーをクリックします。
「接続」フレームの右側の「コード」ペインに、トリガーを作成したコードが表示されます。
「コード」ペインが書込みモードになっています。(鉛筆アイコンをクリックすると、モードが書込みモードから読取り専用モードに、またはその逆に切り替わります。)
「コード」ペインで、コードを変更します。
ペインのタイトルはイタリック・フォントになっており、変更がデータベースに保存されていないことを示しています。
「ファイル」メニューから、「保存」を選択します。
Oracle Databaseは、トリガーをコンパイルして保存します。ペインのタイトルがイタリック・フォントではなくなります。
参照:
|
トリガーが使用不可能なオブジェクトを参照している場合、またはトリガーが原因である遅延なしに大規模なデータのアップロードを実行する必要がある場合(リカバリ操作など)、トリガーを一時的に無効にする必要があります。参照されたオブジェクトが使用可能になった後、またはデータのアップロード終了後に、トリガーを再度有効にすることができます。
この項の内容は次のとおりです。
参照:
|
単一のトリガーを無効化または有効化するには、トリガーの無効化/トリガーの有効化ツール、あるいはDISABLE
またはENABLE
句を指定してALTER
TRIGGER
文を使用します。
たとえば、次の文ではeval_change_trigger
を無効化および有効化します。
ALTER TRIGGER eval_change_trigger DISABLE; ALTER TRIGGER eval_change_trigger ENABLE;
トリガーの無効化/トリガーの有効化ツールを使用するには、次の手順を実行します。
「接続」フレームで、hr_connを展開します。
スキーマ・オブジェクト・タイプのリストで、「トリガー」を展開します。
トリガーのリストで、対象のトリガーを右クリックします。
選択肢のリストで、「無効化」または「有効化」を選択します。
「無効化」または「有効化」ウィンドウで、「適用」をクリックします。
「確認」ウィンドウで「OK」をクリックします。
特定の表のすべてのトリガーを無効化または有効化するには、すべてのトリガーの無効化/すべてのトリガーの有効化ツール、あるいはDISABLE
ALL
TRIGGERS
またはENABLE
ALL
TRIGGERS
句を指定してALTER
TABLE
文を使用します。
たとえば、次の文ではevaluations
表のすべてのトリガーを無効化および有効化します。
ALTER TABLE evaluations DISABLE ALL TRIGGERS; ALTER TABLE evaluations ENABLE ALL TRIGGERS;
すべてのトリガーの無効化/すべてのトリガーの有効化ツールを使用するには、次の手順を実行します。
「接続」フレームで、hr_connを展開します。
スキーマ・オブジェクト・タイプのリストで、「表」を展開します。
表のリストで、対象の表を右クリックします。
選択肢のリストで、「トリガー」を選択します。
選択肢のリストで、「すべて無効化」または「すべて有効化」を選択します。
「すべて無効化」または「すべて有効化」ウィンドウで、「適用」をクリックします。
「確認」ウィンドウで「OK」をクリックします。
CREATE
TRIGGER
文を実行すると、作成中のトリガーがコンパイルされます。このコンパイルでエラーが発生した場合、CREATE
TRIGGER
文は失敗します。コンパイル・エラーを表示するには、このビューを使用します。
SELECT * FROM USER_ERRORS WHERE TYPE = 'TRIGGER';
コンパイルされたトリガーは、トリガーが定義されたスキーマ・オブジェクトに依存します。たとえば、NEW_EVALUATION_TRIGGER
はEVALUATIONS
表に依存します。
CREATE OR REPLACE TRIGGER NEW_EVALUATION_TRIGGER BEFORE INSERT ON EVALUATIONS FOR EACH ROW BEGIN :NEW.evaluation_id := evaluations_seq.NEXTVAL; END;
トリガーが依存するスキーマ・オブジェクトを表示するには、次の文を使用します。
SELECT * FROM ALL_DEPENDENCIES WHERE TYPE = 'TRIGGER';
トリガーが依存するオブジェクトが削除された場合、またはトリガーとオブジェクトが一致しないような変更が行われた場合、トリガーは無効化されます。トリガーは、次の起動時に再コンパイルされます。トリガーをすぐに再コンパイルするには、COMPILE
句を含むALTER
TRIGGER
文を使用します。次に例を示します。
ALTER TRIGGER NEW_EVALUATION_TRIGGER COMPILE;
参照: トリガーのコンパイルおよび依存性の詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。 |
トリガーが依存するオブジェクトを削除する前に、トリガーを削除する必要があります。
トリガーを削除するには、SQL Developerの「接続」フレームと削除ツールまたはDDL文のDROP
TRIGGER
を使用します。
この文は、トリガーEVAL_CHANGE_TRIGGER
を削除します。
DROP TRIGGER EVAL_CHANGE_TRIGGER;
削除ツールを使用してトリガーを削除するには、次の手順を実行します。
「接続」フレームで、hr_connを展開します。
スキーマ・オブジェクト・タイプのリストで、「トリガー」を展開します。
トリガーのリストで、削除するトリガーの名前を右クリックします。
選択肢のリストで、「トリガーの削除」をクリックします。
削除ウィンドウで、「適用」をクリックします。
「確認」ウィンドウで「OK」をクリックします。
参照:
|