Les triggers

Les triggers permettent d'exécuter du code lors d'un évènement particulier. La traduction littéral est déclencheur.


Le trigger sera exécuté dans la même transaction que l'ordre sur lequel il déclenche (en cas de rollback ou commit, le traitement sera annulé ou validé au même titre que l'ordre lui-même).


Trigger FOR EACH ROW


Exemple de création d'un trigger :

Création simple d'un trigger insérant une nouvelle ligne dans une table de log à chaque création de commande :

create or replace trigger TR_LOG_INS_CMD as
BEFORE INSERT ON COMMANDE
FOR EACH ROW
BEGIN
insert into T_LOG (evt_date, evt_label) values (systimestamp, 'Nouvelle commande créée');
END;
/



Exemple d'utilisation du mot clé :old
create or replace trigger TR_LOG_DEL_CMD as
BEFORE DELETE ON COMMANDE
FOR EACH ROW
BEGIN
insert into T_LOG (evt_date, evt_label) values (systimestamp, 'commande ' || :old.cmd_id || ' supprimée');
END;
/


create or replace trigger TR_LOG_UPDT_CMD as
BEFORE UPDATE ON COMMANDE
FOR EACH ROW
BEGIN
insert into T_LOG (evt_date, evt_label) values (systimestamp, 'commande ' || :old.cmd_id || ' mise à jour, la nouvelle date de livraison est : ' || :new.liv_date);
END;
/


Cependant, il est possible de ne déclencher que sur la colonne qui nous intéresse :

create or replace trigger TR_LOG_UPDT_CMD as
BEFORE UPDATE OF LIV_DATE ON COMMANDE
FOR EACH ROW
BEGIN
insert into T_LOG (evt_date, evt_label) values (systimestamp, 'commande ' || :old.cmd_id || ' mise à jour, la nouvelle date de livraison est : ' || :new.liv_date);
END;
/


Le trigger AFTER ... FOR EACH ROW effectuera la même chose mais une fois seulement que les valeurs aient été modifiées

Trigger globaux


Les précédents triggers se déclenchaient et effectuaient le traitement pour chaque tuple de la table concernée.
Or, il existe la possibilité de ne déclencher qu'en début ou fin de transaction sur la table entière (respectivement BEFORE et AFTER). Celà peut être particulièrement utile lorsque nous effectuons un calcul persistent sur les données ; par exemple, dans la table statistique, nous stockons la somme des commandes en cours (date_liv est nulle). Il est alors inutile d'effectuer le calcul plusieurs fois dans une même transaction car seul le dernier résultat sera réellement en base.

create or replace trigger TR_STAT_CMD_DEL as
AFTER INSERT or DELETE or UPDATE of date_liv ON COMMANDE
BEGIN
update statistique set nb_cmd = select count(*) from commande where date_liv is null;
END;
/



Ainsi lors de la suppression de 6 commandes (dans la même transaction), le trigger n'exécutera le code qu'une fois en fin de traitement.

Remarquons que dans le cas d'un trigger global, les références que sont NEW et OLD, ne sont pas possibles ; l'erreur ORA-04082 apparaît lors de la compilation du trigger le cas échéant.

Trigger INSTEAD

Lorsque des vues sont créées à destination de l'utilisateur, 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 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.



Mutating table

Le trigger déclenche du code PL ; ainsi n'importe quel code PL valide peut être exécuté par un trigger (appel de fonctions, de procédures, gestion d'exceptions, ...).
Attention cependant car un ordre DDL peut être déclenché par un trigger qui lui-même peut manipuler dans un autre trigger. On se retrouve alors dans le cas d'une "mutation" de table :
ORA-04091: table ma_table is mutating, trigger/function may not see it

Dans ce cas, l'astuce consiste à coupler un trigger de type ON EACH ROW, un trigger de type AFTER et une table temporaire. Si l'intégrité n'est pas en jeu, les transactions autonomes peuvent également résoudre le problème.

Les triggers sur évènements systèmes (DATABASE)

Il est possible de créer des triggers sur des évènements autres que traitant les données tels que les évènements système :
CREATE OR REPLACE TRIGGER TR_LOG
AFTER LOGON ON DATABASE
CALL ma_procédure_init_user;
/


Les évènements concernés sont :
AFTER STARTUP
BEFORE SHUTDOWN
AFTER LOGON
BEFORE LOGOFF
AFTER DB_ROLE_CHANGE
AFTER SUSPEND
AFTER SERVERERROR


Exemple de trigger de gestion d'erreur (erreur d'authentification notamment) :

create or replace trigger TR_BAD_PWD
AFTER SERVERERROR on DATABASE
BEGIN
IF (IS_SERVERERROR(1017)) THEN
insert into T_LOG (evt_date, evt_label) values (systimestamp, 'une erreur d''authentification est survenue' );
END IF;
END;
/



Les triggers sur évènements DDL


L'ensemble de ces évènements DDL peuvent être associés à des trigger BEFORE ou AFTER :
ALTER
ANALYZE
ASSOCIATE
AUDIT
COMMENT
CREATE
DDL
DISASSOCI
DROP
GRANT
NOAUDIT
RENAME
REVOKE
TRUNCATE





Opération sur les triggers

Tout comme les fonctions ou procédures, un trigger peut se retrouver avec un statut invalide ; il faut alors le recompiler :
ALTER TRIGGER monTriggger COMPILE;

Il est également possible de désactiver un trigger (afin qu'il ne déclanche plus, mais reste présent en base) :
ALTER TRIGGER monTriggger DISABLE;
que l'on réactive en faisant :
ALTER TRIGGER monTriggger ENABLE;

Informations sur les triggers

Les vues du dictionnaire concernées sont :
- ALL_TRIGGERS
- USER_TRIGGERS
- DBA_TRIGGERS




Voir les articles se référents à celui-ci :
- Aperçu des transactions autonomes
- Gérer l'auto-increment sous Oracle
- Les vues  




Vous n'avez pas trouver réponse à votre question ? Préciser votre recherche :

Catégories