A implementação do UPSERT é extremamente complexa para ser segura contra acesso simultâneo de gravação. Dê uma olhada neste Postgres Wiki que serviu como log durante o desenvolvimento inicial. Os hackers do Postgres decidiram não incluir linhas "excluídas" no
RETURNING
cláusula para o primeiro lançamento no Postgres 9.5. Eles podem construir algo para a próxima versão. Esta é a declaração crucial no manual para explicar sua situação:
A sintaxe doRETURNING
lista é idêntica à lista de saída deSELECT
. Somente as linhas inseridas ou atualizadas com êxito serão retornadas. Por exemplo, se uma linha foi bloqueada, mas não atualizada, porque umON CONFLICT DO UPDATE ... WHERE
condição da cláusula não foi satisfeita, a linha não será retornada.
Minha ênfase em negrito.
Para uma linha única inserir:
Sem carga de gravação simultânea na mesma tabela
WITH ins AS (
INSERT INTO users(name)
VALUES ('new_usr_name') -- input value
ON CONFLICT(name) DO NOTHING
RETURNING users.id
)
SELECT id FROM ins
UNION ALL
SELECT id FROM users -- 2nd SELECT never executed if INSERT successful
WHERE name = 'new_usr_name' -- input value a 2nd time
LIMIT 1;
Com possível carga de gravação simultânea na tabela
Considere isso (para linha única
INSERT
):- O SELECT ou INSERT está em uma função propensa a condições de corrida?
Para inserir um conjunto de linhas :
-
Como usar RETURNING com ON CONFLICT no PostgreSQL?
-
Como incluir linhas excluídas em RETURNING from INSERT ... ON CONFLICT
Todos os três com explicação muito detalhada.