Använd datamodifierande CTE :
WITH ins1 AS (
INSERT INTO sample(firstname, lastname)
VALUES ('fai55', 'shaggk')
-- ON CONFLICT DO NOTHING -- optional addition in Postgres 9.5+
RETURNING id AS sample_id
)
, ins2 AS (
INSERT INTO sample1 (sample_id, adddetails)
SELECT sample_id, 'ss' FROM ins1
RETURNING user_id
)
INSERT INTO sample2 (user_id, value)
SELECT user_id, 'ss2' FROM ins2;
Varje INSERT
beror på den tidigare. SELECT
istället för VALUES
ser till att ingenting infogas i underordnade tabeller om ingen rad returneras från en tidigare INSERT
. (Sedan Postgres 9.5+ kan du lägga till en ON CONFLICT
.)
Det är också lite kortare och snabbare på det här sättet.
Vanligtvis är det bekvämare att tillhandahålla fullständiga datarader på ett ställe :
WITH data(firstname, lastname, adddetails, value) AS (
VALUES -- provide data here
('fai55', 'shaggk', 'ss', 'ss2') -- see below
, ('fai56', 'XXaggk', 'xx', 'xx2') -- works for multiple input rows
-- more?
)
, ins1 AS (
INSERT INTO sample (firstname, lastname)
SELECT firstname, lastname -- DISTINCT? see below
FROM data
-- ON CONFLICT DO NOTHING -- UNIQUE constraint? see below
RETURNING firstname, lastname, id AS sample_id
)
, ins2 AS (
INSERT INTO sample1 (sample_id, adddetails)
SELECT ins1.sample_id, d.adddetails
FROM data d
JOIN ins1 USING (firstname, lastname)
RETURNING sample_id, user_id
)
INSERT INTO sample2 (user_id, value)
SELECT ins2.user_id, d.value
FROM data d
JOIN ins1 USING (firstname, lastname)
JOIN ins2 USING (sample_id);
db<>spela här
Du kan behöva explicita typcasts i en fristående VALUES
uttryck - i motsats till en VALUES
uttryck kopplat till en INSERT
där datatyper härleds från måltabellen. Se:
- Casta NULL-typ vid uppdatering av flera rader
Om flera rader kan komma med identisk (firstname, lastname)
, kan du behöva vika dubbletter för den första INSERT
:
...
INSERT INTO sample (firstname, lastname)
SELECT DISTINCT firstname, lastname FROM data
...
Du kan använda en (tillfällig) tabell som datakälla istället för CTE data
.
Det skulle förmodligen vara vettigt att kombinera detta med en UNIK begränsning på (firstname, lastname)
i tabellen och en ON CONFLICT
klausul i frågan.
Relaterat:
- Hur använder man RETURNING med ON CONFLICT i PostgreSQL?
- Är SELECT eller INSERT i en funktion utsatt för tävlingsförhållanden?