Definitieve versie
... na wat meer info van OP. Overweeg deze 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)
);
Waarden invoegen - bar
eerst.
Het zou erg nuttig zijn als u testgegevens op deze manier in uw vraag heeft opgegeven!
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);
Stel reeksen in op de huidige waarden of we krijgen dubbele sleutelovertredingen:
SELECT setval('foo_id_seq', 3);
SELECT setval('bar_id_seq', 102);
Cheques:
-- SELECT nextval('foo_id_seq')
-- SELECT nextval('bar_id_seq')
-- SELECT * from bar;
-- SELECT * from foo;
Vraag:
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);
Dit zou moeten doen wat uw laatste update beschrijft.
De query gaat ervan uit dat z
is UNIQUE
. Als z
is niet uniek, het wordt complexer. Raadpleeg Query 2 in dit gerelateerde antwoord voor een kant-en-klare oplossing met behulp van de vensterfunctie row_number()
in dit geval.
Overweeg ook om de 1:1 relatie . te vervangen tussen foo
en bar
met een enkele verenigde tafel.
Gegevens die CTE wijzigen
Tweede antwoord na meer info.
Als u rijen wilt toevoegen aan foo
en bar
in een enkele query kunt u een CTE gebruiken voor het wijzigen van gegevens sinds 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;
Ik trek waarden uit foo
, plaats ze in bar
, laat ze terugsturen samen met een automatisch gegenereerde bar_id
en plaats dat in foo
. U kunt ook andere gegevens gebruiken.
Hier is een werkende demo om mee te spelen op sqlfiddle.
Basis
Origineel antwoord met basisinformatie voor verduidelijkingen.
De basisvorm is:
INSERT INTO foo (...)
SELECT ... FROM foo WHERE ...
Geen haakjes nodig. U kunt hetzelfde doen met elke tabel
INSERT INTO foo (...)
SELECT ... FROM bar WHERE ...
En u kunt deelnemen aan de tabel waarin u invoegt in de 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
Het is gewoon een SELECT zoals elke andere - die de tabel kan bevatten waarin u invoegt. De rijen worden eerst gelezen en vervolgens ingevoegd.