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

INSERT редове в множество таблици в една заявка, избирайки от включена таблица

Окончателна версия

... след малко повече информация от ОП. Помислете за тази демонстрация:

-- DROP TABLE foo; DROP TABLE bar;

CREATE TEMP TABLE bar (
 id serial PRIMARY KEY  -- using a serial column!
,z  integer NOT NULL
);

CREATE TEMP TABLE foo (
 id     serial PRIMARY KEY  -- using a serial column!
,x      integer NOT NULL
,y      integer NOT NULL
,bar_id integer UNIQUE NOT NULL REFERENCES bar(id)
);

Вмъкване на стойности - bar първо.
Би било много полезно ако сте предоставили тестови данни във вашия въпрос по този начин!

INSERT INTO bar (id,z) VALUES
 (100, 7)
,(101,16)
,(102,21);

INSERT INTO foo (id, x, y, bar_id) VALUES
 (1, 3,4,100)
,(2, 9,6,101)
,(3,18,0,102);

Задайте последователности на текущи стойности или ще получим дублиращи се нарушения на ключовете:

SELECT setval('foo_id_seq', 3);
SELECT setval('bar_id_seq', 102);

Проверки:

-- SELECT nextval('foo_id_seq')
-- SELECT nextval('bar_id_seq')
-- SELECT * from bar;
-- SELECT * from foo;

Запитване:

WITH a AS (
    SELECT f.x, f.y, bar_id, b.z
    FROM   foo f
    JOIN   bar b ON b.id = f.bar_id
    WHERE  x > 3
    ),b AS (
    INSERT INTO bar (z)
    SELECT z
    FROM   a
    RETURNING z, id AS bar_id
    )
INSERT INTO foo (x, y, bar_id)
SELECT a.x, a.y, b.bar_id
FROM   a
JOIN   b USING (z);

Това трябва да направи това, което описва последната ви актуализация.

Заявката предполага, че z е UNIQUE . Ако z не е уникално, става по-сложно. Вижте Заявка 2 в този свързан отговор за готово решение с помощта на функцията на прозореца row_number() в този случай.

Също така помислете за замяна на отношението 1:1 между foo и bar с единна обединена маса.

CTE за модифициране на данни

Втори отговор след повече информация.

Ако искате да добавите редове към foo и bar в една заявка можете да използвате CTE за промяна на данни от PostgreSQL 9.1 :

WITH x AS (
    INSERT INTO bar (col1, col2)
    SELECT f.col1, f.col2
    FROM   foo f
    WHERE  f.id BETWEEN 12 AND 23 -- some filter
    RETURNING col1, col2, bar_id  -- assuming bar_id is a serial column
    )
INSERT INTO foo (col1, col2, bar_id)
SELECT col1, col2, bar_id
FROM   x;

Извличам стойности от foo , вмъкнете ги в bar , да ги върнете заедно с автоматично генериран bar_id и вмъкнете това в foo . Можете да използвате и всякакви други данни.

Ето работеща демонстрация, с която да играете на sqlfiddle.

Основни положения

Оригинален отговор с основна информация преди разяснения.
Основната форма е:

INSERT INTO foo (...)
SELECT ... FROM foo WHERE ...

Не са необходими скоби. Можете да направите същото с всяка таблица

INSERT INTO foo (...)
SELECT ... FROM bar WHERE ...

И можете да се присъедините към таблицата, която вмъквате в SELECT:

INSERT INTO foo (...)
SELECT f.col1, f.col2, .. , b.bar_id
FROM   foo f
JOIN   bar b USING (foo_id);  -- present in foo and bar

Това е просто SELECT като всеки друг - който може да включва таблицата, в която вмъквате. Редовете първо се четат и след това се вмъкват.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Търсене на пълен текст в Postgres или CouchDB?

  2. PostgreSQL конвертира колони в редове? Транспониране?

  3. Най-добрите решения за висока достъпност за клъстериране на PG за PostgreSQL

  4. Функции за дата и час на PostgreSQL

  5. Потребителят на Postgres не съществува?