Para miles de registros
$1
, $2
, $3
. La forma más rápida de cargar es COPY
- o el \copy
metacomando de psql
si los datos no están en la misma máquina. Supongamos esta tabla:
CREATE TEMP TABLE tmp(id int PRIMARY KEY, val1 text, val2 text);
Agregué una restricción PK, que es totalmente opcional, pero se asegura de que estemos tratando con valores int únicos no nulos. Si puede garantizar los datos de entrada, no necesita la restricción.
WITH ins1 AS (
INSERT INTO table1 AS t1 (id, val1, val2)
SELECT id, val1, val2 FROM tmp ON CONFLICT DO NOTHING
RETURNING t1.id, t1.val1, t1.val2 -- only actually inserted rows returned
)
, ins2 AS (
INSERT INTO table2 (table1_id, val1)
SELECT id, val1 FROM ins1
)
UPDATE table3 t3
SET val2 = i.val2
, time = now()
FROM ins1 i
WHERE t3.table1_id = i.id;
Los pasos 1 y 2 deben ejecutarse en la misma sesión (no necesariamente la misma transacción), ya que el alcance de las tablas temporales está vinculado a la misma sesión.
Tenga en cuenta que UPDATE
solo depende del 1er INSERT
, éxito del 2º INSERT
está garantizado, ya que no hay ON CONFLICT DO NOTHING
y toda la operación se revertirá si hay algún conflicto en el 2.º INSERT
.
Relacionado:
Por solo un par de discos
Hay varias opciones de cómo. Su idea de pasar una matriz JSON a una función es una de ellas. Si los objetos coinciden con la tabla de destino, puede usar json_populate_recordset()
en un solo INSERT
consulta. O simplemente use el INSERT
(como declaración preparada) sin contenedor de función.
INSERT INTO target_tbl -- it's ok to omit target columns here
SELECT *
FROM json_populate_recordset(null::target_tbl, -- use same table type
json '[{ "id": "1", "val1": "1-val1", "val2": "1-val2" },
{ "id": "2", "val1": "2-val1", "val2": "2-val2" },
{ "id": "3", "val1": "3-val1", "val2": "3-val2" },
{ "id": "4", "val1": "4-val1", "val2": "4-val2" }]');
Para solo un puñado de columnas, también puede pasar una matriz para cada columna y recorrerlas en paralelo. Puede hacer esto con un bucle simple en el índice de la matriz. Desde Postgres 9.4 también existe el conveniente unnest()
con múltiples parámetros para hacerlo todo en una sola consulta:
La mejor solución depende del formato de datos que tenga .