sql >> Database >  >> RDS >> PostgreSQL

Postgres bulk INSERT-functie met JSON-argumenten

Voor duizenden records

1. Maak een tijdelijke tabel met invoerrijen, bestaande uit uw waarden $1 , $2 , $3 . De snelste manier om te uploaden is COPY - of de \copy meta-commando van psql als de gegevens niet op dezelfde machine staan. Laten we aannemen dat deze tabel:

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

Ik heb een PK-beperking toegevoegd, die volledig optioneel is, maar het zorgt ervoor dat we te maken hebben met unieke niet-null int-waarden. Als u kunt instaan ​​voor invoergegevens, heeft u de beperking niet nodig.

2. Koppel uw opdrachten aan CTE's die gegevens wijzigen. Zoals we hebben vastgesteld onder uw vorige vraag , er zijn geen race-omstandigheden om voor te zorgen in deze specifieke operatie.

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;

Stap 1. en 2. moeten worden uitgevoerd in de dezelfde sessie (niet noodzakelijk dezelfde transactie), aangezien het bereik van tijdelijke tabellen aan dezelfde sessie is gebonden.

Let op, de UPDATE hangt alleen af ​​van de 1e INSERT , succes van de 2e INSERT is gegarandeerd, aangezien er geen ON CONFLICT DO NOTHING en de hele operatie zou worden teruggedraaid als er een conflict is in de 2e INSERT .

Gerelateerd:

Voor slechts een paar records

Er zijn verschillende mogelijkheden hoe. Jouw idee om een ​​JSON-array door te geven aan een functie is daar een van. Als objecten overeenkomen met de doeltabel, kunt u json_populate_recordset() in een enkele INSERT vraag. Of gebruik gewoon de INSERT (als voorbereide instructie) zonder functie-wrapper.

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

Voor slechts een handvol kolommen kunt u ook een array doorgeven voor elke kolom en deze parallel doorlopen. U kunt dit doen met een eenvoudige lus op de array-index. Sinds Postgres 9.4 is er ook de handige unnest() met meerdere parameters om het allemaal in een enkele query te doen:

De beste oplossing hangt af van het gegevensformaat dat u heeft .




  1. Gegevenstype van veld ophalen in select-instructie in ORACLE

  2. Airflow mysql naar gcp Dag fout

  3. SQL INSERT INTO-instructie

  4. XAMPP WERKT NIET! - OS X Yosemite