Structures Conditionnelles en SQL et PL/pgSQL

@joekakone

Joseph Konka @joekakone

03/03/2026 · 7 min

Maîtrisez le branchement logique en base de données : comparez l'expression déclarative CASE WHEN et la structure procédurale IF..THEN..ELSIF..ELSE..END IF, et appliquez-les aux pipelines de données ETL.

En ingénierie de données, l'aiguillage logique est omniprésent : déclencher un recalcul uniquement si de nouvelles données sont arrivées, catégoriser des clients selon leur volume d'achat, ou interrompre un script en cas d'incohérence.

Il convient de distinguer deux notions souvent confondues : 1. L'expression déclarative CASE WHEN (utilisable partout dans le SQL standard). 2. L'instruction de contrôle procédurale IF ... THEN ... ELSE (exclusive aux blocs PL/pgSQL).


1. L'expression déclarative : CASE WHEN#

L'expression CASE WHEN évalue une liste de conditions et retourne une valeur unique. Elle s'intègre directement dans les requêtes SELECT, WHERE, ORDER BY ou UPDATE.

Syntaxe générale (Forme recherchée)#

CASE 
    WHEN condition_1 THEN resultat_1
    WHEN condition_2 THEN resultat_2
    ELSE resultat_par_defaut
END

Cas d'usage A : Segmentation et scoring métier#

SELECT 
    id_client,
    nom,
    total_achats,
    CASE 
        WHEN total_achats >= 50000 THEN 'Client VIP (HVC)'
        WHEN total_achats >= 10000 THEN 'Client Régulier (MVC)'
        WHEN total_achats > 0      THEN 'Client Occasionnel (LVC)'
        ELSE 'Inactif'
    END AS segment_client
FROM analytics.dim_clients;

Cas d'usage B : Agrégation conditionnelle (Pivot Table en SQL pur)#

L'association de SUM() et de CASE WHEN permet de transformer les lignes d'une catégorie en colonnes sans fonction de pivot dédiée :

SELECT 
    date_vente,
    SUM(CASE WHEN categorie = 'Informatique' THEN montant ELSE 0 END) AS ca_informatique,
    SUM(CASE WHEN categorie = 'Mobilier'     THEN montant ELSE 0 END) AS ca_mobilier,
    SUM(CASE WHEN categorie = 'Fournitures'  THEN montant ELSE 0 END) AS ca_fournitures,
    SUM(montant) AS ca_total
FROM fct_ventes
GROUP BY date_vente
ORDER BY date_vente DESC;

2. L'instruction de contrôle procédurale : IF ... THEN ... ELSE#

À la différence de CASE WHEN qui calcule une valeur, l'instruction IF en PL/pgSQL gouverne quelles actions exécuter.

                    [ Condition booléenne ]
                             │
               ┌─────────────┴─────────────┐
          VRAI │                      FAUX │
               ▼                           ▼
        [ Bloc THEN ]              [ Bloc ELSIF ou ELSE ]
               │                           │
               └─────────────┬─────────────┘
                             ▼
                        [ END IF; ]

[!WARNING] En PL/pgSQL, la syntaxe pour les branches intermédiaires s'écrit obligatoirement ELSIF ou ELSEIF (avec un S). La syntaxe Python elif provoquera une erreur de syntaxe à la compilation. Tout bloc conditionnel doit obligatoirement se refermer par END IF;.


3. Les formes de structures procédurales#

Forme 1 : Condition simple (IF ... THEN ... END IF;)#

DO
$$
DECLARE
    v_nb_erreurs INTEGER := 0;
BEGIN
    SELECT COUNT(*) INTO v_nb_erreurs FROM logs_anomalies WHERE resolu = FALSE;

    IF v_nb_erreurs > 0 THEN
        RAISE WARNING 'Attention : % anomalie(s) non résolue(s) détectée(s) !', v_nb_erreurs;
    END IF;
END;
$$ LANGUAGE plpgsql;

Forme 2 : Alternative binaire (IF ... THEN ... ELSE ... END IF;)#

DO
$$
DECLARE
    v_statut_serveur TEXT := 'PRODUCTION';
