Bạn có thể làm tất cả trong một Lệnh SQL sử dụng CTE.
Giả sử Postgres 9.6 và lược đồ nhiều-nhiều cổ điển này (vì bạn không cung cấp):
CREATE TABLE questions (
question_id serial PRIMARY KEY
, title text NOT NULL
, body text
, userid int
, categoryid int
);
CREATE TABLE tags (
tag_id serial PRIMARY KEY
, tag text NOT NULL UNIQUE);
CREATE TABLE questiontags (
question_id int REFERENCES questions
, tag_id int REFERENCES tags
, PRIMARY KEY(question_id, tag_id)
);
Để chèn một single câu hỏi với mảng thẻ :
WITH input_data(body, userid, title, categoryid, tags) AS (
VALUES (:title, :body, :userid, :tags)
)
, input_tags AS ( -- fold duplicates
SELECT DISTINCT tag
FROM input_data, unnest(tags::text[]) tag
)
, q AS ( -- insert question
INSERT INTO questions
(body, userid, title, categoryid)
SELECT body, userid, title, categoryid
FROM input_data
RETURNING question_id
)
, t AS ( -- insert tags
INSERT INTO tags (tag)
TABLE input_tags -- short for: SELECT * FROM input_tags
ON CONFLICT (tag) DO NOTHING -- only new tags
RETURNING tag_id
)
INSERT INTO questiontags (question_id, tag_id)
SELECT q.question_id, t.tag_id
FROM q, (
SELECT tag_id
FROM t -- newly inserted
UNION ALL
SELECT tag_id
FROM input_tags JOIN tags USING (tag) -- pre-existing
) t;
dbfiddle tại đây
Điều này sẽ tạo ra bất kỳ thẻ nào chưa tồn tại.
Biểu diễn văn bản của mảng Postgres trông giống như sau:{tag1, tag2, tag3}
.
Nếu mảng đầu vào được đảm bảo có các thẻ riêng biệt, bạn có thể xóa DISTINCT
từ CTE input_tags
.
Giải thích chi tiết :
- Chèn dữ liệu vào 3 bảng cùng một lúc bằng Postgres
- Làm thế nào để sử dụng RETURNING với ON CONFLICT trong PostgreSQL?
- Làm thế nào để triển khai mối quan hệ nhiều-nhiều trong PostgreSQL?
- Không thể CHÈN:LỖI:giá trị mảng phải bắt đầu bằng" {"hoặc thông tin về thứ nguyên
Nếu bạn có ghi đồng thời bạn có thể phải làm nhiều hơn. Đặc biệt xem xét liên kết thứ hai.