Brug datamodificerende CTE'er :
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;
Hver INSERT
afhænger af den før. SELECT
i stedet for VALUES
sørger for, at intet er indsat i underordnede tabeller, hvis ingen række returneres fra en tidligere INSERT
. (Siden Postgres 9.5+ kan du tilføje en ON CONFLICT
.)
Det er også lidt kortere og hurtigere på denne måde.
Typisk er det mere bekvemt at give komplette datarækker ét sted :
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<>spil her
Du har muligvis brug for eksplicitte typecasts i en selvstændig VALUES
udtryk - i modsætning til en VALUES
udtryk knyttet til en INSERT
hvor datatyper er afledt fra måltabellen. Se:
- Caster NULL-typen ved opdatering af flere rækker
Hvis flere rækker kan komme med identiske (firstname, lastname)
, skal du muligvis folde dubletter for den første INSERT
:
...
INSERT INTO sample (firstname, lastname)
SELECT DISTINCT firstname, lastname FROM data
...
Du kan bruge en (midlertidig) tabel som datakilde i stedet for CTE data
.
Det ville nok give mening at kombinere dette med en UNIK begrænsning på (firstname, lastname)
i tabellen og en ON CONFLICT
klausul i forespørgslen.
Relateret:
- Hvordan bruger man RETURNING med ON CONFLICT i PostgreSQL?
- Er SELECT eller INSERT i en funktion, der er tilbøjelig til løbsforhold?