sql >> Databáze >  >> RDS >> PostgreSQL

Vraťte řádky z INSERT s ON CONFLICT bez nutnosti aktualizace

Je to opakující se problém SELECT or INSERT , týkající se (ale odlišný od) UPSERT. Nová funkce UPSERT v Postgres 9.5 je stále nápomocná.

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;

Tímto způsobem ve skutečnosti nenapíšete novou verzi řádku bez potřeby.

Nicméně , stále existuje malé rohové pouzdro pro závodní podmínky . Souběžné transakce mohly přidat konfliktní řádek, který ještě není viditelný ve stejném příkazu. Poté INSERT a SELECT přijít prázdný.

Správné řešení pro jednořadý UPSERT:

  • Je SELECT nebo INSERT ve funkci náchylný k závodům?

Obecná řešení pro hromadné UPSERT:

  • Jak používat RETURNING s ON CONFLICT v PostgreSQL?

Bez souběžného zatížení zápisu

Pokud souběžné zápisy (z jiné relace) nejsou možné, nemusíte řádek zamykat a můžete to zjednodušit:

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. Jak nahradit všechny výskyty řetězce jiným řetězcem na serveru SQL – REPLACE()

  2. Můj DBA je nemocný – Tipy pro přepnutí databáze při selhání databáze pro správce systému

  3. Oracle DBA Mentor

  4. Jak nevytvářet rozšíření PostgreSQL 9.0 na platformách RPM