Đối với hàng nghìn bản ghi
1. Tạo một bảng tạm thời gồm các hàng đầu vào, bao gồm các giá trị của bạn $1
, $2
, $3
. Cách tải lên nhanh nhất là COPY
- hoặc \copy
lệnh meta của psql
nếu dữ liệu không nằm trên cùng một máy. Giả sử bảng này:
CREATE TEMP TABLE tmp(id int PRIMARY KEY, val1 text, val2 text);
Tôi đã thêm một ràng buộc PK, điều này là hoàn toàn tùy chọn, nhưng nó đảm bảo rằng chúng tôi đang xử lý các giá trị int not-null duy nhất. Nếu bạn có thể đảm bảo cho dữ liệu đầu vào, bạn không cần phải ràng buộc.
2. Chuỗi các lệnh của bạn với các CTE sửa đổi dữ liệu. Như chúng tôi đã xác định trong câu hỏi trước của bạn , không có điều kiện chủng tộc nào để thực hiện trong hoạt động cụ thể này.
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;
Bước 1. và 2. phải chạy trong cùng một phiên (không nhất thiết phải là cùng một giao dịch), vì phạm vi của các bảng tạm thời được ràng buộc với cùng một phiên.
Lưu ý, UPDATE
chỉ phụ thuộc vào INSERT
đầu tiên , thành công của INSERT
thứ 2 được đảm bảo, vì không có ON CONFLICT DO NOTHING
và toàn bộ hoạt động sẽ được khôi phục nếu có bất kỳ xung đột nào trong INSERT
thứ 2 .
Có liên quan:
Chỉ cho một vài bản ghi
Có nhiều lựa chọn như thế nào. Ý tưởng của bạn để truyền một mảng JSON cho một hàm là một trong số đó. Nếu các đối tượng khớp với bảng đích, bạn có thể sử dụng json_populate_recordset()
trong một INSERT
duy nhất truy vấn. Hoặc chỉ sử dụng INSERT
(như câu lệnh đã chuẩn bị) mà không có trình bao bọc hàm.
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" }]');
Đối với chỉ một số ít cột, bạn cũng có thể chuyển một mảng cho mỗi cột và lặp qua chúng song song. Bạn có thể làm điều này với một vòng lặp đơn giản trên chỉ mục mảng. Vì Postgres 9.4 cũng có unnest()
tiện lợi với nhiều tham số để thực hiện tất cả trong một truy vấn:
Giải pháp tốt nhất tùy thuộc vào định dạng dữ liệu mà bạn có .