• Aucun résultat trouvé

Les déclencheurs (Triggers) avec Oracle

N/A
N/A
Protected

Academic year: 2023

Partager "Les déclencheurs (Triggers) avec Oracle"

Copied!
23
0
0

Texte intégral

(1)

1

Les déclencheurs (Triggers) avec Oracle

Sommaire

1) Introduction

2) Événements déclenchant 3) Mécanisme général

4) Privilèges systèmes

5) Création/destruction/manipulation d’un déclencheur 6) Option BEFORE ou AFTER

7) Déclencheur LMD 8) Déclencheur LDD

9) Déclencheur d'instance

10) Création de déclencheurs avec SQL Developer

11) Nouveautés 11g

E.Porcq : Cours BDD

- IUT : DUT Informatique M3106C Année 2019-2020

Sources :

SQL Pour Oracle 3è édition de Christian Soutou Les triggers d’Oracle de J. Akoka & I. Wattiau http://sheikyerbouti.developpez.com/pl_sql/?

page=Chap6

(2)

Les déclencheurs (Triggers) avec Oracle

1) Introduction

Les déclencheurs (triggers) sont des programmes associés à des objets dont l'exécution est lancée automatiquement (déclenchée) lors d'une mise à jour ceux-ci.

Ils se programment en PL/SQL; on peut aussi utiliser les langages C, C++, Java etc ... pour créer des déclencheurs.

Ils permettent de :

Programmer des règles de gestion qui n'ont pu être mises en places par des contraintes statiques

Déporter des contraintes au niveau serveur pour alléger le client

Programmer l'intégrité référentielle et la réplication dans les architectures distribuées avec l'utilisation de liens de données (database links).

Les déclencheurs

existent depuis la version 6 d'Oracle.

sont compilables depuis la version 7.3

Permettent la mise à jour de vues multitables depuis la version 8 (instead of)

(3)

3

Les déclencheurs (Triggers) avec Oracle

2) Événements déclenchant

Les événements déclencheurs peuvent être

Une instruction insert, update ou delete sur une table ou une vue. On parle de déclencheurs LMD

Une instruction create, alter ou drop sur un objet (table, index, séquence, etc...) On parle de déclencheurs LDD

Le démarrage ou l'arrêt de la base (startup ou shutdown), une erreur spécifique (no_data_found, dup_val_on_index, etc...), une connexion ou une déconnexion d'un utilisateur. On parle de déclencheurs d'instances 8 (instead of)

(4)

Les déclencheurs (Triggers) avec Oracle

3) Mécanisme général

Une fois codé puis compilé, le déclencheur est stocké dans la base En cas d'événement approprié, si le déclencheur est actif, il s'exécute

Le bloc PL/SQL qui constitue le trigger peut être exécuté avant ou après la vérification des contraintes d'intégrité

Il peut être exécuté pour chaque ligne affectée par l'ordre LMD ou bien une seule fois pour la commande

Un déclencheur s'exécute dans le cadre d'une transaction. Il ne peut donc pas contenir d'instruction commit ou rollback ou toute instruction générant une fin de transaction implicite (ordre LDD)

(5)

5

Les déclencheurs (Triggers) avec Oracle

4) Privilèges systèmes

Pour créer des déclencheurs, il faut disposer des privilèges systèmes CREATE TRIGGER (présent avec le rôle RESOURCE)

CREATE ANY TRIGGER (pour ceux des autres schémas)

ADMINISTER DATABSE TRIGGER (pour les déclencheurs d'instances)

(6)

Les déclencheurs (Triggers) avec Oracle

5) Création/destruction/manipulation d’un déclencheur

La syntaxe de création du déclencheur commence par :

CREATE [OR REPLACE] TRIGGER [<schéma>].<nom du déclencheur>

La syntaxe de destruction du déclencheur est :

DROP TRIGGER [<schéma>].<nom du déclencheur>

La syntaxe pour renommer un déclencheur est :

ALTER TRIGGER [<schéma>].<nom du déclencheur> RENAME TO [<schéma>].<nouveau nom du déclencheur>

La syntaxe pour compiler un déclencheur est :

ALTER TRIGGER [<schéma>].<nom du déclencheur> COMPILE;

