sql >> Database teknologi >  >> RDS >> PostgreSQL

Returner rækker fra INSERT med ON CONFLICT uden at skulle opdatere

Det er det tilbagevendende problem med SELECT or INSERT , relateret til (men forskellig fra) en UPSERT. Den nye UPSERT-funktionalitet i Postgres 9.5 er stadig medvirkende.

WITH ins AS (
   INSERT INTO names(name)
   VALUES ('bob')
   ON     CONFLICT ON CONSTRAINT names_name_key DO UPDATE
   SET    name = NULL
   WHERE  FALSE      -- never executed, but locks the row
   RETURNING id
   )
SELECT id FROM ins
UNION  ALL
SELECT id FROM names
WHERE  name = 'bob'  -- only executed if no INSERT
LIMIT  1;

På denne måde skriver du faktisk ikke en ny rækkeversion uden behov.

Men , er der stadig en lille hjørnekasse til en løbstilstand . Samtidige transaktioner kan have tilføjet en modstridende række, som endnu ikke er synlig i samme opgørelse. Derefter INSERT og SELECT komme op tom.

Korrekt løsning til enkeltrækket UPSERT:

  • Er SELECT eller INSERT i en funktion, der er tilbøjelig til løbsforhold?

Generelle løsninger til bulk UPSERT:

  • Hvordan bruger man RETURNING med ON CONFLICT i PostgreSQL?

Uden samtidig skrivebelastning

Hvis samtidige skrivninger (fra en anden session) ikke er mulige, behøver du ikke låse rækken og kan forenkle:

WITH ins AS (
   INSERT INTO names(name)
   VALUES ('bob')
   ON     CONFLICT ON CONSTRAINT names_name_key DO NOTHING  -- no lock needed
   RETURNING id
   )
SELECT id FROM ins
UNION  ALL
SELECT id FROM names
WHERE  name = 'bob'  -- only executed if no INSERT
LIMIT  1;



  1. Udtræk ugenummeret fra en dato i SQL Server (T-SQL)

  2. Hvorfor kan jeg ikke bruge et alias i en DELETE-sætning?

  3. Er du sorteret? Tips vedrørende T-SQL-vinduebestilling

  4. Sådan bruger du flere databaser i Laravel