Déclencheurs (Triggers) Esther Pacitti
Définition Programme stocké et invoqué implicitement sur un événement affectant la BD Séquence de règles de production déclenchées à l apparition d un événement prédéfini Règles de Production: Event-Condition-Action Sur Evénement Si Condition Alors Action
Evènement Dépend des transitions de l état de la base: Avant ou après Insertion de données Avant ou après Mise à jour de données Avant ou après Suppression de données Evénement élémentaire ou composite Conjonction d événements élémentaires (Ensemble d événements élémentaires reliés par l opérateur OR)
Condition et Action Condition (when): Prédicat optionnel Action Block PL/SQL: exécuté après l apparition de l événement si la condition événtuelle est satisfaite. Peut contenir des procedures cataloguées Peut activer des déclencheurs en cascade: maximum 32
Caractéristiques Granulatité Déclencheur orienté par table (défaut) Déclencheur orienté par ligne: FOR EACH Condition autorisée uniquement pour le déclencheur par ligne Prise en compte de l état de la base Antérieur à l événement: :OLD Utérieur à l événement: :NEW
Utilisation Le déclencheur renforce des fonctionnalités std du SGB pour: Les valeurs calculées: alimentation de colonnes dérivées, de variables globales à la base, Les règles de gestion complexes L intégrité référentielle dans une architecture répartie La duplication de tables Une sécurité plus sophistiquée: accès à la base sur des critères temporels (date, heure), sur le contenu de table Un audit plus sophistique: statistiques sur les accès aux tables Etc
Déclencheur para table Syntaxe: CREATE/REPLACE TRIGGER nom_trigger BEFORE/AFTER événement1 [OR événement2[or événement3 ]] ON nom_table Bloc PL/SQL événement = INSERT, UPDATE [OF nomcoli, ] ou DELETE
Déclencheur par table Utilisé si le traitement porte globalement sur l ensemble des lignes de la table Un déclencheur BEFORE par table permet d éviter l exécution d un nombre important de traitements si certaines conditions ne sont pas respectées. Un déclencheur AFTER par table permet de vérifier si les opérations se sont exécutés correctement, de réaliser des calculs, un audit,
Exemple 1 Interdire l insertion, la mise à jour et la suppression de données de la table emp après 18h CREATE Trigger nmj_emp Before insert or update or delete on emp Begin IF (TO_CHAR(sysdate, HH24 )) > 18 Then if inserting then Raise_application_error(-20501, Insertion Interdite ); Elseif updating then Raise_application_error(-20502, Mise à jour Interdite ); Else Raise_application_error(-20502, Suppresion Interdite ); end if; End if; End;
Exemple2 Nombre de requêtes de modification intervenues sur la colonne salaire SAL de la table emp CREATE TRIGGER nb_maj_sal AFTER UPDATE OF SAL ON emp BEGIN END, UPADTE surv_emp SET cpt_maj = cpt_maj + 1 where code_op = MAJ ;
Déclencheur par ligne CREATE/REPLACE TRIGGER nom_trigger BEFORE/AFTER événement1 [OR événement2[or événement3 ]] ON nom_table FOR EACH Row [When condition] Bloc PL/SQL événement = INSERT, UPDATE [OF nomcoli, ] ou DELETE condition: prédicat exécuté pour chaque ligne
Utilisation Utilisé si le traitement porte sur chacune des lignes de la table Calcul d une colonne à partir d autre colonnes Duplication de données Audit sophistiqué, etc Exemple 1: Contrôle d intégrité référentielle pour le numéro de département (deptno) avant chaque insertion ou mise à jour sur la table Emp par rapport au contenu de la table Dept Exemple 2: Comptabiliser le nombre de lignes ajoutées, mises à jour ou supprimées dans la table emp.
Exemple 1 CREATE Trigger nmj_emp AFTER insert or update or delete on emp For each row BEGIN IF INSERTING THEN UPADTE Surv_emp SET cpt_maj = cpt_maj +1 where code_op = AJOUT ; ELSEIF UPDATING THEN UPADTE Surv_emp SET cpt_maj = cpt_maj +1 where code_op = MAJ ; ELSE UPADTE Surv_emp SET cpt_maj = cpt_maj +1 where code_op = SUP ; END IF; END IF; END;
Exemple 2 CREATE TRIGGER total_salary AFTER DELETE OR INSERT or UPDATE OF deptno, sal, ON EMP FOR EACH ROW BEGIN IF DELETING OR (UPDATING and :old.deptno!= :new.deptno) THEN UPDATE dept SET total_sal = total_sal - :old.sal WHERE deptno = :old.deptno; END IF; IF INSERTING OR (UPDATING and :old.deptno!= :new.deptno) THEN UPDATE dept SET total_sal = total_sal -+:old.sal WHERE deptno = :new.deptno; ENF IF; IF (UPDATING AND :old.deptno = :new.deptno and :old.sal!= :new.sal) THEN UPADTE dept SET total_sal = total_sal -:old.sal + :new.sal WHERE deptno = :new.deptno; END IF END;
Status d un déclencheur Enable: actif (dès sa création) ALTER TRIGGER nom_trigger ENABLE ALTER TABLE nom_table ENABLE all triggers Disable ALTER TRIGGER nom_trigger DISABLE ALTER TABLE nom_table DISABLE all triggers
Update T1 SET Déclencheurs en Cascade Before update on T1 For each row Begin insert into T2 values values ( ) End; Before update on T2 For each row Begin insert into values ( ); End;
ATTENTION!!! Une utilisation abusive de déclencheurs sur une base de données peut déboucher sur: Des inter dépendances très complexes entre tables et par conséquence, sur une application difficilement maintenable. Des temps de réponse non raisonnables pour utilisateurs.