Oracle PL / SQL - Exemple INSTEAD OF Trigger
Cet article vous montre comment utiliserINSTEAD OF TRIGGER pour mettre à jour
-
Une vue sans édition
-
Une colonne de table imbriquée d'une vue sans édition
Ces déclencheursINSTEAD OF fournissent un moyen de modifier lesviews qui ne peuvent pas être modifiés directement via des instructions DML comme INSERT, UPDATE et DELETE
Un déclencheur INSTEAD OF est
-
Toujours un déclencheur au niveau des lignes.
-
Peut lire les valeurs ANCIENNES et NOUVELLES, mais ne peut pas les modifier.
-
Ne peut pas être conditionnel. Cela signifie que nous ne pouvons pas ajouter de condition WHEN ou IF.
1. Insérer des données dans une vue
Dans cet exemple, nous avons créé un déclencheurINSTEAD OF qui insérera des lignes dans les tables respectives d'unview lorsque nous exécutons l'instruction d'insertion sur une vue.
1.1 Create tables.
Détails du client
CREATE TABLE customer_details
(
customer_id number(10) primary key,
customer_name varchar2(20),
country varchar2(20)
);
projects_details
CREATE TABLE projects_details
(
project_id number(10) primary key,
project_name varchar2(30),
project_start_Date date,
customer_id number(10) references customer_details(customer_id)
);
1.2 Create customer_projects_view view to get results of customers and their projects.
customer_projects_view
CREATE OR REPLACE VIEW customer_projects_view AS
SELECT cust.customer_id, cust.customer_name, cust.country,
projectdtls.project_id, projectdtls.project_name,
projectdtls.project_start_Date
FROM customer_details cust, projects_details projectdtls
WHERE cust.customer_id = projectdtls.customer_id;
1.3 If we INSERT INTO customer_projects_view view directly, the database will raise the following error :
INSERT INTO customer_projects_view VALUES (1,'XYZ Enterprise','Japan',101,'Library management',sysdate);
-- output
SQL Error: ORA-01779: cannot modify a column which maps to a non key-preserved table
01779. 00000 - "cannot modify a column which maps to a non key-preserved table"
*Cause: An attempt was made to insert or update columns of a join view which
map to a non-key-preserved table.
*Action: Modify the underlying base tables directly.
1.4 Instead, we should create a INSTEAD OF trigger on the view to perform the actual operation.
trg_cust_proj_view_insert
CREATE OR REPLACE TRIGGER trg_cust_proj_view_insert
INSTEAD OF INSERT ON customer_projects_view
DECLARE
duplicate_info EXCEPTION;
PRAGMA EXCEPTION_INIT (duplicate_info, -00001);
BEGIN
INSERT INTO customer_details
(customer_id,customer_name,country)
VALUES (:new.customer_id, :new.customer_name, :new.country);
INSERT INTO projects_details (project_id, project_name, project_start_Date, customer_id)
VALUES (
:new.project_id,
:new.project_name,
:new.project_start_Date,
:new.customer_id);
EXCEPTION
WHEN duplicate_info THEN
RAISE_APPLICATION_ERROR (
num=> -20107,
msg=> 'Duplicate customer or project id');
END trg_cust_proj_view_insert;
1.5 Insert into view again. Le déclencheurINSTEAD OF sera déclenché et insérera les données dans la table réelle.
INSERT INTO customer_projects_view VALUES (1,'XYZ Enterprise','Japan',101,'Library management',sysdate); INSERT INTO customer_projects_view VALUES (2,'ABC Infotech','India',202,'HR management',sysdate);
1.6 Select table.
SELECT * FROM customer_details;
N ° DE CLIENT
CUSTOMER_NAME
PAYS
1
Entreprise XYZ
Japon
2
ABC Infotech
Inde
SELECT * FROM projects_details;
| PROJECT_ID | NOM DU PROJET | PROJECT_START_DATE | N ° DE CLIENT |
|---|---|---|---|
101 |
Gestion de la bibliothèque |
25-JUIN-17 |
1 |
202 |
gestion des ressources humaines |
25-JUIN-17 |
2 |
1.7 Select view.
SELECT * FROM customer_projects_view;
| N ° DE CLIENT | CUSTOMER_NAME | PAYS | PROJECT_ID | NOM DU PROJET | PROJECT_START_DATE |
|---|---|---|---|---|---|
1 |
Entreprise XYZ |
Japon |
101 |
Gestion de la bibliothèque |
25-JUIN-17 |
2 |
ABC Infotech |
Inde |
202 |
gestion des ressources humaines |
25-JUIN-17 |
2. Colonne de vue de table imbriquée
Exemple pour insérer des données dans une colonne de vue de table imbriquée avec INSTEAD OF Trigger.
2.1 Create table, type, nested table view column for testing.
vehicule_mfg_company_details
CREATE TABLE vehicle_mfg_company_details ( company_id number(10) primary key, company_name varchar2(50) NOT NULL );
les détails du véhicule
CREATE TABLE vehicle_details ( vehicle_id number(10) primary key, company_id number(10) references vehicle_mfg_company_details(company_id), vehicle_model_name varchar2(50) NOT NULL );
nestedTableEle
CREATE OR REPLACE TYPE nestedTableEle IS OBJECT ( vehicle_id NUMBER(10), vehicle_model_name VARCHAR2(50) );
Vehicle_details_list_
-- nested table view column CREATE OR REPLACE TYPE vehicle_details_list_ IS TABLE OF nestedTableEle;
2.2 Create a View.
company_vehicles_view
CREATE OR REPLACE VIEW company_vehicles_view AS
SELECT company.company_id,
company.company_name,
CAST (MULTISET (SELECT vehicle.vehicle_id, vehicle.vehicle_model_name
FROM vehicle_details vehicle
WHERE vehicle.company_id = company.company_id
)
AS vehicle_details_list_
) vehiclelist
FROM vehicle_mfg_company_details company;
2.3 Insert data into nested table view column.
-- no error.
INSERT INTO vehicle_mfg_company_details VALUES (101,'Ford');
-- error
INSERT INTO TABLE (
SELECT vw.vehiclelist
FROM company_vehicles_view vw
WHERE company_id = 101
)
VALUES (1, 'EcoSport');
-- output
SQL Error: ORA-25015: cannot perform DML on this nested table view column
25015. 00000 - "cannot perform DML on this nested table view column"
*Cause: DML cannot be performed on a nested table view column except through
an INSTEAD OF trigger
*Action: Create an INSTEAD OF trigger over the nested table view column
and then perform the DML.
2.4 Create a INSTEAD OF trigger
trg_comp_vehicles_view_insrt
CREATE OR REPLACE TRIGGER trg_comp_vehicles_view_insrt
INSTEAD OF INSERT ON NESTED TABLE vehiclelist OF company_vehicles_view
REFERENCING NEW AS Vehicle
PARENT AS Company
FOR EACH ROW
BEGIN
-- Insert on nested table translates to insert on base table.
INSERT INTO vehicle_details (
vehicle_id,
company_id,
vehicle_model_name
)
VALUES (
:Vehicle.vehicle_id,
:Company.company_id,
:Vehicle.vehicle_model_name
);
END;
2.5 Insert data into nested table view column again.
INSERT INTO TABLE ( SELECT vw.vehiclelist FROM company_vehicles_view vw WHERE company_id = 101 ) VALUES (1, 'EcoSport'); INSERT INTO TABLE ( SELECT vw.vehiclelist FROM company_vehicles_view vw WHERE company_id = 101 ) VALUES (2, 'Endeavour');
2.6 Display table.
select * from vehicle_mfg_company_details;
| COMPANY_ID | NOM DE LA COMPAGNIE |
|---|---|
101 |
Ford |
select * from vehicle_details;
| VEHICLE_ID | COMPANY_ID | VEHICLE_MODEL_NAME |
|---|---|---|
1 |
101 |
EcoSport |
2 |
101 |
Effort |