Utilice CTE de modificación de datos :
WITH ins1 AS (
INSERT INTO sample(firstname, lastname)
VALUES ('fai55', 'shaggk')
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;
Cada uno INSERT
depende del anterior. SELECT
en lugar de, VALUES
se asegura de que no se inserte nada en las tablas subsidiarias si no se devuelve ninguna fila de una anterior INSERT
. (Desde Postgres 9.5+, puede agregar un ON CONFLICT
.)
También es un poco más corto y rápido de esta manera.
Por lo general, es más conveniente proporcionar filas de datos completas en un solo lugar :
WITH data(firstname, lastname, adddetails, value) AS (
VALUES
('fai55', 'shaggk', 'ss', 'ss2')
, ('fai56', 'XXaggk', 'xx', 'xx2')
)
, ins1 AS (
INSERT INTO sample (firstname, lastname)
SELECT firstname, lastname
FROM data
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 <> violín aquí
Es posible que necesite conversiones de tipos explícitas en una VALUES
expresión independiente , a diferencia de una VALUES
expresión adjunta a una INSERT
donde los tipos de datos se derivan de la tabla de destino. Ver:
Si varias filas pueden tener idénticas (firstname, lastname)
, es posible que deba doblar duplicados para la primera INSERT
:
...
INSERT INTO sample (firstname, lastname)
SELECT DISTINCT firstname, lastname FROM data
...
Puede utilizar una tabla (temporal) como fuente de datos en lugar del CTE data
.
Probablemente tendría sentido combinar esto con una restricción ÚNICA (firstname, lastname)
en la tabla y una ON CONFLICT
cláusula en la consulta.
Relacionado: