Untuk ribuan catatan
1. Buat tabel sementara dari baris input, terdiri dari nilai Anda $1
, $2
, $3
. Cara tercepat untuk mengunggah adalah COPY
- atau \copy
meta-perintah psql
jika data tidak pada mesin yang sama. Misalkan tabel ini:
CREATE TEMP TABLE tmp(id int PRIMARY KEY, val1 text, val2 text);
Saya menambahkan batasan PK, yang sepenuhnya opsional, tetapi memastikan bahwa kita berurusan dengan nilai int not-null yang unik. Jika Anda dapat menjamin data masukan, Anda tidak memerlukan batasan.
2. Rantai perintah Anda dengan CTE pengubah data. Seperti yang telah kami tentukan berdasarkan pertanyaan sebelumnya Anda , tidak ada kondisi balapan yang harus diperhatikan dalam operasi khusus ini.
WITH ins1 AS (
INSERT INTO table1 AS t1 (id, val1, val2)
SELECT id, val1, val2 FROM tmp ON CONFLICT DO NOTHING
RETURNING t1.id, t1.val1, t1.val2 -- only actually inserted rows returned
)
, ins2 AS (
INSERT INTO table2 (table1_id, val1)
SELECT id, val1 FROM ins1
)
UPDATE table3 t3
SET val2 = i.val2
, time = now()
FROM ins1 i
WHERE t3.table1_id = i.id;
Langkah 1. dan 2. harus dijalankan di sesi yang sama (tidak harus transaksi yang sama), karena cakupan tabel sementara terikat pada sesi yang sama.
Perhatikan, UPDATE
hanya bergantung pada INSERT
pertama , keberhasilan INSERT
ke-2 dijamin, karena tidak ada ON CONFLICT DO NOTHING
dan seluruh operasi akan dibatalkan jika ada konflik di INSERT
ke-2 .
Terkait:
Hanya untuk beberapa catatan
Ada berbagai pilihan caranya. Ide Anda untuk meneruskan array JSON ke suatu fungsi adalah salah satunya. Jika objek cocok dengan tabel target, Anda dapat menggunakan json_populate_recordset()
dalam satu INSERT
pertanyaan. Atau cukup gunakan INSERT
(sebagai pernyataan yang disiapkan) tanpa pembungkus fungsi.
INSERT INTO target_tbl -- it's ok to omit target columns here
SELECT *
FROM json_populate_recordset(null::target_tbl, -- use same table type
json '[{ "id": "1", "val1": "1-val1", "val2": "1-val2" },
{ "id": "2", "val1": "2-val1", "val2": "2-val2" },
{ "id": "3", "val1": "3-val1", "val2": "3-val2" },
{ "id": "4", "val1": "4-val1", "val2": "4-val2" }]');
Untuk hanya segelintir kolom, Anda mungkin juga melewatkan larik untuk setiap kolom dan mengulangnya secara paralel. Anda dapat melakukan ini dengan loop sederhana pada indeks array. Sejak Postgres 9.4 ada juga unnest()
convenient yang nyaman dengan beberapa parameter untuk melakukan semuanya dalam satu kueri:
Solusi terbaik bergantung pada format data yang Anda miliki .