PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Wstawiaj dane w 3 tabelach jednocześnie za pomocą Postgres

Użyj modyfikacji danych CTE :

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;

Każda INSERT zależy od poprzedniego. SELECT zamiast VALUES upewnia się, że nic nie jest wstawiane do tabel pomocniczych, jeśli żaden wiersz nie jest zwracany z poprzedniego INSERT . (Od Postgres 9.5+ możesz dodać ON CONFLICT .)
Dzięki temu jest też nieco krótsze i szybsze.

Zazwyczaj wygodniej jest umieścić pełne wiersze danych w jednym miejscu :

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<>graj tutaj

Możesz potrzebować jawnego rzutowania typu w samodzielnym VALUES wyrażenie - w przeciwieństwie do VALUES wyrażenie dołączone do INSERT gdzie typy danych pochodzą z tabeli docelowej. Zobacz:

  • Rzutowanie typu NULL podczas aktualizowania wielu wierszy

Jeśli wiele wierszy może zawierać identyczny (firstname, lastname) , może być konieczne złożenie duplikatów dla pierwszego INSERT :

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

Możesz użyć (tymczasowej) tabeli jako źródła danych zamiast CTE data .

Prawdopodobnie byłoby sensowne połączenie tego z ograniczeniem UNIQUE na (firstname, lastname) w tabeli i ON CONFLICT klauzula w zapytaniu.

Powiązane:

  • Jak używać RETURNING z ON CONFLICT w PostgreSQL?
  • Czy SELECT lub INSERT w funkcji podatnej na wyścigi?


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak mogę wstawić obiekt JSON do Postgresa za pomocą przygotowanego Javy?

  2. PHP i Postgres:łapanie błędów?

  3. BŁĄD:nie można załadować biblioteki „/opt/PostgreSQL/9.0/lib/postgresql/plperl.so”:libperl.so:

  4. Obliczanie sumy skumulowanej w PostgreSQL

  5. jak mogę utworzyć nowy plik XML z istniejącej bazy danych w bazie danych PostgreSQL za pomocą java?