I am beginner in postgres. while working on a dummy project I came across this problem.
I have two tables let say t1 and t2.The t1 having 1->Many relation with t2.
I am trying to write an SQL statement which first inserts data in t1 and using id from t1 inserts the multiple rows in t2.
Something like this.
WITH ins AS (
INSERT INTO t1(t1_col)
VALUES (4)
RETURNING t1_id
)
INSERT INTO t2(t1_id, t2_col) VALUES (ins.t1_id, 3), (ins.t1_id, 4)...
t1 structure -> (t1_id primary_key serial, t1_col integer).
t2 structure -> (t2_id primary_key serial, t1_id integer, t2_col integer).
What is the correct way to do this.
Thank you in advance.
except for inserting with VALUES
clause you can insert the result of SELECT
. in general form it will be:
WITH ins AS (
INSERT INTO table1(target columns)
VALUES (some values) -- or -- SELECT something FROM somewhere
RETURNING some_id
)
INSERT INTO table2(target columns)
SELECT ins.some_id, other columns or expressions
FROM ins;
variant for multiple rows (fixed list)
WITH ins AS (
INSERT INTO table1(target columns)
VALUES (some values) -- or -- SELECT something FROM somewhere
RETURNING some_id
)
INSERT INTO table2(target columns)
SELECT ins.some_id, UNNEST(ARRAY[3,4,...])
FROM ins;
where 3,4.... is the list of values
An anonymous plpgsql block will do.
do language plpgsql
$$
declare
t1id t1.t1_id%type;
begin
INSERT INTO t1(t1_col) VALUES (4) RETURNING t1_id INTO t1id;
INSERT INTO t2(t1_id, t2_col)
VALUES (t1id, 3), (t1id, 4)...;
end;
$$;
This will do it in a single statement.
WITH ins AS (
INSERT INTO t1(t1_col)
VALUES (4)
RETURNING t1_id
)
INSERT INTO t2(t1_id, t2_col)
SELECT ins.t1_id, v.t2_col
from ins
cross join (VALUES (3), (4)) as v(t2_col)
;
If you are running this from a host language and can pass the t2
values as an array, please comment because this can be simplified.
I would build it something like this for use with a host language:
with invars as (
select $1 as t1_col, $2::text[] as t2_cols
), ins as (
insert into t1 (t1_col)
select t1_col
from invars
returning t1_id
)
insert into t2 (t1_id, t2_col)
select ins.t1_id, unnest(invars.t2_cols) as t2_col
from ins
cross join invars;
Then, from the host, I would pass t1_col
and an array of t2_col
values as parameters to the query.
No need for a CTE or variables, you can uselastval()
to get the last generated identity (or sequence) value:
INSERT INTO t1(t1_col)
VALUES (4);
INSERT INTO t2(t1_id, t2_col)
VALUES
(lastval(), 3),
(lastval(), 4),
...
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.