Wersja ostateczna
... po więcej informacji z OP. Rozważ tę prezentację:
-- 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)
);
Wstaw wartości - bar
po pierwsze.
Byłoby to bardzo pomocne jeśli podałeś dane testowe w swoim pytaniu w ten sposób!
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);
Ustaw sekwencje na bieżące wartości lub otrzymamy zduplikowane naruszenia klawiszy:
SELECT setval('foo_id_seq', 3);
SELECT setval('bar_id_seq', 102);
Czeki:
-- SELECT nextval('foo_id_seq')
-- SELECT nextval('bar_id_seq')
-- SELECT * from bar;
-- SELECT * from foo;
Zapytanie:
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);
Powinno to zrobić to, co opisuje Twoja ostatnia aktualizacja.
Zapytanie zakłada, że z
jest UNIQUE
. Jeśli z
nie jest wyjątkowy, staje się bardziej złożony. Zapoznaj się z zapytaniem 2 w tej powiązanej odpowiedzi, aby uzyskać gotowe rozwiązanie za pomocą funkcji okna row_number()
w tym przypadku.
Rozważ także zastąpienie relacji 1:1 między foo
i bar
z jednym wspólnym stołem.
Modyfikowanie danych CTE
Druga odpowiedź po więcej informacji.
Jeśli chcesz dodać wiersze do foo
i bar
w pojedynczym zapytaniu możesz użyć CTE modyfikującego dane 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;
Rysuję wartości z foo
, wstaw je w bar
, zwróć je razem z automatycznie wygenerowanym bar_id
i wstaw to w foo
. Możesz również użyć dowolnych innych danych.
Oto działające demo do zabawy na sqlfiddle.
Podstawy
Oryginalna odpowiedź z podstawowymi informacjami przed wyjaśnieniami.
Podstawowa forma to:
INSERT INTO foo (...)
SELECT ... FROM foo WHERE ...
Nie potrzeba nawiasów. To samo możesz zrobić z dowolną tabelą
INSERT INTO foo (...)
SELECT ... FROM bar WHERE ...
I możesz dołączyć do tabeli, do której wstawiasz w 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
To po prostu SELECT jak każda inna — może zawierać tabelę, do której wstawiasz. Wiersze są najpierw odczytywane, a następnie wstawiane.