sql >> Database >  >> RDS >> PostgreSQL

INSERT rijen in meerdere tabellen in een enkele query, selecteren uit een betrokken tabel

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.



  1. De naam van een kolom in SQL Server wijzigen (T-SQL)

  2. Query verwijderen en vernieuwen in ListView in Android (sqlite)

  3. MySQL relationele databases gebruiken op Debian 5 (Lenny)

  4. Is er een manier om power bi-rapporten en -dashboards in de vb.net- of C#-desktoptoepassing in te sluiten met de SQL Server 2008-database?