Phiên bản cuối cùng
... sau một số thông tin thêm từ OP. Hãy xem xét bản trình diễn này:
-- 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)
);
Chèn giá trị - bar
đầu tiên.
Nó sẽ rất hữu ích nếu bạn đã cung cấp dữ liệu thử nghiệm trong câu hỏi của mình như thế này!
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);
Đặt các chuỗi thành giá trị hiện tại nếu không chúng tôi nhận được các lỗi vi phạm chính trùng lặp:
SELECT setval('foo_id_seq', 3);
SELECT setval('bar_id_seq', 102);
Séc:
-- SELECT nextval('foo_id_seq')
-- SELECT nextval('bar_id_seq')
-- SELECT * from bar;
-- SELECT * from foo;
Truy vấn:
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);
Điều này sẽ thực hiện những gì mà bản cập nhật cuối cùng của bạn mô tả.
Truy vấn giả định rằng z
là UNIQUE
. Nếu z
không phải là duy nhất, nó trở nên phức tạp hơn. Tham khảo Truy vấn 2 trong câu trả lời liên quan này để biết giải pháp sẵn sàng bằng cách sử dụng hàm window row_number()
trong trường hợp này.
Ngoài ra, hãy xem xét thay thế mối quan hệ 1:1 giữa foo
và bar
với một bảng thống nhất.
CTE sửa đổi dữ liệu
Câu trả lời thứ hai sau khi biết thêm thông tin.
Nếu bạn muốn thêm hàng vào foo
và bar
trong một truy vấn duy nhất, bạn có thể sử dụng CTE sửa đổi dữ liệu kể từ 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;
Tôi lấy các giá trị từ foo
, chèn chúng vào bar
, chúng được trả về cùng nhau bằng bar_id
được tạo tự động và chèn that thành foo
. Bạn cũng có thể sử dụng bất kỳ dữ liệu nào khác.
Đây là bản demo hoạt động để chơi trên sqlfiddle.
Kiến thức cơ bản
Câu trả lời gốc với thông tin cơ bản trước khi làm rõ.
Dạng cơ bản là:
INSERT INTO foo (...)
SELECT ... FROM foo WHERE ...
Không cần dấu ngoặc đơn. Bạn có thể làm tương tự với bất kỳ bảng nào
INSERT INTO foo (...)
SELECT ... FROM bar WHERE ...
Và bạn có thể tham gia vào bảng mà bạn chèn vào trong phần CHỌN:
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
Nó chỉ là một CHỌN giống như bất kỳ lệnh nào khác - có thể bao gồm bảng bạn đang chèn vào. Các hàng được đọc trước tiên, sau đó được chèn vào.