CodeGym /Cours /SQL SELF /Analyse des erreurs typiques lors du développement de tri...

Analyse des erreurs typiques lors du développement de triggers

SQL SELF
Niveau 58 , Leçon 4
Disponible

Alors, les amis, maintenant que vous avez déjà chopé les bases sur les triggers, leurs types, comment ça marche et même comment en créer pour différentes tâches, il est temps de parler d’un truc super important. Comme souvent en dev, savoir ce qu’on peut faire c’est cool, mais savoir ce qu’il ne faut surtout pas faire, c’est tout aussi crucial. Aujourd’hui, on va décortiquer les erreurs classiques que font les devs avec les triggers, histoire que vous puissiez les éviter et vous épargner quelques heures (ou jours !) de debug galère.

Récursion des triggers : le trigger s’appelle lui-même

C’est clairement l’erreur préférée des débutants. Imagine que tu crées un trigger qui met à jour une colonne, genre last_modified. Mais dès que cette modif a lieu, l’update déclenche à nouveau le trigger. Boucle infinie, et ton serveur finit par planter avec une erreur de stack overflow.

Exemple :

CREATE OR REPLACE FUNCTION update_last_modified()
RETURNS TRIGGER AS $$
BEGIN
    -- On met à jour le champ last_modified
    UPDATE my_table
    SET last_modified = NOW()
    WHERE id = NEW.id;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER after_update
AFTER UPDATE ON my_table
FOR EACH ROW
EXECUTE FUNCTION update_last_modified();

Qu’est-ce qui cloche ici ? L’opération UPDATE dans la fonction déclenche le même trigger qui l’a créée. Et voilà, boucle infinie.

Comment éviter ça :

Utilise la variable OLD et compare les valeurs avant de faire la modif :

CREATE OR REPLACE FUNCTION update_last_modified_safe()
RETURNS TRIGGER AS $$
BEGIN
    -- On vérifie si la valeur a changé
    IF NEW.last_modified IS DISTINCT FROM OLD.last_modified THEN
        NEW.last_modified = NOW();
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

Assure-toi de ne pas lancer d’opérations inutiles dans le trigger.

Mauvaise utilisation de OLD et NEW

Ces variables sont tes meilleures potes quand tu bosses avec les triggers, mais mal utilisées, elles peuvent te filer de sacrés maux de tête. OLD contient les données avant la modif de la ligne, NEW celles qui seront sauvegardées après la modif.

L’erreur classique, c’est de mal interpréter ou d’essayer d’utiliser ces variables là où elles n’existent pas. Par exemple, dans un trigger BEFORE INSERT, OLD n’existe pas — la ligne vient juste d’être créée.

Exemple d’erreur :

-- Ça va planter, car OLD n’existe pas lors d’un insert
CREATE OR REPLACE FUNCTION log_inserts()
RETURNS TRIGGER AS $$
BEGIN
    INSERT INTO audit_log (old_data, new_data)
    VALUES (OLD.my_column, NEW.my_column);
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

Comment éviter ça :

Fais gaffe à bien choisir où utiliser OLD et NEW :

  • OLD dispo pour les opérations UPDATE et DELETE.
  • NEW dispo pour les opérations INSERT et UPDATE.

Triggers multiples sur une même opération

Dans PostgreSQL, tu peux créer plusieurs triggers sur la même opération et la même table. Ça a l’air pratique, mais en vrai, ça peut vite devenir le bazar si les triggers se marchent dessus ou modifient les mêmes données.

Exemple :

-- Trigger 1
CREATE OR REPLACE FUNCTION trigger_one()
RETURNS TRIGGER AS $$
BEGIN
    -- Logique du trigger 1
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- Trigger 2
CREATE OR REPLACE FUNCTION trigger_two()
RETURNS TRIGGER AS $$
BEGIN
    -- Logique du trigger 2
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- Création de deux triggers
CREATE TRIGGER trigger_one AFTER INSERT ON my_table EXECUTE FUNCTION trigger_one();
CREATE TRIGGER trigger_two AFTER INSERT ON my_table EXECUTE FUNCTION trigger_two();

