Endgültige Version
... nach einigen weiteren Informationen von OP. Sehen Sie sich diese Demo an:
-- 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)
);
Werte einfügen - bar
zuerst.
Es wäre sehr hilfreich wenn Sie in Ihrer Frage solche Testdaten angegeben haben!
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);
Sequenzen auf aktuelle Werte setzen oder wir erhalten doppelte Schlüsselverletzungen:
SELECT setval('foo_id_seq', 3);
SELECT setval('bar_id_seq', 102);
Kontrollen:
-- SELECT nextval('foo_id_seq')
-- SELECT nextval('bar_id_seq')
-- SELECT * from bar;
-- SELECT * from foo;
Abfrage:
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);
Dies sollte das tun, was Ihr letztes Update beschreibt.
Die Abfrage geht davon aus, dass z
ist UNIQUE
. Wenn z
ist nicht einzigartig, es wird komplexer. Siehe Abfrage 2 in dieser verwandten Antwort für eine fertige Lösung mit der Fensterfunktion row_number()
in diesem Fall.
Erwägen Sie auch, die 1:1-Beziehung zu ersetzen zwischen foo
und bar
mit einer einzigen vereinten Tabelle.
Daten ändern CTE
Zweite Antwort nach mehr Infos.
Wenn Sie Zeilen zu foo
hinzufügen möchten und bar
in einer einzelnen Abfrage können Sie seit PostgreSQL 9.1 einen Datenänderungs-CTE verwenden :
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;
Ich ziehe Werte aus foo
, fügen Sie sie in bar
ein , lassen Sie sich diese zusammen mit einer automatisch generierten bar_id
zurückgeben und füge das ein in foo
. Sie können auch beliebige andere Daten verwenden.
Hier ist eine funktionierende Demo zum Spielen auf sqlfiddle.
Grundlagen
Ursprüngliche Antwort mit grundlegenden Informationen vor Erläuterungen.
Die Grundform lautet:
INSERT INTO foo (...)
SELECT ... FROM foo WHERE ...
Keine Klammern erforderlich. Sie können dasselbe mit jeder Tabelle tun
INSERT INTO foo (...)
SELECT ... FROM bar WHERE ...
Und Sie können sich mit der Tabelle verbinden, in die Sie in SELECT:
einfügenINSERT INTO foo (...)
SELECT f.col1, f.col2, .. , b.bar_id
FROM foo f
JOIN bar b USING (foo_id); -- present in foo and bar
Es ist nur ein SELECT wie jedes andere - das kann die Tabelle enthalten, in die Sie einfügen. Die Zeilen werden zuerst gelesen und dann eingefügt.