Versi final
... setelah beberapa info lebih lanjut dari OP. Pertimbangkan demo ini:
-- DROP TABLE foo; DROP TABLE bar;
CREATE TEMP TABLE bar (
id serial PRIMARY KEY -- using a serial column!
,z integer NOT NULL
);
CREATE TEMP TABLE foo (
id serial PRIMARY KEY -- using a serial column!
,x integer NOT NULL
,y integer NOT NULL
,bar_id integer UNIQUE NOT NULL REFERENCES bar(id)
);
Masukkan nilai - bar
pertama.
Akan sangat membantu jika Anda memberikan data uji dalam pertanyaan Anda seperti ini!
INSERT INTO bar (id,z) VALUES
(100, 7)
,(101,16)
,(102,21);
INSERT INTO foo (id, x, y, bar_id) VALUES
(1, 3,4,100)
,(2, 9,6,101)
,(3,18,0,102);
Setel urutan ke nilai saat ini atau kami mendapatkan pelanggaran kunci duplikat:
SELECT setval('foo_id_seq', 3);
SELECT setval('bar_id_seq', 102);
Cek:
-- SELECT nextval('foo_id_seq')
-- SELECT nextval('bar_id_seq')
-- SELECT * from bar;
-- SELECT * from foo;
Pertanyaan:
WITH a AS (
SELECT f.x, f.y, bar_id, b.z
FROM foo f
JOIN bar b ON b.id = f.bar_id
WHERE x > 3
),b AS (
INSERT INTO bar (z)
SELECT z
FROM a
RETURNING z, id AS bar_id
)
INSERT INTO foo (x, y, bar_id)
SELECT a.x, a.y, b.bar_id
FROM a
JOIN b USING (z);
Ini akan melakukan apa yang dijelaskan oleh pembaruan terakhir Anda.
Kueri mengasumsikan bahwa z
adalah UNIQUE
. Jika z
tidak unik, itu menjadi lebih kompleks. Lihat Kueri 2 dalam jawaban terkait ini untuk solusi siap pakai menggunakan fungsi jendela row_number()
dalam hal ini.
Juga, pertimbangkan untuk mengganti relasi 1:1 antara foo
dan bar
dengan satu meja bersatu.
CTE memodifikasi data
Jawaban kedua setelah info lebih lanjut.
Jika Anda ingin menambahkan baris ke foo
dan bar
dalam satu kueri, Anda dapat menggunakan CTE yang memodifikasi data sejak PostgreSQL 9.1 :
WITH x AS (
INSERT INTO bar (col1, col2)
SELECT f.col1, f.col2
FROM foo f
WHERE f.id BETWEEN 12 AND 23 -- some filter
RETURNING col1, col2, bar_id -- assuming bar_id is a serial column
)
INSERT INTO foo (col1, col2, bar_id)
SELECT col1, col2, bar_id
FROM x;
Saya mengambil nilai dari foo
, masukkan di bar
, minta mereka kembali bersama dengan bar_id
. yang dibuat secara otomatis dan masukkan itu ke foo
. Anda juga dapat menggunakan data lain.
Berikut adalah demo yang berfungsi untuk dimainkan di sqlfiddle.
Dasar
Jawaban asli dengan informasi dasar sebelum klarifikasi.
Bentuk dasarnya adalah:
INSERT INTO foo (...)
SELECT ... FROM foo WHERE ...
Tidak perlu tanda kurung. Anda dapat melakukan hal yang sama dengan tabel apa pun
INSERT INTO foo (...)
SELECT ... FROM bar WHERE ...
Dan Anda dapat bergabung ke tabel yang Anda masukkan ke dalam SELECT:
INSERT INTO foo (...)
SELECT f.col1, f.col2, .. , b.bar_id
FROM foo f
JOIN bar b USING (foo_id); -- present in foo and bar
Ini hanya SELECT seperti yang lain - yang dapat menyertakan tabel yang Anda masukkan. Baris pertama dibaca, lalu disisipkan.