For tusindvis af registreringer
1. Opret en midlertidig tabel med inputrækker, der består af dine værdier $1
, $2
, $3
. Den hurtigste måde at uploade er COPY
- eller \copy
meta-kommando af psql
hvis dataene ikke er på samme maskine. Lad os antage denne tabel:
CREATE TEMP TABLE tmp(id int PRIMARY KEY, val1 text, val2 text);
Jeg tilføjede en PK-begrænsning, som er helt valgfri, men den sikrer, at vi har at gøre med unikke ikke-null int-værdier. Hvis du kan stå inde for inputdata, behøver du ikke begrænsningen.
2. Kæd dine kommandoer sammen med datamodificerende CTE'er. Som vi har fastslået under dit tidligere spørgsmål , der er ingen løbsforhold at tage sig af i denne særlige operation.
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;
Trin 1. og 2. skal køre i samme session (ikke nødvendigvis den samme transaktion), da omfanget af midlertidige tabeller er bundet til den samme session.
Bemærk, INSERT
, succes med 2. INSERT
er garanteret, da der ikke er nogen ON CONFLICT GØR INGENTING
og hele operationen ville blive rullet tilbage, hvis der er nogen konflikt i den 2. INSERT
.
Relateret:
For blot et par poster
Der er forskellige muligheder hvordan. Din idé om at videregive et JSON-array til en funktion er en af dem. Hvis objekter matcher måltabellen, kan du bruge json_populate_recordset()
i en enkelt INSERT
forespørgsel. Eller brug bare INSERT
(som udarbejdet erklæring) uden funktionsindpakning.
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" }]');
For blot en håndfuld kolonner kan du også sende et array for hver kolonne og gå gennem dem parallelt. Du kan gøre dette med en simpel løkke på array-indekset. Siden Postgres 9.4 er der også den praktiske unnest()
med flere parametre for at gøre det hele i en enkelt forespørgsel:
Den bedste løsning afhænger af det dataformat, du har .