Konečná verze
... po dalších informacích z OP. Zvažte toto demo:
-- 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)
);
Vložit hodnoty - bar
za prvé.
Bylo by to velmi užitečné pokud jste ve své otázce takto poskytli testovací data!
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);
Nastavte sekvence na aktuální hodnoty, jinak dojde k duplicitnímu porušení klíče:
SELECT setval('foo_id_seq', 3);
SELECT setval('bar_id_seq', 102);
Kontroly:
-- SELECT nextval('foo_id_seq')
-- SELECT nextval('bar_id_seq')
-- SELECT * from bar;
-- SELECT * from foo;
Dotaz:
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);
To by mělo odpovídat tomu, co popisuje vaše poslední aktualizace.
Dotaz předpokládá, že z
je UNIQUE
. Pokud z
není unikátní, je složitější. Připravené řešení pomocí funkce okna row_number()
naleznete v dotazu 2 v této související odpovědi. v tomto případě.
Zvažte také nahrazení vztahu 1:1 mezi foo
a bar
s jednou sjednocenou tabulkou.
Úpravy dat CTE
Druhá odpověď po dalších informacích.
Pokud chcete přidat řádky do foo
a bar
v jediném dotazu můžete použít data upravující CTE od 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;
Hodnoty čerpám z foo
, vložte je do bar
, nechte je vrátit spolu s automaticky vygenerovaným bar_id
a vložte to do foo
. Můžete použít i jakákoli jiná data.
Zde je funkční demo, se kterým si můžete zahrát na sqlfiddle.
Základy
Původní odpověď se základními informacemi před upřesněním.
Základní tvar je:
INSERT INTO foo (...)
SELECT ... FROM foo WHERE ...
Nejsou potřeba závorky. Totéž můžete udělat s jakoukoli tabulkou
INSERT INTO foo (...)
SELECT ... FROM bar WHERE ...
A můžete se připojit k tabulce, do které vkládáte, v 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
Je to prostě SELECT jako každý jiný - který může zahrnovat tabulku, do které vkládáte. Řádky jsou nejprve přečteny a poté vloženy.