Oracle PL / SQL - Vor dem UPDATE Trigger-Beispiel
Dieser Artikel zeigt Ihnen, wie SieBEFORE UPDATE TRIGGER
verwenden. Es wird ausgelöst, bevor der Aktualisierungsvorgang ausgeführt wird. In realen Szenarien wird es hauptsächlich für folgende Zwecke verwendet:
-
Datenvalidierung
-
Werte automatisch aktualisieren
-
Datenprotokollierung oder Überwachung
1. Datenvalidierung
Angenommen, einige Unternehmen haben offene Stellen und bereits Bewerbungsdaten. Die Kriterien sind:
-
Die Berufserfahrung muss mindestens 3 Jahre betragen
-
Ein vorheriger Bewerbungsversuch darf nicht in den letzten 2 Jahren durchgeführt werden.
Um die Datenintegrität sicherzustellen, erstellen wir den TriggerBEFORE UPDATE
und beschränken UPDATE auf Daten, die gegen eines der oben genannten Kriterien verstoßen.
1.1 First, we will create table job_openings.
Stellenangebote
--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;
APPLICATION_ID |
VORNAME |
NACHNAME |
BERUFSERFAHRUNG |
LAST_APPLIED_DATE |
1 |
Mark |
Sharma |
10 |
01. Januar 2012 |
2 |
Praveen |
Kumar |
4 |
01. DEZ-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. Werte aktualisieren
EinBEFORE UPDATE
löst ein Beispiel aus, um:NEW.UPDATED_BY
und:NEW.UPDATED_DATE
automatisch zu aktualisieren.
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 |
VORNAME |
NACHNAME |
ANSTELLUNGSDATUM |
AKTUALISIERT VON |
NEUES DATUM |
101 |
Teufel |
Khedut |
06-JUN-2017 |
null |
null |
102 |
Kanji |
Yadav |
06-JUN-2017 |
null |
null |
2.4 Update records and it will fires the before update trigger. Die Werte vonUPDATED_BY
undUPDATED_DATE
werden automatisch aktualisiert.
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 |
VORNAME |
NACHNAME |
ANSTELLUNGSDATUM |
AKTUALISIERT VON |
NEUES DATUM |
101 |
Lavji |
Khedut |
06-JUN-2017 |
HR |
06-JUN-2017 |
102 |
Jogi |
Yadav |
06-JUN-2017 |
HR |
06-JUN-2017 |
3. Logging/Auditing data
In diesem Beispiel haben wir einen Trigger erstellt, der vor jeder Aktualisierung der Transaktionstabelle Zeilen in eine Prüftabelle einfügt. Immer wenn Benutzer UPDATE-Daten vonbank_transactions
verwenden, werden die alten Daten per Trigger für Prüfungs- oder Sicherungszwecke inbank_transactions_audit
eingefügt.
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 |
PARTEINAMEN |
TXN_DATE |
ERSTELLT VON |
CREATED_DATE |
1 |
TXN1234 |
Peter Thomas |
12. MAI 2017 |
HR |
06-JUN-2017 |
2 |
TXN9999 |
Jemes Patel |
10. Juni 2016 |
HR |
06-JUN-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 |
PARTEINAMEN |
TXN_DATE |
ERSTELLT VON |
CREATED_DATE |
1 |
NEWTXN8080 |
Peter Thomas |
12. MAI 2017 |
HR |
06-JUN-2017 |
2 |
NEWTXN9595 |
Jemes Patel |
10. Juni 2016 |
HR |
06-JUN-2017 |
select * from BANK_TRANSACTIONS_AUDIT;
TXN_ID |
TXN_NUMBER |
PARTEINAMEN |
TXN_DATE |
ERSTELLT VON |
CREATED_DATE |
1 |
TXN1234 |
Peter Thomas |
12. MAI 2017 |
HR |
06-JUN-2017 |
2 |
TXN9999 |
Jemes Patel |
10. Juni 2016 |
HR |
06-JUN-2017 |
Verweise
-
https://docs.oracle.com/cloud/latest/db112/LNPLS/create_trigger.htm#LNPLS01374 [Oracle
-
CREATE TRIGGER-Anweisung]
-
-
https://docs.oracle.com/cloud/latest/db112/LNPLS/triggers.htm#LNPLS020 [Oracle
-
PL/SQL Triggers]
-