Pour des milliers d'enregistrements
1. Créez une table temporaire de lignes d'entrée, composée de vos valeurs $1
, $2
, $3
. Le moyen le plus rapide de télécharger est COPY
- ou le \copy
méta-commande de psql
si les données ne sont pas sur la même machine. Supposons ce tableau :
CREATE TEMP TABLE tmp(id int PRIMARY KEY, val1 text, val2 text);
J'ai ajouté une contrainte PK, qui est totalement facultative, mais elle garantit que nous avons affaire à des valeurs int uniques non nulles. Si vous pouvez vous porter garant des données d'entrée, vous n'avez pas besoin de la contrainte.
2. Enchaînez vos commandes avec des CTE modificateurs de données. Comme nous l'avons déterminé dans votre question précédente , il n'y a pas de conditions de course à prendre en compte dans cette opération particulière.
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;
Les étapes 1 et 2 doivent être exécutées dans la même session (pas nécessairement la même transaction), puisque la portée des tables temporaires est liée à la même session.
Remarque, la UPDATE
ne dépend que du 1er INSERT
, succès du 2ème INSERT
est garanti, puisqu'il n'y a pas de ON CONFLICT DO NOTHING
et toute l'opération serait annulée s'il y avait un conflit dans le 2ème INSERT
.
Connexe :
Pour seulement quelques enregistrements
Il existe différentes options comment. Votre idée de passer un tableau JSON à une fonction en fait partie. Si les objets correspondent à la table cible, vous pouvez utiliser json_populate_recordset()
en un seul INSERT
requête. Ou utilisez simplement le INSERT
(en tant qu'instruction préparée) sans wrapper de fonction.
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" }]');
Pour seulement quelques colonnes, vous pouvez également passer un tableau pour chaque colonne et les parcourir en parallèle. Vous pouvez le faire avec une simple boucle sur l'index du tableau. Depuis Postgres 9.4, il existe également le pratique unnest()
avec plusieurs paramètres pour tout faire en une seule requête :
La meilleure solution dépend du format de données que vous avez .