Oracle PL / SQL - Exemple de déclencheur avant UPDATE
Cet article vous montre comment utiliserBEFORE UPDATE TRIGGER, il se déclenche avant que l’opération de mise à jour ne soit exécutée. Dans les scénarios de la vie réelle, il est principalement utilisé à des fins telles que:
-
La validation des données
-
Mettre à jour les valeurs automatiquement
-
Enregistrement des données ou audit
1. La validation des données
Supposons que certaines entreprises aient des offres d'emploi et disposent déjà de données de candidature et que les critères soient:
-
L'expérience professionnelle doit être supérieure ou égale à 3 ans et
-
La tentative d'application précédente ne doit pas être effectuée au cours des 2 dernières années.
Pour assurer l'intégrité des données, nous créerons le déclencheurBEFORE UPDATE et il limitera UPDATE sur les données qui violent l'un des critères ci-dessus.
1.1 First, we will create table job_openings.
jobs_ouvertures
--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 D'APPLICATION |
PRÉNOM |
NOM DE FAMILLE |
EXPÉRIENCE DE TRAVAIL |
LAST_APPLIED_DATE |
1 |
Mark |
Sharma |
10 |
01-JAN-2012 |
2 |
Praveen |
Kumar |
4 |
01-DÉC-2010 |
3 |
Rahul |
Kohli |
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. Mettre à jour les valeurs
Un exemple de déclenchement deBEFORE UPDATE pour mettre à jour automatiquement:NEW.UPDATED_BY et: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 |
PRÉNOM |
NOM DE FAMILLE |
DATE D'EMBAUCHE |
MIS À JOUR PAR |
UPDATED_DATE |
101 |
Diable |
Khedut |
06-JUIN-2017 |
null |
null |
102 |
Kanji |
Yadav |
06-JUIN-2017 |
null |
null |
2.4 Update records and it will fires the before update trigger. Les valeurs deUPDATED_BY etUPDATED_DATE seront mises à jour automatiquement.
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 |
PRÉNOM |
NOM DE FAMILLE |
DATE D'EMBAUCHE |
MIS À JOUR PAR |
UPDATED_DATE |
101 |
Lavji |
Khedut |
06-JUIN-2017 |
HR |
06-JUIN-2017 |
102 |
Jogi |
Yadav |
06-JUIN-2017 |
HR |
06-JUIN-2017 |
3. Logging/Auditing data
Dans cet exemple, nous avons créé un déclencheur qui insérera des lignes dans une table d'audit avant chaque mise à jour de la table de transaction. Chaque fois que l'utilisateur UPDATE des données debank_transactions, les anciennes données seront insérées dansbank_transactions_audit par déclencheur à des fins d'audit ou de sauvegarde.
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 |
NOM DE LA FÊTE |
TXN_DATE |
CRÉÉ PAR |
CREATED_DATE |
1 |
TXN1234 |
Peter Thomas |
12-MAI-2017 |
HR |
06-JUIN-2017 |
2 |
TXN9999 |
Jemes Patel |
10-JUIN-2016 |
HR |
06-JUIN-2017 |
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 |
NOM DE LA FÊTE |
TXN_DATE |
CRÉÉ PAR |
CREATED_DATE |
1 |
NOUVEAUTXN8080 |
Peter Thomas |
12-MAI-2017 |
HR |
06-JUIN-2017 |
2 |
NOUVEAUTXN9595 |
Jemes Patel |
10-JUIN-2016 |
HR |
06-JUIN-2017 |
select * from BANK_TRANSACTIONS_AUDIT;
TXN_ID |
TXN_NUMBER |
NOM DE LA FÊTE |
TXN_DATE |
CRÉÉ PAR |
CREATED_DATE |
1 |
TXN1234 |
Peter Thomas |
12-MAI-2017 |
HR |
06-JUIN-2017 |
2 |
TXN9999 |
Jemes Patel |
10-JUIN-2016 |
HR |
06-JUIN-2017 |
Références
-
https://docs.oracle.com/cloud/latest/db112/LNPLS/create_trigger.htm#LNPLS01374 [Oracle
-
Instruction CREATE TRIGGER]
-
-
https://docs.oracle.com/cloud/latest/db112/LNPLS/triggers.htm#LNPLS020 [Oracle
-
PL/SQL Triggers]
-