1

I have a one-to-many relationship between two tables, where IDs are automatically generated on insertion. I want to insert a single row into the "parent" table, then use the generated ID of that row as a foreign key when I insert multiple rows into the "children" table.

For example, say I have this schema:

CREATE TABLE users (
 id UUID PRIMARY KEY DEFAULT uuid_generate_v4 (),
 username TEXT NOT NULL,
);
CREATE TABLE posts (
 id UUID PRIMARY KEY DEFAULT uuid_generate_v4 (),
 author_user_id UUID NOT NULL REFERENCES users (id),
 body TEXT,
);

In postgres I can insert multiple rows using VALUES:

INSERT INTO
 posts (author_user_id, body)
VALUES
 (<some uuid here>, "Hello, World!"),
 (<some uuid here>, "I'm hungry.");

I can also insert a user and a single post referencing that author using a common table expression:

WITH john AS (
 INSERT INTO
 users (username)
 VALUES
 (john_smith)
 RETURNING
 id
)
INSERT INTO
 posts (author_user_id, body)
SELECT
 john.id, "Hello, World!"
FROM
 john;

Is there a way I can combine the two? i.e. insert a single user, get the ID of that new row, and use that ID when inserting multiple posts?

It doesn't have to be via a CTE if there's a simpler way. Thanks!

asked May 4, 2023 at 9:33

1 Answer 1

4
WITH
cte1 (author_user_id) AS (
 INSERT INTO users (username) 
 VALUES ('John Smith')
 RETURNING id
 ),
cte2 (body) AS (
 VALUES ('Text 1'), ('Text 2')
 )
INSERT INTO posts (author_user_id, body)
SELECT cte1.author_user_id, cte2.body
FROM cte1
CROSS JOIN cte2;

or

WITH
cte (author_user_id) AS (
 INSERT INTO users (username) 
 VALUES ('John Smith')
 RETURNING id
 )
INSERT INTO posts (author_user_id, body)
SELECT cte.author_user_id, subq.body
FROM cte
CROSS JOIN (
 VALUES ('Text 1'), ('Text 2')
 ) AS subq (body);
answered May 4, 2023 at 10:55

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.