PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Obter ID de um INSERT condicional


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 do RETURNING lista é idêntica à lista de saída de SELECT . Somente as linhas inseridas ou atualizadas com êxito serão retornadas. Por exemplo, se uma linha foi bloqueada, mas não atualizada, porque um ON 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.