La syntaxe pour rendre un déclencheur actif ou inactif :

ALTER TRIGGER [<schéma>].<nom du déclencheur> {ENABLE|

DISABLE};

Le nom doit être unique dans un même schéma.

Il peut avoir le nom d'un autre objet (table, vue, procédure) mais à éviter.

Ex : CREATE TRIGGER trigInsertCoureur

(7)

7

Les déclencheurs (Triggers) avec Oracle

6) Option before ou after

Elle précise le moment de l'exécution du déclencheur (avant ou après l'opération).

Avec l’option before, le déclencheur s’exécute avant une éventuelle contrainte d’intégrité portant sur la même table et/ou colonne.

Avec l’option after, le déclencheur s’exécutera peut être après une éventuelle contrainte d’intégrité portant sur la même table et/ou colonne.

Si le déclencheur n'a pas pour but d'interdire éventuellement l'opération déclenchante, il est préférable qu'il soit de type after

Dans un trigger after, la table concernée sera affectée avant l’exécution du trigger.

Ex : CREATE TRIGGER trigInsertCoureur before insert ...

(8)

Les déclencheurs (Triggers) avec Oracle

6) Option before ou after

Exemple 1

drop table essai;

create table essai ( a int,

b int,

constraint pk1 check (a is not null) );

CREATE OR REPLACE TRIGGER DEC_ESSAI XXXX

INSERT ON ESSAI for each row BEGIN

if :new.a is null then

raise_application_error(-20001,'pas nul');

else

dbms_output.put_line('ok');

end if;

dbms_output.put_line('fin');

END;

/

insert into essai values (null,4);

Avec cet exemple, on voit que before place l’exécution du déclencheur prioritaire sur la contrainte statique. After le place après la contrainte.

Avec before

Erreur SQL : ORA-20001: pas nul ORA-06512: à "ERIC.DEC_ESSAI", ligne 3

ORA-04088: erreur lors d'exécution du déclencheur 'ERIC.DEC_ESSAI'

Avec after

Erreur SQL : ORA-02290: violation de contraintes (ERIC.PK1) de

vérification

02290. 00000 - "check constraint (%s.%s) violated"

(9)

9

Les déclencheurs (Triggers) avec Oracle

6) Option before ou after

Exemple 2

drop table essai;

create table essai (a int, b char(10));

create or replace trigger trig_compte_essai XXX insert on essai

declare nb int;

begin

select count(*) into nb from essai;

dbms_output.put_line('nb :' || nb);

end;

/

insert into essai values (1,'toto');

Avec cet exemple, on voit que qu’avec before, le déclencheur s’exécute avant

l’insertion de données. C’est le contraire avec after.

Avec before

Avec after

(10)

Les déclencheurs (Triggers) avec Oracle

7) Déclencheur LMD 7-1) Déclencheur global ou ligne

Ils sont lancés par une opération insert ou update ou delete Le même déclencheur peut s'activer par les trois opérations

Pour update, on peut spécifier une liste de colonnes. Dans ce cas, le trigger ne se déclenchera que si l'instruction update porte sur l'une au moins des colonnes précisée dans la liste.

Ex : CREATE TRIGGER trigInsertCoureur before insert or delete on tdf_coureur

7-1) Déclencheur global ou ligne

un déclencheur ligne (row trigger) est exécuté pour chaque ligne concernée par l'opération LMD. On le distingue par la directive " for each row ".

un déclencheur global ou d'état (statement trigger) ou d'instruction ne s'exécute qu'une fois par instruction LMD

Ex : CREATE TRIGGER trigInsertCoureur before insert or update on tdf_coureur for each row

(11)

11

Les déclencheurs (Triggers) avec Oracle

7) Déclencheur LMD 7-2) Déclencheur ligne

avec ce type de déclencheur, on peut avoir accès (suivant l'opération LMD) à l'ancienne et/ou à la nouvelle donnée affectant la table.

pour un insert, toutes les colonnes de la ligne insérée sont accessibles. Elles se nomment :new.<nom de la colonne>

pour un delete, toutes les colonnes de la ligne supprimée sont accessibles.

Elles se nomment :old.<nom de la colonne>

pour un update, toutes les colonnes de la ligne supprimée et insérées sont accessibles. Elles se nomment :new.<nom de la colonne> :old.<nom de la colonne>

il est possible de restreindre l'exécution du déclencheur avec la clause when.

Si l'expression when n'est pas vérifiée le déclencheur ne s'exécute pas.

Ex CREATE TRIGGER trigInsertCoureur before insert or update on tdf_coureur for each row when (new.code_tdf = 'FRA')

La clause referencing peut permettre de renommer new et old

Ex CREATE TRIGGER trigInsertCoureur before insert or update on tdf_coureur for each row referencing NEW as nouveau

(12)

Les déclencheurs (Triggers) avec Oracle

7) Déclencheur LMD 7-2) Déclencheur ligne

Lorsque le même déclencheur peut être exécuté à partir d'opérations LMD

différentes, il est possible de tester dans le programme l'événement déclencheur avec les prédicats

If inserting then If deleting then if updating then

If updating[('<colonne>')] then

Exemple de déclencheur ligne

create or replace trigger SONDAGE_TRIG1 after insert or update on SONDAGE

for each row begin

dbms_output.put_line('début SONDAGE_TRIG1');

If inserting then

insert into sondage_copie values (

:new.num,:new.date_naissance,

:new.reponse1, :new.reponse2,:new.val );

End if ;

dbms_output.put_line('fin SONDAGE_TRIG1');

end;

(13)

13

Les déclencheurs (Triggers) avec Oracle

7) Déclencheur LMD 7-2) Déclencheur ligne

Lorsqu'un déclencheur s'exécute pour un update sur quelques colonnes, les attributs non utilisés prennent dans le programme les anciennes valeurs des enregistrements concernés : old = new

Exemple de déclencheur ligne

update sondage set val=10 where val=9;

CREATE OR REPLACE TRIGGER SONDAGE_TRIG0 AFTER UPDATE ON SONDAGE

FOR EACH ROW BEGIN

dbms_output.put_line('début SONDAGE_TRIG0');

dbms_output.put_line(:new.num||' '||:new.reponse1||' '||:new.reponse2||' '||:new.val);

dbms_output.put_line(:old.num||' '||:old.reponse1||' '||:old.reponse2||' '||:old.val);

dbms_output.put_line('fin SONDAGE_TRIG0');

END;

début SONDAGE_TRIG0 69 oui non 10 69 oui non 9 fin SONDAGE_TRIG0 début SONDAGE_TRIG0 70 oui non 10 70 oui non 9 fin SONDAGE_TRIG0

(14)

Les déclencheurs (Triggers) avec Oracle

7) Déclencheur LMD 7-3) Table en mutation

Un déclencheur ligne ne peut pas modifier la table concernée (appelée aussi table mutante) par l'instruction (insert, update ou delete) qui a déclenché ce trigger

Il peut éventuellement lire la table dans le cas d'un déclenchement par un insert de type before

CREATE OR REPLACE TRIGGER TRIGGER_MUTANT BEFORE UPDATE ON TDF_COUREUR

for each row BEGIN

update tdf_coureur set date_insert = sysdate where n_coureur = :new.n_coureur;

END;

Test : update tdf_coureur set nom = 'TAYOU' where nom = 'HINAULT'

Erreur SQL : ORA-04091: table PATRICE.TDF_COUREUR is mutating, trigger/function may not see it

ORA-06512: at "PATRICE.TRIGGER_MUTANT", line 2

ORA-04088: error during execution of trigger 'PATRICE.TRIGGER_MUTANT'

04091. 00000 - "table %s.%s is mutating, trigger/function may not see it"

*Cause: A trigger (or a user defined plsql function that is referenced in this statement) attempted to look at (or modify) a table that was in the middle of being modified by the statement which fired it.

*Action: Rewrite the trigger (or function) so it does not read that table.

X X

X X

Tables

(15)

15

Les déclencheurs (Triggers) avec Oracle

7) Déclencheur LMD 7-4) Déclencheur d’état

Ils n'ont pas accès aux valeurs mises à jours (:new et :old) par l'opération puisqu'ils se déclenchent une seule fois même si la requête LMD met à jour plusieurs lignes.

