CodeGym /Cours /SQL SELF /Gestion des erreurs lors du chargement des données (

Gestion des erreurs lors du chargement des données ( ON CONFLICT)

SQL SELF
Niveau 23 , Leçon 3
Disponible

Bienvenue au cœur des scénarios dramatiques du chargement massif de données ! Aujourd’hui, on va apprendre à gérer efficacement les erreurs qui apparaissent pendant l’import de données, grâce à la clause ON CONFLICT. C’est un peu comme activer le pilote automatique dans un avion : même si ça part en vrille, tu sauras quoi faire pour éviter la cata. Allez, on va décortiquer les subtilités de PostgreSQL !

Personne n’aime les surprises, surtout quand les données refusent de s’importer ! Pendant les imports massifs, tu peux tomber sur plusieurs problèmes classiques :

  • Doublons de données. Par exemple, si ta table a une contrainte UNIQUE et que ton fichier de données est blindé de répétitions.
  • Conflits avec les contraintes. Genre, tu essaies d’importer une valeur vide dans une colonne avec la contrainte NOT NULL. Résultat ? Erreur. PostgreSQL est toujours strict dans ces cas-là.
  • Infos primaires dupliquées. La table peut déjà contenir des données avec les mêmes identifiants que ton fichier CSV.

Voyons comment éviter ces "pièges" avec ON CONFLICT.

Utiliser ON CONFLICT pour gérer les erreurs

La syntaxe de ON CONFLICT te permet de dire quoi faire en cas de conflit avec une contrainte (genre UNIQUE ou PRIMARY KEY). PostgreSQL te laisse soit mettre à jour les données existantes, soit ignorer la ligne en conflit.

Voilà à quoi ressemble la syntaxe de base de ON CONFLICT :

INSERT INTO table_name (column1, column2, ...)
VALUES (value1, value2, ...)
ON CONFLICT (conflict_target)
DO UPDATE SET column1 = new_value1, column2 = new_value2;

Tu peux remplacer DO UPDATE par DO NOTHING si tu veux juste ignorer le conflit.

Exemple : mise à jour des données en cas de conflit

Imaginons qu’on a une table students :

CREATE TABLE students (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL,
    age INT
);

Maintenant, on veut importer de nouvelles données, mais certaines existent déjà dans la base :

INSERT INTO students (id, name, age)
VALUES 
    (1, 'Peter', 22),  -- Cet étudiant existe déjà
    (2, 'Anna', 20),  -- Nouvel étudiant
    (3, 'Mal', 25) -- Nouvel étudiant
ON CONFLICT (id) DO UPDATE SET 
    name = EXCLUDED.name, 
    age = EXCLUDED.age;

Dans cet exemple, si un étudiant avec cet ID existe déjà, ses données seront mises à jour :

ON CONFLICT (id) DO UPDATE SET
    name = EXCLUDED.name, 
    age = EXCLUDED.age;

Fais gaffe au mot magique EXCLUDED. Ça veut dire "les valeurs que tu as essayé d’insérer mais qui ont été exclues à cause du conflit".

Résultat :

  • L’étudiant avec id = 1 verra ses infos (nom et âge) mises à jour.
  • Les étudiants avec id = 2 et id = 3 seront ajoutés à la table.

Exemple : ignorer les conflits

Si tu ne veux pas mettre à jour les données, mais juste ignorer les lignes qui posent problème, utilise DO NOTHING :

INSERT INTO students (id, name, age)
VALUES 
    (1, 'Peter', 22),  -- Cet étudiant existe déjà
    (2, 'Anna', 20),  -- Nouvel étudiant
    (3, 'Mal', 25) -- Nouvel étudiant
ON CONFLICT (id) DO NOTHING;

Maintenant, les lignes en conflit ne seront pas insérées, et les autres s’installeront tranquillou dans ta base.

Logger les erreurs

Parfois, ignorer ou mettre à jour ne suffit pas. Par exemple, tu veux enregistrer les conflits pour les analyser plus tard. On peut créer une table spéciale pour logger les erreurs :

CREATE TABLE conflict_log (
    conflict_time TIMESTAMP DEFAULT NOW(),
    id INT,
    name TEXT,
    age INT,
    conflict_reason TEXT
);

Ensuite, on ajoute la gestion des erreurs avec logging :

INSERT INTO students (id, name, age)
VALUES 
    (1, 'Peter', 22), 
    (2, 'Anna', 20), 
    (3, 'Mal', 25)
ON CONFLICT (id) DO UPDATE SET 
    name = EXCLUDED.name, 
    age = EXCLUDED.age
RETURNING EXCLUDED.id, EXCLUDED.name, EXCLUDED.age
INTO conflict_log;

Ce dernier exemple ne marche que dans les procédures stockées. Tu verras comment ça marche quand on étudiera PL-SQL. J’ai un peu grillé les étapes, mais je voulais te montrer une autre façon de gérer les conflits d’import : logger toutes les lignes problématiques.

Maintenant tu peux analyser les raisons des conflits. Cette technique est super utile dans les systèmes complexes où il est important de garder une "trace" lors des imports massifs.

Exemple pratique

On va rassembler tout ce qu’on a vu dans un exercice simple. Imagine que tu as un fichier CSV avec des updates d’étudiants que tu veux importer dans la table :

Fichier students_update.csv

id name age
1 Otto 23
2 Anna 21
4 Wally 30

Import des données et gestion des conflits

  1. D’abord, on crée une table temporaire tmp_students :
CREATE TEMP TABLE tmp_students (
  id   INTEGER,
  name TEXT,
  age  INTEGER
);
  1. On importe les données du fichier avec \COPY :
\COPY tmp_students FROM 'students_update.csv' DELIMITER ',' CSV HEADER
  1. On insère les données de la table temporaire dans la table principale avec INSERT ON CONFLICT :
INSERT INTO students (id, name, age)
SELECT id, name, age FROM tmp_students
ON CONFLICT (id) DO UPDATE
  SET name = EXCLUDED.name,
      age = EXCLUDED.age;

Maintenant, toutes les données, y compris les updates (la ligne avec id = 1), sont importées avec succès.

Erreurs courantes et comment les éviter

Les erreurs arrivent même aux devs les plus expérimentés, mais en sachant comment les éviter, tu peux économiser des heures (voire des jours) de galère.

  • Conflit avec la contrainte UNIQUE. Vérifie que tu as bien indiqué le bon champ dans ON CONFLICT. Par exemple, si tu mets la mauvaise clé (id au lieu de email), PostgreSQL va juste dire "ciao" à ta requête.
  • Mauvaise utilisation de EXCLUDED. Ce pseudo-nom ne sert que pour les valeurs passées dans la requête actuelle. Essaie pas de l’utiliser ailleurs.
  • Oubli de colonnes. Vérifie que toutes les colonnes dans SET existent dans la table. Par exemple, si tu ajoutes SET non_existing_column = 'value', tu vas te prendre une erreur.

L’utilisation de ON CONFLICT rend l’import massif de données dans PostgreSQL flexible et safe. Tu peux non seulement éviter que tes requêtes plantent à cause des conflits, mais aussi contrôler comment tes données sont gérées. Tes utilisateurs (et tes serveurs !) te diront merci.

Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION