Oracle PL/SQL - UPDATEトリガの例

Oracle PL / SQL – UPDATEトリガーの前の例

この記事では、BEFORE UPDATE TRIGGERの使用方法を説明します。これは、更新操作が実行される前に発生します。 現実のシナリオでは、主に次のような目的で使用されます。

  1. データ検証

  2. 値を自動的に更新する

  3. データロギング、または監査

1. データ検証

一部の企業に求人があり、すでにアプリケーションデータがあり、基準は次のとおりであるとします。

  1. 職歴は3年以上でなければならず、

  2. 過去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_BYUPDATED_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日