Ils présentent l'avantage de pouvoir effectuer des manipulations sur la table qui a déclenché le trigger.

Ils sont plus performants en général

create or replace trigger SONDAGE_TRIG_612B AFTER insert on SONDAGE begin

dbms_output.put_line('début SONDAGE_TRIG_612B');

insert into sondage_copie select * from sondage where num not in ( select num from sondage_copie );

dbms_output.put_line('fin SONDAGE_TRIG_612B');

end;

/

(16)

Les déclencheurs (Triggers) avec Oracle

7) Déclencheur LMD 7-5) Avantage et inconvénients des déclencheurs ligne et globaux

Un trigger pouvant avorter la requête déclenchante doit toujours être de type ligne (for each row)

Un trigger n’avortant jamais la requête déclenchante peut être de type ligne ou global mais est souvent plus efficace en global

Il y a risque de mutation avec un trigger de type ligne :new et:old n’ont aucun sens avec un trigger global

Ligne global requête sur la table déclenchant le programme Non * Oui

utilisation de:new ou:old Oui Non

* : sauf select dans le cas d’un déclencheur before insert

(17)

17

Les déclencheurs (Triggers) avec Oracle

7) Déclencheur LMD 7-6) Déclencheur Instead of

il permet de mettre à jour une vue multitable ce qui n'est pas toujours possible avec une requête LMD standard. En effet la mise à jour n'est possible dans une vue que

si on effectue la mise à jour uniquement dans une table si une table est protégée par clé

Si elle ne comporte pas de distinct, de group by, d’ensemble, de sous- requête

(voir exemple page suivante)

il utilise la clause for each row (implicite) il n'utilise pas la les options before et after

il ne permet pas de préciser le nom d'une colonne pour un update il ne permet pas non plus d'utiliser la clause when

(18)

18

Les déclencheurs (Triggers) avec Oracle

7) Déclencheur LMD 7-6) Déclencheur Instead of

création d'une vue modifiable (v_article_fournisseur1)

create view v_article_fournisseur1 as

select fo.fo_nom, ar.fo_numero,ar_numero,ar_nom,ar_poids,ar_couleur, ar_stock,ar_pa,ar_pv from cdi_article ar

join cdi_fournisseur fo on ar.fo_numero = fo.fo_numero;

create view v_article_fournisseur2 as

select fo.fo_nom, fo.fo_numero,ar_numero,ar_nom,ar_poids,ar_couleur, ar_stock,ar_pa,ar_pv from cdi_article ar

join cdi_fournisseur fo on ar.fo_numero = fo.fo_numero;

insert into v_article_fournisseur1 (fo_numero,ar_numero, ar_nom,ar_poids,ar_couleur,ar_stock,ar_pa,ar_pv)

values ('F06','A85','GOMME','25','BLANC',20,1,2);

insert into v_article_fournisseur2 (fo_numero,ar_numero, ar_nom,ar_poids,ar_couleur,ar_stock,ar_pa,ar_pv)

values ('F06','A86','GOMME','25','BLANC',20,1,2);

ORA-01779: impossible de modifier une colonne correspondant à une table non protégée par clé

select * from user_updatable_columns where lower(table_name) like 'v_article_fournisseur%' and column_name like '%NUMERO%';

OWNER TABLE_NAME COLUMN_NAME UPDATABLE INSERTABLE DELETABLE CDI V_ARTICLE_FOURNISSEUR1 FO_NUMERO YES YES YES CDI V_ARTICLE_FOURNISSEUR1 AR_NUMERO YES YES YES CDI V_ARTICLE_FOURNISSEUR2 FO_NUMERO NO NO NO CDI V_ARTICLE_FOURNISSEUR2 AR_NUMERO YES YES YES

(19)

19

Les déclencheurs (Triggers) avec Oracle

7) Déclencheur LMD 7-6) Déclencheur Instead of

Ce trigger permet de modifier aussi bien article que fournisseur, ce qui est impossible normalement.

create or replace trigger art_four_trig1 instead of insert on v_article_fournisseur1 Declare

vNbFour int := 0; vNbArt int := 0;

Begin

select count(*) into vNbFour from cdi_fournisseur where fo_numero=:new.fo_numero;

select count(*) into vNbArt from cdi_article where ar_numero = :new.ar_numero;

if vnbart<>0 and vnbfour<>0 then

raise_application_error (-20001,'l''article et le fournisseur existent déjà');

elsif vnbart=0 then

insert into cdi_article (fo_numero,ar_numero,ar_nom,ar_poids,ar_couleur, ar_stock,ar_pa,ar_pv) values (:new.fo_numero,:new.ar_numero,:new.ar_nom, :new.ar_poids,:new.ar_couleur,:new.ar_stock,:new.ar_pa,:new.ar_pv);

Else

insert into cdi_fournisseur (fo_numero,fo_nom) values (:new.fo_numero,null);

end if;

dbms_output.put_line('v_article_fournisseur1 terminé');

end;

(20)

Les déclencheurs (Triggers) avec Oracle

8) Déclencheur LDD

Ils réagissent aux modifications de la structure de la base de données Ils sont sensibles aux options before et after

la directive database précise que le déclencheur peut s'exécuter à partir d'un événement provoqué par n'importe quel schéma

la directive schema précise que le déclencheur peut s'exécuter à partir d'un événement provoqué par le schéma lui même

Les ordres LDD pouvant provoquer l'exécution du déclencheur sont : alter, comment, create, drop, grant, rename, revoke

Ex :

create trigger majTDF before drop on iut123.schema Begin

if to_char(sysdate,'DAY') = 'DIMANCHE' then raise_application_error

(-20001,'pas de destruction le dimanche');

end if;

end;

(21)

21

Les déclencheurs (Triggers) avec Oracle

9) Déclencheur d'instance

Des événements systèmes peuvent provoquer le déclenchement d'un code PL/SQL

Des événements comme logon, startup, serverrror, suspend utilisent l'option after

Des événements comme LOGOFF, SHUTDOWN utilisent l'option before

Des événements comme AFTER STARUP et BEFORE SHUTDOWN s'appliquent avec des déclencheurs de type DATABASE

Ex :

create or replace

trigger deconnexion before LOGOFF on DATABASE begin

insert into trace values (user,sysdate);

end;

(22)

Les déclencheurs (Triggers) avec Oracle

10) Création de déclencheurs avec SQL Developer

Il est possible d'utiliser cette interface pour créer les déclencheurs

Utilisateur propriétaire Nom du déclencheur

Table Vue Schema Database Schéma concerné

Objet concerné Before after

Renommage old et new

Ligne ou global Événement déclenchant

(23)

23

Les déclencheurs (Triggers) avec Oracle

11) Nouveautés 11g

Il est possible de créer des déclencheurs directement inactifs (disable) Il est possible de choisir l'ordre d'exécution des déclencheurs d'un même événement (utilisation de la directive follows)

Il est possible de créer des déclencheurs composés de plusieurs blocs sensibles à des événements différents.

Cela peut permettre de résoudre le problème des tables mutantes.

Cela peut aussi permettre de réduire le nombre de déclencheurs

Références

Documents relatifs

Je suis un entier égal au produit de six nombres premiers distincts. La somme de mon inverse et des inverses de mes six facteurs premiers est égale

Par la méthode des moindres carrés, à l’aide de la calaulatrice et à l’unité près on obtient l’équation : y = 140x + 4873.. Pour tracer la droite il suffit de

CAP blanc - Femme : Shampooing, coupe, couleur, permanente et coiffage Etude de cas - Compétences comportementales. EVALUATION - ELABORER

When the unit or power cord is damaged, the unit must be repaired by Omcan or an Omcan approved service

Ainsi, l’incidence du cancer du sein est de 49 814 nouveaux cas (36,7 % des nouveaux cas de cancer) et la mortalité de 11 201 cas (18,9 % des décès par cancer) : l’évolution des

En général le système sera constitué d’un système de triggers AFTER (INSERT, UPDATE et DELETE) pour la table dont dépend l’attribut calculé, et d’un système

Avec %type, on utilise le type d’un attribut d’une table comme type de variable..

Appel d’une procédure dans SQL*PLUS : call ou execute ou exec 17 Appel d’une procédure dans une procédure ou une fonction 18 Variable locale : IS ou AS : Zone des variables