Multiple INSERTS into one table and many to many table Multiple INSERTS into one table and many to many table database database

Multiple INSERTS into one table and many to many table


You can do it all in one SQL command using CTEs.

Assuming Postgres 9.6 and this classic many-to-many schema (since you did not provide it):

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));

To insert a single question with an array of tags:

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_idFROM   q, (   SELECT tag_id   FROM   t                                -- newly inserted   UNION  ALL   SELECT tag_id   FROM   input_tags JOIN tags USING (tag) -- pre-existing   ) t;

dbfiddle here

This creates any tags that do not exist yet on the fly.

The text representation of a Postgres array looks like this: {tag1, tag2, tag3}.

If the input array is guaranteed to have distinct tags, you can remove DISTINCT from the CTE input_tags.

Detailed explanation:

If you have concurrent writes you may have to do more. Consider the second link in particular.