Окончателна версия
... след малко повече информация от ОП. Помислете за тази демонстрация:
-- 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 като всеки друг - който може да включва таблицата, в която вмъквате. Редовете първо се четат и след това се вмъкват.