Skip to content

Faire un upsert d'une ligne (INSERT ou UPDATE en une seule instruction) snippet

Un upsert insère la ligne si elle n'existe pas et la met à jour sinon — en UNE seule instruction, sans la course read-then-write.

Un upsert insère la ligne si elle n'existe pas et la met à jour sinon — en UNE seule instruction, sans la course read-then-write. Les deux étapes naïves (SELECT, puis INSERT ou UPDATE) corrompent les données en concurrence : deux écrivains ratent tous les deux le SELECT et insèrent tous les deux. ON CONFLICT est la réponse Postgres ; MySQL l'écrit ON DUPLICATE KEY UPDATE et SQLite copie la syntaxe de Postgres. Deux choses décident de la justesse : la cible du conflit doit être une vraie contrainte d'unicité ou une clé primaire, et DO UPDATE a besoin de la pseudo-table excluded.* pour lire les valeurs qui ont échoué à l'insertion.

Recette exécutable · 1 langages
Files & Datasqlupsertinserton-conflictpostgres

Every language

1 langages, copy-ready. One at a time with syntax highlighting, or all inline.

SQLSQLrunnable
INSERT INTO users (id, email, name)
VALUES (42, 'ada@example.com', 'Ada')
ON CONFLICT (id) DO UPDATE
    SET email = excluded.email,
        name  = excluded.name
RETURNING id, (xmax = 0) AS inserted_this_time;

excluded holds the row that failed to insert — read the challenger's values from it, not from the table. ON CONFLICT DO NOTHING is the ignore-duplicates variant. Run it twice in the playground: first pass inserts (true), second pass updates (false).

Run in the SQL playground →

Keep going

Read the database-objects cheatsheet →