Ordre d'Exécution des Triggers
Comprendre la séquence et les variables spéciales
1 Séquence d'Exécution Complète
🎬 Déroulement lorsqu'une requête arrive
1️⃣ BEFORE STATEMENT
Une seule foisTous les triggers FOR EACH STATEMENT de type BEFORE
→ Exécutés dans l'ordre alphabétique s'il y en a plusieurs
🔄 Pour CHAQUE enregistrement concerné :
2️⃣ BEFORE ROW
Par ligneTous les triggers FOR EACH ROW de type BEFORE
⚡ Important: Peut modifier
NEW avant l'enregistrement
3️⃣ MODIFICATION EFFECTIVE
L'enregistrement est verrouillé et le changement effectué dans la table
💾 INSERT / UPDATE / DELETE réellement exécuté
4️⃣ AFTER ROW
Par ligneTous les triggers FOR EACH ROW de type AFTER
⚠️ Les données sont déjà enregistrées, impossible de les modifier
5️⃣ AFTER STATEMENT
Une seule foisTous les triggers FOR EACH STATEMENT de type AFTER
→ Exécutés dans l'ordre alphabétique s'il y en a plusieurs
📊 Exemple: UPDATE de 3 employés
🔷 BEFORE STATEMENT (1 fois)
▪️ BEFORE ROW employé #1
✓ Modification employé #1
▪️ AFTER ROW employé #1
▪️ BEFORE ROW employé #2
✓ Modification employé #2
▪️ AFTER ROW employé #2
▪️ BEFORE ROW employé #3
✓ Modification employé #3
▪️ AFTER ROW employé #3
🔷 AFTER STATEMENT (1 fois)
2 Variables OLD et NEW
| Opération | OLD | NEW | Modification possible ? |
|---|---|---|---|
| INSERT | ❌ NULL | ✅ Nouvelles valeurs | BEFORE: Oui (modifier NEW) |
| UPDATE | ✅ Anciennes valeurs | ✅ Nouvelles valeurs | BEFORE: Oui (modifier NEW) |
| DELETE | ✅ Valeurs supprimées | ❌ NULL | Non (OLD en lecture seule) |
| STATEMENT | ❌ NULL | ❌ NULL | Non applicable |
📝 Exemple BEFORE INSERT
CREATE FUNCTION maj_date_creation()
RETURNS TRIGGER AS $$
BEGIN
-- Modifier NEW avant insertion
NEW.date_creation := CURRENT_DATE;
NEW.user_creation := CURRENT_USER;
RETURN NEW; -- Important !
END;
$$ LANGUAGE plpgsql;
📝 Exemple AFTER UPDATE
CREATE FUNCTION log_changement()
RETURNS TRIGGER AS $$
BEGIN
INSERT INTO audit_log VALUES (
OLD.emp_no,
OLD.emp_salaire,
NEW.emp_salaire,
CURRENT_TIMESTAMP
);
RETURN NULL; -- Pas important pour AFTER
END;
$$ LANGUAGE plpgsql;
3 Variables Spéciales dans les Triggers
TG_NAME
Nom du trigger actuellement exécuté
Type: TEXT
TG_WHEN
Moment du déclenchement
Valeurs: BEFORE / AFTER / INSTEAD OF
TG_LEVEL
Niveau du trigger
Valeurs: ROW / STATEMENT
TG_OP
Type d'opération
Valeurs: INSERT / UPDATE / DELETE
TG_TABLE_NAME
Nom de la table concernée
Type: TEXT
TG_TABLE_SCHEMA
Schéma de la table
Type: TEXT
💡 Exemple d'utilisation
CREATE FUNCTION universal_trigger() RETURNS TRIGGER AS $$
BEGIN
IF TG_OP = 'INSERT' THEN
RAISE NOTICE 'Insertion dans %', TG_TABLE_NAME;
RETURN NEW;
ELSIF TG_OP = 'UPDATE' THEN
RAISE NOTICE 'Mise à jour de % dans %', OLD.emp_no, TG_TABLE_NAME;
RETURN NEW;
ELSIF TG_OP = 'DELETE' THEN
RAISE NOTICE 'Suppression de % dans %', OLD.emp_no, TG_TABLE_NAME;
RETURN OLD;
END IF;
END;
$$ LANGUAGE plpgsql;
-- Un seul trigger pour 3 événements !
CREATE TRIGGER trg_audit
AFTER INSERT OR UPDATE OR DELETE ON exe_employe
FOR EACH ROW
EXECUTE FUNCTION universal_trigger();
4 Valeurs à Retourner
| Type de Trigger | Valeur à retourner | Effet |
|---|---|---|
| BEFORE ROW (INSERT/UPDATE) | NEW |
L'opération continue avec NEW (éventuellement modifié) |
| BEFORE ROW (INSERT/UPDATE) | NULL |
⚠️ L'opération est ANNULÉE pour cette ligne ! |
| BEFORE ROW (DELETE) | OLD |
L'opération continue |
| BEFORE ROW (DELETE) | NULL |
⚠️ Le DELETE est ANNULÉ pour cette ligne ! |
| AFTER ROW | NULL ou n'importe quoi |
La valeur est ignorée (données déjà enregistrées) |
| STATEMENT (BEFORE/AFTER) | NULL |
Toujours NULL (pas de OLD/NEW) |
⚠️ Attention !
- • Retourner
NULLdans un BEFORE ROW = annuler l'opération - • Dans un AFTER, la valeur retournée n'a aucun effet (mais doit être non-NULL pour ne pas générer d'erreur)
- • Pour modifier les données, il faut un BEFORE ROW et retourner NEW modifié
🎮 Exercice Interactif: Ordre d'Exécution
Vous avez les triggers suivants sur la table exe_employe:
• trg_audit_statement AFTER INSERT STATEMENT
• trg_before_insert BEFORE INSERT ROW
• trg_validate BEFORE INSERT STATEMENT
• trg_log AFTER INSERT ROW
Question: Dans quel ordre seront-ils exécutés lors d'un INSERT de 2 employés ?
A) trg_validate (BEFORE STATEMENT)
B) trg_before_insert (BEFORE ROW) pour employé 1
C) INSERT réel employé 1
D) trg_log (AFTER ROW) pour employé 1
E) trg_before_insert (BEFORE ROW) pour employé 2
F) INSERT réel employé 2
G) trg_log (AFTER ROW) pour employé 2
H) trg_audit_statement (AFTER STATEMENT)