BEGIN
    IF v_statut_serveur = 'PRODUCTION' THEN
        RAISE NOTICE 'Mode sécurisé actif : journalisation stricte.';
    ELSE
        RAISE NOTICE 'Mode bac à sable : réinitialisation autorisée.';
    END IF;
END;
$$ LANGUAGE plpgsql;

Forme 3 : Multi-branches (IF ... ELSIF ... ELSE ... END IF;)#

DO
$$
DECLARE
    v_taux_remise NUMERIC(4, 2);
    v_anciennete_annees INTEGER := 4;
BEGIN
    IF v_anciennete_annees >= 5 THEN
        v_taux_remise := 0.20;
    ELSIF v_anciennete_annees >= 2 THEN
        v_taux_remise := 0.10;
    ELSIF v_anciennete_annees >= 1 THEN
        v_taux_remise := 0.05;
    ELSE
        v_taux_remise := 0.00;
    END IF;

    RAISE NOTICE 'Remise accordée : % %', v_taux_remise * 100, '%';
END;
$$ LANGUAGE plpgsql;

4. Cas d'application en Data Engineering : Contrôle qualité d'ingestion#

Dans un pipeline de données, avant de charger une table de reporting finale, on effectue des contrôles préalables de volumétrie et de cohérence :

Validation de volumétrie avant chargement
DO
$$
DECLARE
    v_nb_lignes INTEGER;
    c_seuil_minimal CONSTANT INTEGER := 1000;
BEGIN
    -- 1. Comptage des données reçues dans la table de staging
    SELECT COUNT(*) INTO v_nb_lignes FROM staging.commandes_brutes;

    -- 2. Évaluation de la complétude
    IF v_nb_lignes = 0 THEN
        RAISE EXCEPTION 'ÉCHEC PIPELINE : La table staging est vide ! Abandon immédiat.';
    ELSIF v_nb_lignes < c_seuil_minimal THEN
        RAISE WARNING 'ALERTE : Seulement % lignes reçues (attendu : au moins %). Chargement sous surveillance.',
            v_nb_lignes, c_seuil_minimal;
        -- Déclenchement de la procédure de chargement avec marquage
        PERFORM etl.charger_avec_reserve();
    ELSE
        RAISE NOTICE 'SUCCESS : % enregistrements prêts. Lancement de la consolidation.', v_nb_lignes;
        PERFORM etl.charger_table_finale();
    END IF;
END;
$$ LANGUAGE plpgsql;

5. Mise en pratique : Détecteur et nettoyeur de doublons#

Objectif#

Écrire un bloc anonyme PL/pgSQL qui : 1. Compte le nombre d'adresses email dupliquées dans une table temporaire tmp_prospects. 2. Si des doublons sont présents, journalise un avertissement avec le nombre de doublons trouvés, puis purge les doublons en ne conservant que l'entrée ayant l'identifiant le plus récent. 3. Si aucun doublon n'existe, valide le bon état de la table.

Solution de l'exercice
DO
$$
DECLARE
    v_doublons_count INTEGER;
BEGIN
    -- Comptage des doublons sur le champ email
    SELECT COUNT(*)
    INTO v_doublons_count
    FROM (
        SELECT email
        FROM tmp_prospects
        GROUP BY email
        HAVING COUNT(*) > 1
    ) sub;

    IF v_doublons_count > 0 THEN
        RAISE WARNING 'DOUBLONS DÉTECTÉS : % emails en double identifiés.', v_doublons_count;

        -- Déduplication propre : suppression des doublons anciens
        DELETE FROM tmp_prospects
        WHERE id NOT IN (
            SELECT MAX(id)
            FROM tmp_prospects
            GROUP BY email
        );

        RAISE NOTICE 'NETTOYAGE EFFECTUÉ : Table assainie avec succès.';
    ELSE
        RAISE NOTICE 'CONTRÔLE VALIDÉ : Aucun doublon dans la table des prospects.';
    END IF;
END;
$$ LANGUAGE plpgsql;

Grâce aux conditions, vos scripts prennent des décisions autonomes et sécurisent vos données. Dans la leçon suivante, nous aborderons les Structures Répétitives (Boucles LOOP, WHILE et FOR) pour automatiser les traitements itératifs.

Commentaires

Inscrivez-vous à une formation complète

Voir le catalogue