PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Zwróć wiersze z INSERT z ON CONFLICT bez konieczności aktualizacji

To powtarzający się problem SELECT or INSERT , związany z (ale inny niż) UPSERT. Nowa funkcja UPSERT w Postgres 9.5 nadal ma kluczowe znaczenie.

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;

W ten sposób nie piszesz nowej wersji wiersza bez potrzeby.

Jednak , nadal istnieje mały przypadek w przypadku wyścigu . Transakcje współbieżne mogły dodać sprzeczny wiersz, który nie jest jeszcze widoczny w tym samym wyciągu. Następnie INSERT i SELECT wyjdź pusty.

Właściwe rozwiązanie dla UPSERT jednorzędowego:

  • Czy SELECT lub INSERT w funkcji podatnej na wyścigi?

Ogólne rozwiązania dla UPSERT masowych:

  • Jak używać RETURNING z ON CONFLICT w PostgreSQL?

Bez równoczesnego ładowania zapisu

Jeśli współbieżne zapisy (z innej sesji) nie są możliwe, nie trzeba blokować wiersza i można to uprościć:

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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. PostgreSQL:KLUCZ OBCY / PRZY USUWANIU KASKADY

  2. SQLAlchemy wiele kluczy obcych w jednej zmapowanej klasie do tego samego klucza podstawowego

  3. Tablice liczb całkowitych Postgres jako parametry?

  4. Jak działa justify_hours() w PostgreSQL

  5. Jak używać zmiennych w prostym skrypcie PostgreSQL?