PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Вмъквайте данни в 3 таблици наведнъж с помощта на Postgres

Използвайте 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;

Всеки INSERT зависи от предишния. SELECT вместо VALUES гарантира, че нищо не е вмъкнато в помощни таблици, ако не е върнат ред от предишен INSERT . (След Postgres 9.5+ можете да добавите ON CONFLICT .)
По този начин също е малко по-кратък и по-бърз.

Обикновено е по-удобно да предоставяте пълни редове с данни на едно място :

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<>цигулка тук

Може да се нуждаете от изрично прехвърляне на тип в самостоятелен VALUES израз - за разлика от VALUES израз, прикачен към INSERT където типовете данни се извличат от целевата таблица. Вижте:

  • Прехвърляне на NULL тип при актуализиране на няколко реда

Ако няколко реда могат да идват с идентичен (firstname, lastname) , може да се наложи да сгънете дубликати за първия INSERT :

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

Можете да използвате (временна) таблица като източник на данни вместо CTE data .

Вероятно би имало смисъл да се комбинира това с УНИКАЛНО ограничение за (firstname, lastname) в таблицата и ON CONFLICT клауза в заявката.

Свързано:

  • Как да използвам RETURNING с ON CONFLICT в PostgreSQL?
  • Изберете или INSERT във функция предразположени ли са условия на състезание?


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Деактивирайте проверките на външни ключове на PostgreSQL за миграции

  2. Балансиране на натоварването на PostgreSQL с помощта на HAProxy &Keepalived

  3. Създайте уникално ограничение с нулеви колони

  4. Индекс на долните букви на Flask-SQLAlchemy - функция за пропускане, не се поддържа от отражението на SQLAlchemy

  5. Каква е причината за грешката Повече не се разпознава... при стартиране на Postgresql 11 на машина с Windows?