Skip to content

Faça upsert de uma linha (INSERT ou UPDATE numa só statement) snippet

Um upsert insere a linha se ela não existe e atualiza-a se existir — numa ÚNICA statement, sem a race de ler-para-depois-escrever.

Um upsert insere a linha se ela não existe e atualiza-a se existir — numa ÚNICA statement, sem a race de ler-para-depois-escrever. O passo-a-passo ingénuo (SELECT, depois INSERT ou UPDATE) corrompe dados sob concorrência: dois escritores falham ambos o SELECT e ambos inserem. ON CONFLICT é a resposta do Postgres; o MySQL escreve-o ON DUPLICATE KEY UPDATE e o SQLite copia a sintaxe do Postgres. Duas coisas decidem a correção: o alvo do conflito tem de ser uma unique constraint ou primary key verdadeira, e o DO UPDATE precisa da pseudo-tabela excluded.* para ler os valores que falharam ao inserir.

Receita executável · 1 linguagens
Files & Datasqlupsertinserton-conflictpostgres

Every language

1 linguagens, 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 →