sql >> Databasteknik >  >> RDS >> PostgreSQL

Postgres bulk INSERT-funktion med JSON-argument

För tusentals poster

1. Skapa en tillfällig tabell med inmatningsrader, som består av dina värden $1 , $2 , $3 . Det snabbaste sättet att ladda upp är COPY - eller \copy metakommando för psql om data inte finns på samma maskin. Låt oss anta att den här tabellen:

CREATE TEMP TABLE tmp(id int PRIMARY KEY, val1 text, val2 text);

Jag lade till en PK-begränsning, som är helt valfri, men den ser till att vi har att göra med unika int-värden som inte är null. Om du kan garantera indata behöver du inte begränsningen.

2. Kedja dina kommandon med datamodifierande CTE:er. Som vi har fastställt under din föregående fråga , det finns inga tävlingsförhållanden att ta hand om i just denna 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;

Steg 1. och 2. måste köras i samma session (inte nödvändigtvis samma transaktion), eftersom omfattningen av tillfälliga tabeller är bunden till samma session.

Notera, UPDATE beror bara på den första INSERT , framgång för den andra INSERT är garanterad, eftersom det inte finns någon ON CONFLICT DO NOTHING och hela operationen skulle återställas om det finns någon konflikt i den andra INSERT .

Relaterat:

För bara ett par poster

Det finns olika alternativ hur. Din idé att skicka en JSON-array till en funktion är en av dem. Om objekt matchar måltabellen kan du använda json_populate_recordset() i en enda INSERT fråga. Eller använd bara INSERT (som förberett uttalande) utan funktionsomslag.

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" }]');

För bara en handfull kolumner kan du också skicka en array för varje kolumn och gå igenom dem parallellt. Du kan göra detta med en enkel slinga på arrayindexet. Sedan Postgres 9.4 finns även den praktiska unnest() med flera parametrar för att göra allt i en enda fråga:

Den bästa lösningen beror på vilket dataformat du har .




  1. Hur man flyttar sedan radera fält i MySQL

  2. Kan jag automatisera att infoga lösenordet för PEM-filen för SSL-certifikat i MySQL?

  3. hur kan jag koda en sträng i HMAC-SHA256 med pl/sql?

  4. MySQL korrumperar efter varje omstart av servern