Aller au contenu

Introduction aux triggers de niveau rangée

Un trigger (déclencheur) est un bloc PL/SQL stocké dans la base de données qui s’exécute automatiquement lorsqu’un événement survient sur une table.

✏ Contrairement aux fonctions et procédures, le trigger n'est JAMAIS appelé manuellement, c'est un automatisme.

Ce qui déclenche un trigger est une instruction du DML sur une table : INSERT, UPDATE ou DELETE.

✔ Les triggers offrent une solution procédurale pour définir des contraintes complexes ou qui prennent en compte des données issues de plusieurs lignes ou de plusieurs tables. Par exemple, pour garantir qu'un client ne peut pas avoir plus de 2 commandes non payées.

❌ Les triggers ne remplacent pas les contraintes d'intégrité, car ils remandent plus de ressources et sont généralement plus lents.

Syntaxe de base du trigger de niveau rangée

CREATE OR REPLACE TRIGGER 
nom_trigger
BEFORE ou AFTER 
INSERT ou UPDATE ou DELETE
ON nom_table
FOR EACH ROW
    --variables
BEGIN
    -- Instructions PL/SQL
END;
/

✅ C'est la ligne FOR EACH ROW qui indique que c'Est un trigger de niveau rangée.

Niveau de trigger

Il existe deux niveau de trigger :

  • Trigger de table / niveau instruction : s'exécute une seule fois avant ou après l'instruction déclencheuse
  • Trigger de rangée : s'exécute une fois PAR LIGNE touchée par l'instruction déclencheuse

Comparaison :

Triggers

Trigger de niveau rangée

Un trigger de niveau rangée s’exécute plusieurs fois : soit une fois par ligne touchée par l'instruction SQL déclencheuse.

Par exemple :

Lors de l'instruction

UPDATE Client SET ville = 'Québec';

Le trigger s'exécute autant de fois qu'il y a de clients (une fois par client modifié).

Le trigger de niveau rangée est donc utilisé généralement pour des contraintes complexes sur des données de table qui nécessitent des validations d'autres tables.

Exemple :

Objectif : lors de l'insertion d'une facture client, s'assurer que le solde du client est à 0.

Trigger qui s'exécute avant l'ajout d'une facture :

CREATE OR REPLACE TRIGGER trg_validationSoldeClient
BEFORE INSERT ON Facture
FOR EACH ROW
    solde Client.soldeClient%Type;

    solde_eleve EXCEPTION;
BEGIN
    SELECT soldeClient INTO solde
    FROM Client 
    WHERE noCLient = :NEW.noClientFacture;

    IF solde > 0 THEN
        RAISE solde_eleve;
    END IF;
EXCEPTION
    WHEN solde_eleve THEN
        RAISE_APPLICATION_ERROR(-20100, 'Le solde de ce client est trop élevé pour accepter une nouvelle facture.');
END;
/

❓ Pourquoi un trigger de niveau rangée ?

Grâce à ce type de trigger, on a accès directement à la ligne en modification et on peut donc traiter cette ligne grâce aux variable :OLD et :NEW.

Variables :OLD et :NEW

Dans un trigger de niveau rangée (FOR EACH ROW), il n'est pas possible d'accéder aux données de la table à laquelle est associée le trigger.

Seule la ligne en cours de modification est accessible à l'aide de deux pseudo variables de type RECORD: les variables :OLD et :NEW qui reprennent la structure de la table associée.

:NEW :

représente les nouvelles valeurs qui seront (ou ont été) placées dans la ligne traitée par le déclencheur. Cet enregistrement est disponible seulement pour les déclencheurs de type INSERT ou UPDATE.

:OLD

représente les anciennes valeurs qui étaient (ou sont encore) dans la ligne traitée par le déclencheur. Cet enregistrement est disponible seulement pour les déclencheurs de type UPDATE ou DELETE.

➡️ Disponibilité

Opération :OLD :NEW
INSERT
UPDATE
DELETE

Cas d'utilisation des triggers de table

Les triggers de rangée sont généralement utilisés pour :

  • ✔️ Validation d’une valeur propre à chaque ligne
  • ✔️ Comparaison ancienne valeur vs nouvelle valeur
  • ✔️ Contrôle de capacité, de stock, de quotas
  • ✔️ Règles de données fines (ex. un billet, un compte, un salaire)

Gestion des erreurs

Un trigger peut contenir une section EXCEPTION comme un bloc PL/SQL classique.

Toutefois, l'exception reste au niveau de l'exécution du trigger.

Exemple :

CREATE OR REPLACE TRIGGER trg_update_client
AFTER UPDATE ON Client
BEGIN
    INSERT INTO Audit_Client(action, date_action)
    VALUES ('UPDATE Client', SYSDATE);

EXCEPTION
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('Erreur dans le trigger d''audit.');
END;
/

⚠️ Ce trigger est déclenché après la mise à jour de la table client. Donc, si l'exception est levée, un message sera envoyé dans le buffer d'Oracle, mais ne remontera par plus haut. De plus, la mise à jour aura eu lieu malgré cela.

✔ Pour qu'une erreur soit traitée, qu'elle annule la modification et remonte de un niveau d'exécution pour être affichée, on doit alors utiliser RAISE_APPLICATION_ERROR.