Oracle PL/SQL - Exemple de déclencheur INSTEAD OF

Oracle PL / SQL - Exemple INSTEAD OF Trigger

Cet article vous montre comment utiliserINSTEAD OF TRIGGER pour mettre à jour

  1. Une vue sans édition

  2. 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

  1. Toujours un déclencheur au niveau des lignes.

  2. Peut lire les valeurs ANCIENNES et NOUVELLES, mais ne peut pas les modifier.

  3. 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