Cara untuk referensi ID dalam transaksi multi-insert? (postgres)

8

Dengan asumsi tabel "entitas.eid" adalah kenaikan otomatis, saya ingin dapat merujuk nilai kenaikan otomatis yang ditugaskan kemudian dalam transaksi yang sama. Cara saya melakukan ini adalah dengan melakukan beberapa transaksi yang saya pikir tidak optimal.

START TRANSACTION;
INSERT INTO entity ...;
INSERT INTO t2 (eid, ...) VALUES (?NEW EID REF HERE?, ...), (...), (...);
COMMIT;
Tony
sumber

Jawaban:

11

Ada berbagai cara untuk melakukan ini.

Cara termudah adalah dengan menggunakan lastval()fungsi yang akan mengembalikan nilai yang dihasilkan oleh urutan berikutnya "terakhir".

START TRANSACTION;
INSERT INTO entity ...;
INSERT INTO t2 (eid, ...) VALUES (lastval(), ...), (...), (...);
COMMIT;

Jika Anda tahu nama urutan untuk entitytabel Anda juga bisa menggunakan currvalfungsi:

START TRANSACTION;
INSERT INTO entity ...;
INSERT INTO t2 (eid, ...) VALUES (currval('entity_eid_seq'), ...), (...), (...);
COMMIT;

Ini dapat ditulis dengan cara yang lebih umum dengan menggunakan pg_get_serial_sequence()fungsi, menghindari untuk meng-hardcode nama urutan:

START TRANSACTION;
INSERT INTO entity ...;
INSERT INTO t2 (eid, ...) VALUES (currval(pg_get_serial_sequence('entity', 'eid')), ...), (...);
COMMIT;

Untuk detail lebih lanjut, silakan lihat manual: http://www.postgresql.org/docs/current/static/functions-afterence.html

seekor kuda tanpa nama
sumber
7

Anda tidak menentukan versi Postgresql Anda, tetapi jika Anda menggunakan 8.4+ Anda dapat menggunakan RETURNINGklausa untuk mengembalikan id (atau kolom apa saja) yang baru saja dimasukkan.

Documents: http://www.postgresql.org/docs/current/static/sql-insert.html

Contoh:

INSERT INTO t2 (eid, ...) VALUES (...) RETURNING eid;

Jika Anda menggunakan Postgresql versi 9.1+, Anda juga dapat menggunakan WITHklausa (alias Common Table Expressions) untuk melakukan penyisipan ke dalam satu klausa, kemudian referensi nilai dari RETURNINGklausa untuk melakukan lebih banyak tindakan (klausa WITH dapat berantai bersama).

Documents on WITHclause: http://www.postgresql.org/docs/current/static/queries-with.html

bma
sumber
4

Perlu dicatat bahwa SERIAL di Postgres hanyalah sebuah INT dengan SEQUENCE sebagai nilai default, Anda dapat dengan mudah meminta sequencer sendiri dalam suatu transaksi alih-alih memasukkan ke dalam tabel yang memungkinkan terjadinya default.

xenoterracide
sumber