Les deux triggers vont s’activer à chaque insert dans my_table. Si leur logique n’est pas bien synchronisée, ça peut donner des résultats imprévisibles.

Comment éviter ça :

  • Planifie l’architecture de tes triggers à l’avance.
  • Si les triggers touchent à la même logique, regroupe-les dans un seul trigger.

Problèmes de performance

Les triggers ajoutent du calcul à chaque opération liée. Si tu mets des triggers sur des tables très sollicitées ou volumineuses, ça peut plomber les perfs de ta base.

Mauvais exemple :

CREATE OR REPLACE FUNCTION heavy_trigger_function()
RETURNS TRIGGER AS $$
BEGIN
    -- Opération lourde exécutée à chaque update de ligne
    PERFORM some_heavy_query();
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER performance_killer AFTER UPDATE ON huge_table EXECUTE FUNCTION heavy_trigger_function();

Comment éviter ça :

  • Réduis au max la logique dans le trigger. Si tu dois faire un truc lourd, pense à le déporter en tâche de fond.
  • Utilise des conditions pour limiter l’exécution du trigger, avec WHEN :
CREATE TRIGGER optimized_trigger
AFTER UPDATE ON my_table
WHEN (OLD.column_name IS DISTINCT FROM NEW.column_name)
EXECUTE FUNCTION light_function();

Triggers et transactions

Les triggers s’exécutent dans la transaction lancée par ta requête. Si une erreur survient dans le trigger, toute la transaction est rollback. Ça peut être utile parfois, mais ça peut aussi causer des surprises si tu n’as pas prévu la gestion d’erreur.

Exemple d’erreur :

CREATE OR REPLACE FUNCTION error_prone_trigger()
RETURNS TRIGGER AS $$
BEGIN
    -- Erreur volontaire
    RAISE EXCEPTION 'Quelque chose s’est mal passé !';
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

Si ce trigger se déclenche, la transaction de ta requête principale sera annulée.

Comment éviter ça :

Ajoute de la gestion d’erreur dans tes triggers pour limiter l’impact sur la transaction principale :

CREATE OR REPLACE FUNCTION safe_trigger()
RETURNS TRIGGER AS $$
BEGIN
    BEGIN
        -- Code qui peut planter
        INSERT INTO another_table VALUES (NEW.data);
    EXCEPTION
        WHEN OTHERS THEN
            RAISE NOTICE 'Une erreur est survenue, mais on l’a gérée proprement.';
    END;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

Conseils pratiques

  1. Garde tes triggers aussi simples que possible. Si tu trouves qu’un trigger devient trop gros ou trop complexe, c’est sûrement qu’il faut le découper en plusieurs fonctions ou revoir la logique.

  2. Teste toujours tes triggers sur peu de données. Avant de brancher un trigger sur une table critique, essaye-le sur des données de test.

  3. Documente tes triggers. Dans quelques mois, toi ou tes collègues aurez peut-être oublié pourquoi tel trigger existe. Une doc claire t’évitera bien des prises de tête.

  4. Évite les triggers pour des tâches faisables côté appli. Les triggers sont top pour automatiser des trucs à exécuter direct, mais pour de la logique métier complexe, ça peut vite devenir galère.

  5. Surveille les perfs. Checke régulièrement l’impact de tes triggers sur la perf de la base, surtout si tes données ou la charge augmentent.

Avec ces conseils et ce que t’as appris aujourd’hui, t’es prêt non seulement à créer des triggers, mais à en écrire qui tournent bien, efficacement, et sans mauvaises surprises.

1
Étude/Quiz
Déclencheurs au niveau des lignes et des tables, niveau 58, leçon 4
Indisponible
Déclencheurs au niveau des lignes et des tables
Déclencheurs au niveau des lignes et des tables
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION