Vous êtes sur la page 1sur 23

ENSIT

Chapitre V
Les déclencheurs

1
Introduction
• Un déclencheur (ou trigger) est un bloc PL/SQL qui s'exécutera
automatiquement suite à un événement.

• Un déclencheur de BD est généralement associé à une table ou une vue.

• Les événements déclencheurs peuvent être:


- Une instruction insert, update ou delete. On parle de déclencheurs LMD.
- Une instruction create, alter ou drop. On parle de déclencheurs LDD.
- Le démarrage ou l'arrêt de la base (startup ou shutdown), une erreur
spécifique, une connexion ou une déconnexion d'un utilisateur.
On parle de déclencheurs systèmes.

• Les déclencheurs de BD permettent d’implémenter des règles de gestion


complexes et complètent les règles d’intégrité associées à la création des
tables.

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

3
Déclencheurs sur table

• Le traitement associé à un déclencheur LMD peut être


exécuté:

– soit une fois: suite à l’événement qui l’a déclenché


→trigger par ordre (exécuté une seule fois)

– soit pour chaque ligne de la table concernée par


l’événement
→trigger ligne (exécuté pour chaque ligne)

4
Déclencheurs sur table
1- Déclencheur par ordre

CREATE [OR REPLACE] TRIGGER nom_declencheur


{BEFORE | AFTER} {INSERT | UPDATE [OF nom_colonne[,
nom_colonne]] | DELETE} [OR { DELETE | INSERT | UPDATE [OF col1
[,col2]…] }]…
ON nom_table
{ Bloc PL/SQL | CALL nomSousProgramme(paramètres) }

- Le moment où le trigger va se déclencher par rapport à l'instruction LMD


(Before, After)
- Les instructions du LMD qui déclenchent le trigger (insert or update or delete)
- Dans le cas de UPDATE nous pouvons préciser la (ou les colonnes sur
lesquelles porte la mise à jour).
- La table à laquelle le trigger est lié (nom_table)
- Le bloc Pl/SQL qui décrit le traitement effectué en cas de déclenchement du
trigger. 5
Déclencheurs sur table

Exemple 1

create or replace trigger TR_STAT_CMD


AFTER INSERT or DELETE ON COMMANDE
BEGIN
update statistique set nb_cmd = select count(*) from commande;
END;
/

6
Déclencheurs sur table

Exemple 2

CREATE OR REPLACE TRIGGER périodeOKQualifs


BEFORE DELETE OR UPDATE
OR INSERT ON Qualifications
BEGIN
IF TO_CHAR(SYSDATE,'DAY') IN
('SAMEDI', 'DIMANCHE') THEN
RAISE_APPLICATION_ERROR(-20200, 'Désolé pas de mises à
jour des qualifications le week-end');
END IF ;
END;
/

7
Déclencheurs sur table
2- Déclencheur ligne
• Un déclencheur ligne est exécuté pour chacune des lignes concernées
par l’exécution de l’événement (FOR EACH ROW)

CREATE [OR REPLACE] TRIGGER nom_declencheur


{BEFORE | AFTER} {INSERT | UPDATE [OF nom_colonne[,
nom_colonne]] | DELETE} [OR { DELETE | INSERT | UPDATE [OF col1
[,col2]…] }]…
ON nom_table
[REFERENCING {[OLD [AS] ancien] | [NEW [AS] nouveau]}]
FOR EACH ROW
[WHEN condition]
{ Bloc PL/SQL | CALL nomSousProgramme(paramètres) }

8
Déclencheurs sur table
• Dans un trigger ligne, on peut faire référence à la ligne courante, celle
pour laquelle le trigger s'exécute
• Pour cette ligne, on a accès à la valeur avant l'instruction LMD (nommée
:old) et à la valeur après l'instruction (nommée :new)

• il est possible de modifier les noms OLD et NEW en précisant les


nouveaux noms dans la clause suivante:
REFERENCING OLD AS nouveau_nom NEW AS nouveau_nom

9
Déclencheurs sur table
Exemple 1
Ecrire un trigger permettant de tenir compte d’une copie de sauvegarde des
informations sur les pilotes après chaque suppression ou mise à jour de la
table pilote.
Nous supposons avoir créé une table info_pilote de la manière suivante:
CREATE TABLE info_pilote (date_modif Date, V_nopilot char(4));

CREATE OR REPLACE TRIGGER Contrôle_pilote


AFTER DELETE OR UPDATE ON Pilote
FOR EACH ROW
BEGIN
INSERT INTO info_pilote (date_modif, V_nopilot)
VALUES(SYSDATE, :OLD.nopilot);
END;
/
10
Déclencheurs sur table
Exemple 2

Create or replace trigger ModifNbreEmp


after insert on employe
for each row
begin
update departement set nbemp = nbemp + 1
where numd = :new.numd;
end;
/

11
Déclencheurs sur table
Exemple 3
On peut définir une condition pour un trigger ligne (WHEN condition).
Le trigger se déclenchera pour chaque ligne vérifiant la condition.

Create or replace trigger journal_emp


after update of salaire on EMPLOYE
for each row
when (new.salaire < old.salaire)
begin
insert into EMP_LOG(emp_id, NouvSal date_evt, msg)
values (:new.empno, :new.salaire, sysdate, 'salaire diminué');
end ;
/

12
Déclencheurs sur table
Exemple 3

CREATE OR REPLACE TRIGGER TRG_BIUDR_EMP


BEFORE INSERT OR UPDATE OR DELETE
-- avant insertion, modification ou suppression
ON EMP
FOR EACH ROW -- pour chaque ligne
Begin
If INSERTING Then dbms_output.put_line( 'Insertion dans la table EMP' ) ;
End if ;
If UPDATING Then dbms_output.put_line( 'Mise à jour de la table EMP' ) ;
End if ;
If DELETING Then dbms_output.put_line( 'Suppression dans la table EMP');
End if ;
End ;
/

13
Déclencheurs sur vue

CREATE OR REPLACE TRIGGER nom_trigger


INSTEAD OF {INSERT | UPDATE [OF nom_colonne[,
nom_colonne]] | DELETE} [OR { DELETE | INSERT | UPDATE [OF col1
[,col2]…] }]…
ON nom_vue
{ Bloc PL/SQL | CALL nomSousProgramme(paramètres) }

• Il est possible d'implémenter un trigger offrant à l'utilisateur un


contournement à la mise à jour des données d'une vue. Dans ce cas, le
trigger INSTEAD OF est tout à fait adapté.

• L'utilisateur effectuera ainsi une requête INSERT (ou UPDATE ou


DELETE) sur un objet de type vue, mais derrière, le code sera adapté afin
que la vue devienne complètement transparente et se manipule comme une
table.

14
Déclencheurs sur vue

CREATE OR REPLACE view empinfo as select


EMPNO,ENAME,JOB,SAL,COMM,DNAME from emp e ,dept d where
d.deptno = e.deptno;

CREATE OR REPLACE trigger update_emp_throu_empinfo_view


instead of update on empinfo
begin
update emp set ename = :new.ename, empno = :new.empno,
job = :new.job, sal = :new.sal, comm = :new.comm, deptno = (select deptno
from dept where dname = :new.dname ) where empno = :old.empno;
end;
/

15
Déclencheurs LDD
CREATE [OR REPLACE] TRIGGER nomDéclencheur
BEFORE | AFTER { actionStructureBase [OR actionStructureBase]… }
ON { SCHEMA | DATABASE }
{ Bloc PL/SQL | CALL nomSousProgramme(paramètres) }

• 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
Exemple
CREATE TRIGGER majTDF
BEFORE DROP ON DATABASE
BEGIN
if to_char(sysdate,'DAY') = 'DIMANCHE' then
raise_application_error
(-20001,'pas de destruction le dimanche') ;
end if ;
END ; 16
/
Les déclencheurs systèmes
• Depuis la version Oracle 8i, il est désormais possible d'utiliser des
déclencheurs pour suivre les changements d'état du système
CREATE [OR REPLACE] TRIGGER nom_déclencheur
{BEFORE|AFTER} évènement_système ON{DATABASE|SCHEMA}
{ Bloc PL/SQL | CALL nomSousProgramme(paramètres) }

STARTUP
Trigger déclenché lors de l'ouverture de l'instance (AFTER seulement)
SHUTDOWN
Trigger déclenché avant le processus d'arrêt de l'instance (non déclenché
en cas d'arrêt brutal du serveur) (BEFORE seulement)
SERVERERROR
Trigger déclenché lors d'une erreur Oracle (sauf ORA-1034, ORA-1403,
ORA-1422, ORA-1423 et ORA-4030) (AFTER seulement)
LOGOFF
Trigger déclenché lors d’une déconnexion de la BD.
LOGON
Trigger déclenché lors d’une connexion à la BD 17
Les déclencheurs systèmes

Exemple
CREATE TRIGGER espionDeconnexion
BEFORE LOGOFF ON DATABASE
BEGIN
INSERT INTO Trace VALUES (USER || ' déconnexion le ' ||
TO_CHAR(SYSDATE,'DD-MM-YYYY HH24:MI:SS'));
END;
/

18
Appels de sous-programmes

Exemples

CREATE PROCEDURE sousProgDéclencheur(param IN VARCHAR2) IS


BEGIN
INSERT INTO Trace VALUES (param);
END sousProgDéclencheur;

CREATE TRIGGER espionConnexion


AFTER LOGON ON DATABASE
CALL sousProgDéclencheur(SYSDATE)
/
CREATE TRIGGER TrigDelTrace
AFTER SERVERERROR ON SCHEMA
BEGIN
sousProgDéclencheur('Une erreur s''est produite');
END;
19
Opérations sur les déclencheurs
• Il est également possible de:
- Désactiver un déclencheur (afin qu'il ne se déclenche plus, mais reste
présent dans la base) :
ALTER TRIGGER monTriggger DISABLE;
-Activer un déclencheur
ALTER TRIGGER monTriggger ENABLE;
- Désactiver tous les déclencheurs d’une table
ALTER TABLE nomTable DISABLE ALL TRIGGERS;
-Activer tous les déclencheurs d’une table
ALTER TABLE nomTable ENABLE ALL TRIGGERS;
- Recompiler un trigger
ALTER TRIGGER nomDéclencheur COMPILE;
-Supprimer un trigger
DROP TRIGGER montrigger;

20
Informations sur les déclencheurs
• Les informations sur les déclencheurs sont visibles à travers les vues du
dictionnaire de données:
-USER_TRIGGERS pour les déclencheurs appartenant au schéma
-ALL_TRIGGERS pour les déclencheurs appartenant aux schémas
accessibles
- DBA_TRIGGERS pour les déclencheurs appartenant à tous les schémas

La colonne BASE_OBJECT_TYPE permet de savoir si le déclencheur est


basé sur une table, une vue, un schéma ou la totalité de la base.

La colonne TRIGGER_TYPE permet de savoir s'il s'agit d'un déclencheur


BEFORE, AFTER ou INSTEAD OF si son mode est FOR EACH ROW ou
non.

La colonne TRIGGERING_EVENT permet de connaître l’événement


concerné par le déclencheur.

La colonne TRIGGER_BODY contient le code du bloc PL/SQL . 21


Exercice

Soit le schéma relationnel suivant:


MODULE (codMod, nomMod,effecMax);
EXAMEN (#codMod, codExam, dateExam);
INSCRIPTION (#numEtud, #codMod, dateInsc);

Implémentez la contrainte suivante:


On ne peut créer un examen pour un module que s’il y a des élèves inscrits
dans ce module.

22
Correction
CREATE VIEW examensPossibles
AS SELECT codMod FROM MODULE M
WHERE ( SELECT COUNT(*)
FROM INSCRIPTION I
WHERE I.codmod = M.codmod ) > 0 ;

CREATE OR REPLACE TRIGGER beforeInsertUpdateExam


BEFORE INSERT OR UPDATE ON examen
FOR EACH ROW
DECLARE
nbLignes NUMBER;
BEGIN
SELECT count(*) INTO nbLignes
FROM examenspossibles WHERE codmod = :new.codmod;
IF (nbLignes = 0)
THEN
RAISE_APPLICATION_ERROR (-20111, ‘Pas d’’élèves dans ce module’);
END IF;
END;
23
/

Vous aimerez peut-être aussi