sql >> Database >  >> RDS >> PostgreSQL

Voeg gegevens in 3 tabellen tegelijk in met Postgres

Gebruik gegevensmodificerende CTE's :

WITH ins1 AS (
   INSERT INTO sample(firstname, lastname)
   VALUES ('fai55', 'shaggk')
-- ON     CONFLICT DO NOTHING         -- optional addition in Postgres 9.5+
   RETURNING id AS sample_id
   )
, ins2 AS (
   INSERT INTO sample1 (sample_id, adddetails)
   SELECT sample_id, 'ss' FROM ins1
   RETURNING user_id
   )
INSERT INTO sample2 (user_id, value)
SELECT user_id, 'ss2' FROM ins2;

Elke INSERT hangt af van de vorige. SELECT in plaats van VALUES zorgt ervoor dat er niets wordt ingevoegd in secundaire tabellen als er geen rij wordt geretourneerd uit een eerdere INSERT . (Sinds Postgres 9.5+ kunt u een ON CONFLICT toevoegen .)
Het is op deze manier ook een beetje korter en sneller.

Meestal is het handiger om volledige gegevensrijen op één plaats aan te bieden :

WITH data(firstname, lastname, adddetails, value) AS (
   VALUES                              -- provide data here
      ('fai55', 'shaggk', 'ss', 'ss2') -- see below
    , ('fai56', 'XXaggk', 'xx', 'xx2') -- works for multiple input rows
       --  more?                      
   )
, ins1 AS (
   INSERT INTO sample (firstname, lastname)
   SELECT firstname, lastname          -- DISTINCT? see below
   FROM   data
   -- ON     CONFLICT DO NOTHING       -- UNIQUE constraint? see below
   RETURNING firstname, lastname, id AS sample_id
   )
, ins2 AS (
   INSERT INTO sample1 (sample_id, adddetails)
   SELECT ins1.sample_id, d.adddetails
   FROM   data d
   JOIN   ins1 USING (firstname, lastname)
   RETURNING sample_id, user_id
   )
INSERT INTO sample2 (user_id, value)
SELECT ins2.user_id, d.value
FROM   data d
JOIN   ins1 USING (firstname, lastname)
JOIN   ins2 USING (sample_id);

db<>viool hier

Mogelijk hebt u expliciete typecasts nodig in een stand-alone VALUES uitdrukking - in tegenstelling tot een VALUES uitdrukking gekoppeld aan een INSERT waarbij gegevenstypen zijn afgeleid van de doeltabel. Zie:

  • NULL-type casten bij het bijwerken van meerdere rijen

Als meerdere rijen identiek kunnen zijn (firstname, lastname) , moet u mogelijk duplicaten vouwen voor de eerste INSERT :

...
INSERT INTO sample (firstname, lastname)
SELECT DISTINCT firstname, lastname FROM data
...

Je zou een (tijdelijke) tabel als databron kunnen gebruiken in plaats van de CTE data .

Het zou waarschijnlijk logisch zijn om dit te combineren met een UNIEKE beperking op (firstname, lastname) in de tabel en een ON CONFLICT clausule in de zoekopdracht.

Gerelateerd:

  • Hoe RETURNING gebruiken met ON CONFLICT in PostgreSQL?
  • Is SELECT of INSERT in een functie die vatbaar is voor race-omstandigheden?


  1. Installeer SQL Server 2016

  2. Een OBJECT_NAME() ophalen uit een andere database in SQL Server

  3. Tabelafdruk past niet op paginaformaat

  4. Controleer of de tabel bestaat in SQL Server