PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Kembalikan baris dari INSERT dengan ON CONFLICT tanpa perlu memperbarui

Ini adalah masalah berulang dari SELECT or INSERT , terkait dengan (tetapi berbeda dari) UPSERT. Fungsionalitas UPSERT baru di Postgres 9.5 masih berperan.

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;

Dengan cara ini Anda tidak benar-benar menulis versi baris baru tanpa perlu.

Namun , masih ada kotak sudut kecil untuk kondisi balapan . Transaksi bersamaan mungkin telah menambahkan baris yang bertentangan, yang belum terlihat dalam pernyataan yang sama. Kemudian INSERT dan SELECT kosong.

Solusi yang tepat untuk UPSERT satu baris:

  • Apakah SELECT atau INSERT dalam fungsi rentan terhadap kondisi balapan?

Solusi umum untuk UPSERT massal:

  • Bagaimana cara menggunakan RETURNING dengan ON CONFLICT di PostgreSQL?

Tanpa beban tulis bersamaan

Jika penulisan bersamaan (dari sesi yang berbeda) tidak memungkinkan, Anda tidak perlu mengunci baris dan dapat menyederhanakan:

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. Bagaimana Tand() Bekerja di PostgreSQL

  2. Mengacu pada alias kolom agregat pilih dalam klausa memiliki di Postgres

  3. PostgreSQL 9.6:Pemindaian Sekuensial Paralel

  4. Penyortiran alami yang mendukung angka besar

  5. Mengelola Ketersediaan Tinggi di PostgreSQL – Bagian III:Patroni