Implementasi UPSERT sangat kompleks agar aman terhadap akses tulis bersamaan. Lihatlah Wiki Postgres ini yang berfungsi sebagai log selama pengembangan awal. Peretas Postgres memutuskan untuk tidak menyertakan baris "dikecualikan" di RETURNING
klausa untuk rilis pertama di Postgres 9.5. Mereka mungkin membangun sesuatu untuk rilis berikutnya.
Ini adalah pernyataan penting dalam manual untuk menjelaskan situasi Anda:
Sintaks dari
RETURNING
list identik dengan daftar keluaranSELECT
. Hanya baris yang berhasil dimasukkan atau diperbarui yang akan dikembalikan. Misalnya, jika sebuah baris dikunci tetapi tidak diperbarui karenaON CONFLICT DO UPDATE ... WHERE
kondisi klausa tidak terpenuhi, baris tidak akan dikembalikan.
Penekanan saya yang berani.
Untuk satu baris untuk menyisipkan:
Tanpa beban tulis bersamaan pada tabel yang sama
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;
Dengan kemungkinan beban tulis bersamaan di atas meja
Pertimbangkan ini sebagai gantinya (untuk baris tunggal INSERT
):
- Apakah SELECT atau INSERT dalam fungsi rentan terhadap kondisi balapan?
Untuk menyisipkan kumpulan baris :
-
Bagaimana cara menggunakan RETURNING dengan ON CONFLICT di PostgreSQL?
-
Bagaimana cara memasukkan baris yang dikecualikan di RETURNING from INSERT ... ON CONFLICT
Ketiganya dengan penjelasan yang sangat detail.