Oracle PL / SQL – UPDATEトリガーの前の例
この記事では、BEFORE UPDATE TRIGGER
の使用方法を説明します。これは、更新操作が実行される前に発生します。 現実のシナリオでは、主に次のような目的で使用されます。
-
データ検証
-
値を自動的に更新する
-
データロギング、または監査
1. データ検証
一部の企業に求人があり、すでにアプリケーションデータがあり、基準は次のとおりであるとします。
-
職歴は3年以上でなければならず、
-
過去2年間に以前の申請を試みてはなりません。
データの整合性を確保するために、BEFORE UPDATE
トリガーを作成し、上記の基準のいずれかに違反するデータのUPDATEを制限します。
1.1 First, we will create table job_openings.
job_openings
--Creating job_openings table. CREATE TABLE job_openings ( APPLICATION_ID number(10) primary key, FIRST_NAME varchar2(50), LAST_NAME varchar2(50), JOB_EXPERIENCE number(2), LAST_APPLIED_DATE date );
1.2 Then we will create a before update tigger on column JOB_EXPERIENCE
and LAST_APPLIED_DATE
of job_openings table.
trg_before_emp_update
-- Creating TRIGGER CREATE OR REPLACE TRIGGER trg_before_emp_update BEFORE UPDATE OF JOB_EXPERIENCE,LAST_APPLIED_DATE on job_openings FOR EACH ROW DECLARE years_since_last_applied number(5); BEGIN years_since_last_applied := -1; IF(:NEW.LAST_APPLIED_DATE IS NOT NULL) THEN SELECT MONTHS_BETWEEN(TO_DATE(sysdate,'DD-MON-YYYY'), TO_DATE(:NEW.LAST_APPLIED_DATE,'DD-MON-YYYY'))/12 INTO years_since_last_applied FROM dual; -- Check whether years_since_last_applied is greater than 2 years or not IF (years_since_last_applied <= 2) THEN RAISE_APPLICATION_ERROR(-20000,'Previous application attempt must not be done in last 2 years.'); END IF; END IF; -- Job experience must be more than or equal to 3 years. IF(:new.JOB_EXPERIENCE < 3) THEN RAISE_APPLICATION_ERROR(-20000,'Job experience must be more than or equal to 3 years.'); END IF; END;
1.3 Normal Data.
-- setting date format to to 'DD-MON-YYYY' alter session set nls_date_format = 'DD-MON-YYYY'; INSERT INTO job_openings VALUES (1,'Mark','Sharma',10,'01-JAN-2012'); INSERT INTO job_openings VALUES (2,'Praveen','Kumar',4,'01-DEC-2010'); INSERT INTO job_openings VALUES (3,'Rahul','Kohli',6,null); -- output 1 rows inserted. 1 rows inserted. 1 rows inserted.
select * from job_openings;
アプリケーションID |
ファーストネーム |
苗字 |
JOB_EXPERIENCE |
LAST_APPLIED_DATE |
1 |
Mark |
シャルマ |
10 |
2012年1月1日 |
2 |
Praveen |
クマール |
4 |
2010年12月1日 |
3 |
ラフル |
コーリ |
6 |
null |
1.4 Test Trigger raise error – Job experience must be more than or equal to 3 years.
-- Try to update job_experience less than 3 years UPDATE job_openings SET JOB_EXPERIENCE = 2 where APPLICATION_ID = 1; -- error Error report - ORA-20000: Job experience must be more than or equal to 3 years. ORA-06512: at "SYSTEM.TRG_BEFORE_EMP_UPDATE", line 21 ORA-04088: error during execution of trigger 'SYSTEM.TRG_BEFORE_EMP_UPDATE'
1.5 Test Trigger raise error – Previous application attempt must not be done in last 2 years.
-- Try to update last_Applied_Date which is less than 2 years UPDATE job_openings SET LAST_APPLIED_DATE = '10-JUN-2016' where APPLICATION_ID = 3; -- error Error report - ORA-20000: Previous application attempt must not be done in last 2 years. ORA-06512: at "SYSTEM.TRG_BEFORE_EMP_UPDATE", line 15 ORA-04088: error during execution of trigger 'SYSTEM.TRG_BEFORE_EMP_UPDATE'
2. 値を更新する
BEFORE UPDATE
トリガーの例は、:NEW.UPDATED_BY
と:NEW.UPDATED_DATE
を自動的に更新します。
2.1 Create a table.
person_records
--Creating person_records table. CREATE TABLE person_records ( PERSON_ID number(10) primary key, FIRST_NAME varchar2(50), LAST_NAME varchar2(50), HIRE_DATE date, UPDATED_BY varchar2(20), UPDATED_DATE date );
2.2 Create a before update trigger on table person_records
trg_before_person_update
CREATE OR REPLACE TRIGGER trg_before_person_update BEFORE UPDATE on person_records FOR EACH ROW DECLARE username varchar2(20); BEGIN SELECT USER INTO username FROM dual; -- Setting updated_by and updated_Date values. :NEW.UPDATED_BY := username; :NEW.UPDATED_DATE := sysdate; END;
2.3 Insert two records.
-- setting date format to to 'DD-MON-YYYY' alter session set nls_date_format = 'DD-MON-YYYY'; INSERT INTO person_records VALUES (101,'Devil','Khedut',sysdate,null,null); INSERT INTO person_records VALUES (102,'Kanji','Yadav',sysdate,null,null); -- output 1 rows inserted. 1 rows inserted.
select * from person_records;
PERSON_ID |
ファーストネーム |
苗字 |
HIRE_DATE |
UPDATED_BY |
UPDATED_DATE |
101 |
悪魔 |
Khedut |
2017年6月6日 |
null |
null |
102 |
漢字 |
ヤーダブ |
2017年6月6日 |
null |
null |
2.4 Update records and it will fires the before update trigger. UPDATED_BY
とUPDATED_DATE
の値は自動的に更新されます。
UPDATE person_records SET first_name = 'Lavji' WHERE person_id = 101; UPDATE person_records SET first_name = 'Jogi' WHERE person_id = 102; -- output 1 rows updated. 1 rows updated.
select * from person_records;
PERSON_ID |
ファーストネーム |
苗字 |
HIRE_DATE |
UPDATED_BY |
UPDATED_DATE |
101 |
ラブジ |
Khedut |
2017年6月6日 |
HR |
2017年6月6日 |
102 |
Jogi |
ヤーダブ |
2017年6月6日 |
HR |
2017年6月6日 |
3. Logging/Auditing data
この例では、トランザクションテーブルが更新されるたびに監査テーブルに行を挿入するトリガーを作成しました。 ユーザーがbank_transactions
のデータを更新するたびに、古いデータは監査またはバックアップの目的でトリガーによってbank_transactions_audit
に挿入されます。
3.1 Create a bank transaction table.
bank_transactions
--Creating bank_transactions table. CREATE TABLE bank_transactions ( TXN_ID number(10) primary key, TXN_NUMBER varchar2(20), PARTY_NAME varchar2(50), TXN_DATE date, CREATED_BY varchar2(20), CREATED_DATE date );
3.2 Create another bank transaction audit table.
bank_transactions_audit
--Creating bank_transactions_audit table. CREATE TABLE bank_transactions_audit ( TXN_ID number(10), TXN_NUMBER varchar2(20), PARTY_NAME varchar2(50), TXN_DATE date, CREATED_BY varchar2(20), CREATED_DATE date );
3.3 Create a before update trigger on bank_transactions
table.
trg_before_update_txn_audit
--Creating Trigger CREATE OR REPLACE TRIGGER trg_before_update_txn_audit BEFORE UPDATE ON bank_transactions FOR EACH ROW BEGIN -- Insert OLD values in audit table for logging purpose INSERT INTO bank_transactions_audit VALUES(:OLD.TXN_ID,:OLD.TXN_NUMBER, :OLD.PARTY_NAME,:OLD.TXN_DATE,:OLD.CREATED_BY,:OLD.CREATED_DATE); END;
3.4 Insert some records.
--Inserting values INSERT INTO BANK_TRANSACTIONS values ('1','TXN1234','Peter Thomas','12-MAY-2017','HR',sysdate); INSERT INTO BANK_TRANSACTIONS values ('2','TXN9999','Jemes Patel','10-JUN-2016','HR',sysdate); select * from BANK_TRANSACTIONS;
TXN_ID |
TXN_NUMBER |
PARTY_NAME |
TXN_DATE |
によって作成された |
作成日 |
1 |
TXN1234 |
ピータートーマス |
2017年5月12日 |
HR |
2017年6月6日 |
2 |
TXN9999 |
ジェメス・パテル |
2016年6月10日 |
HR |
2017年6月6日 |
3.5 Insert operation didn’t fire the before update trigger.
select * from BANK_TRANSACTIONS_AUDIT; -- output no rows selected.
3.6 Update records, it will fires the "before update" trigger and insert the old data into another audit table.
--updating values. UPDATE bank_transactions SET txn_number = 'NEWTXN8080' WHERE txn_id = 1; UPDATE bank_transactions SET txn_number = 'NEWTXN9595' WHERE txn_id = 2; -- output 1 rows updated. 1 rows updated.
select * from BANK_TRANSACTIONS;
TXN_ID |
TXN_NUMBER |
PARTY_NAME |
TXN_DATE |
によって作成された |
作成日 |
1 |
NEWTXN8080 |
ピータートーマス |
2017年5月12日 |
HR |
2017年6月6日 |
2 |
NEWTXN9595 |
ジェメス・パテル |
2016年6月10日 |
HR |
2017年6月6日 |
select * from BANK_TRANSACTIONS_AUDIT;
TXN_ID |
TXN_NUMBER |
PARTY_NAME |
TXN_DATE |
によって作成された |
作成日 |
1 |
TXN1234 |
ピータートーマス |
2017年5月12日 |
HR |
2017年6月6日 |
2 |
TXN9999 |
ジェメス・パテル |
2016年6月10日 |
HR |
2017年6月6日 |
参考文献
-
https://docs.oracle.com/cloud/latest/db112/LNPLS/create_trigger.htm#LNPLS01374 [Oracle
-
CREATE TRIGGERステートメント]
-
-
https://docs.oracle.com/cloud/latest/db112/LNPLS/triggers.htm#LNPLS020 [Oracle
-
PL/SQL Triggers]
-