( tl;dr
:goto opsi 3:INSERT with RETURNING )
Ingat bahwa di postgresql tidak ada konsep "id" untuk tabel, hanya urutan (yang biasanya tetapi tidak selalu digunakan sebagai nilai default untuk kunci primer pengganti, dengan tipe semu SERIAL).
Jika Anda tertarik untuk mendapatkan id dari baris yang baru dimasukkan, ada beberapa cara:
Opsi 1:CURRVAL(<sequence name>);
.
Misalnya:
INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John');
SELECT currval('persons_id_seq');
Nama urutannya harus diketahui, itu benar-benar arbitrer; dalam contoh ini kita asumsikan bahwa tabel persons
memiliki id
kolom dibuat dengan SERIAL
tipe semu. Untuk menghindari mengandalkan ini dan untuk merasa lebih bersih, Anda dapat menggunakan pg_get_serial_sequence
sebagai gantinya :
INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John');
SELECT currval(pg_get_serial_sequence('persons','id'));
Peringatan:currval()
hanya berfungsi setelah INSERT
(yang telah mengeksekusi nextval()
), dalam sesi yang sama .
Opsi 2:LASTVAL();
Ini mirip dengan yang sebelumnya, hanya saja Anda tidak perlu menentukan nama urutan:ini mencari urutan modifikasi terbaru (selalu di dalam sesi Anda, peringatan yang sama seperti di atas).
Keduanya CURRVAL
dan LASTVAL
benar-benar bersamaan aman. Perilaku urutan di PG dirancang agar sesi yang berbeda tidak akan mengganggu, sehingga tidak ada risiko kondisi balapan (jika sesi lain menyisipkan baris lain antara INSERT dan SELECT saya, saya masih mendapatkan nilai yang benar).
Namun mereka memiliki potensi masalah yang halus. Jika database memiliki beberapa PEMICU (atau ATURAN) itu, pada penyisipan ke persons
tabel, buat beberapa penyisipan tambahan di tabel lain... lalu LASTVAL
mungkin akan memberi kita nilai yang salah. Masalahnya bahkan dapat terjadi dengan CURRVAL
, jika penyisipan tambahan dilakukan ke persons
yang sama tabel (ini lebih jarang terjadi, tetapi risikonya tetap ada).
Opsi 3:INSERT
dengan RETURNING
INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John') RETURNING id;
Ini adalah cara yang paling bersih, efisien dan aman untuk mendapatkan id. Itu tidak memiliki risiko sebelumnya.
Kekurangan? Hampir tidak ada:Anda mungkin perlu mengubah cara Anda memanggil pernyataan INSERT Anda (dalam kasus terburuk, mungkin lapisan API atau DB Anda tidak mengharapkan INSERT untuk mengembalikan nilai); itu bukan SQL standar (siapa peduli); ini tersedia sejak Postgresql 8.2 (Des 2006...)
Kesimpulan:Jika bisa, pilih opsi 3. Di tempat lain, pilih 1.
Catatan:semua metode ini tidak berguna jika Anda bermaksud mendapatkan id yang terakhir dimasukkan secara global (belum tentu menurut sesi Anda). Untuk ini, Anda harus menggunakan SELECT max(id) FROM table
(tentu saja, ini tidak akan membaca sisipan yang tidak terikat dari transaksi lain).
Sebaliknya, Anda harus tidak pernah gunakan SELECT max(id) FROM table
alih-alih salah satu dari 3 opsi di atas, untuk mendapatkan id yang baru saja dibuat oleh INSERT
. Anda pernyataan, karena (terlepas dari kinerja) ini tidak aman secara bersamaan:antara INSERT
. Anda dan SELECT
sesi lain mungkin telah memasukkan catatan lain.