2016-07-21 18 views
0

Ich versuche, eine Reihe von Daten in einer Eins-zu-viele-Beziehung zu kopieren, um eine neue Gruppe derselben Daten in einer neuen Beziehung zu erstellen, die aber nicht verwandt ist . Lässt sie Gruppen und Gegenstände nennen. Gruppen haben eine 1 * -Beziehung zu Gegenständen - eine Gruppe hat viele Gegenstände.So kopieren Sie Zeilen in eine neue 1: 0-Beziehung

Ich habe versucht, ein CTE dafür zu erstellen, aber ich kann die Elemente nicht einfügen (in y), da die neu eingefügten Gruppen noch keine Elemente mit ihnen verknüpft haben. Ich denke, ich muss auf alt zugreifen können. und neu. wie bei einem Trigger, aber ich kann nicht herausfinden, wie das geht.

Ich denke, ich könnte dies lösen, indem ich eine vorherige Eltern-ID in die templateitem-Tabelle oder vielleicht eine temporäre Tabelle mit den erforderlichen Daten einfüge, um mich daran zu beteiligen, aber ich frage mich, ob es möglich ist, dies zu lösen Weg?

SQL Fiddle auf mich Keeps brechen, also habe ich den Code auch hier setzen:

DROP TABLE IF EXISTS meta.templateitem; 
DROP TABLE IF EXISTS meta.templategroup; 

CREATE TABLE meta.templategroup (
templategroup_id serial PRIMARY KEY, 
groupname text, 
roworder int 
); 

CREATE TABLE meta.templateitem (
templateitem_id serial PRIMARY KEY, 
itemname text, 
templategroup_id INTEGER NOT NULL REFERENCES meta.templategroup(templategroup_id) 
); 

INSERT INTO meta.templategroup (groupname, roworder) values ('Group1', 1), ('Group2', 2); 
INSERT INTO meta.templateitem (itemname, templategroup_id) values ('Item1A',1), ('Item1B',1), ('Item2A',2); 


WITH 
x AS (
    INSERT INTO meta.templategroup (groupname, roworder) 
     SELECT distinct groupname || '_v1' FROM meta.templategroup where templategroup_id in (1,2) 
     RETURNING groupname, templategroup_id, roworder 
    ), 
y AS (
    Insert INTO meta.templateitem (itemname, templategroup_id) 
     Select itemname, x.templategroup_id 
     From meta.templateitem i 
     INNER JOIN x on x.templategroup_id = i.templategroup_id 
     RETURNING * 
    ) 
SELECT * FROM y; 

Antwort

1

eine Hilfsspalte verwenden templategroup.old_id:

ALTER TABLE meta.templategroup ADD old_id int; 

WITH x AS (
    INSERT INTO meta.templategroup (groupname, roworder, old_id) 
     SELECT DISTINCT groupname || '_v1', roworder, templategroup_id 
     FROM meta.templategroup 
     WHERE templategroup_id IN (1,2) 
     RETURNING templategroup_id, old_id 
    ), 
y AS (
    INSERT INTO meta.templateitem (itemname, templategroup_id) 
     SELECT itemname, x.templategroup_id 
     FROM meta.templateitem i 
     INNER JOIN x ON x.old_id = i.templategroup_id 
     RETURNING * 
    ) 
SELECT * FROM y; 

templateitem_id | itemname | templategroup_id 
-----------------+----------+------------------ 
       4 | Item1A |    3 
       5 | Item1B |    3 
       6 | Item2A |    4 
(3 rows)  

Es ist unmöglich, dass in einem einzigen zu tun einfache SQL-Abfrage ohne eine zusätzliche Spalte. Sie müssen die alte ids irgendwo speichern.

Bevor:

select * 
from meta.templategroup 
join meta.templateitem using (templategroup_id); 

templategroup_id | groupname | roworder | templateitem_id | itemname 
------------------+-----------+----------+-----------------+---------- 
       1 | Group1 |  1 |    1 | Item1A 
       1 | Group1 |  1 |    2 | Item1B 
       2 | Group2 |  2 |    3 | Item2A 
(3 rows) 

Einsatz: Als Alternative können Sie plpgsql und anonymen Codeblock verwenden

do $$ 
declare 
    grp record; 
begin 
    for grp in 
     select distinct groupname || '_v1' groupname, roworder, templategroup_id 
     from meta.templategroup 
     where templategroup_id in (1,2) 
    loop 
     with insert_group as (
      insert into meta.templategroup (groupname, roworder) 
      values (grp.groupname, grp.roworder) 
      returning templategroup_id 
     ) 
     insert into meta.templateitem (itemname, templategroup_id) 
      select itemname || '_v1', g.templategroup_id 
      from meta.templateitem i 
      join insert_group g on grp.templategroup_id = i.templategroup_id; 
    end loop; 
end $$; 

Nach:

select * 
from meta.templategroup 
join meta.templateitem using (templategroup_id); 

templategroup_id | groupname | roworder | templateitem_id | itemname 
------------------+-----------+----------+-----------------+----------- 
       1 | Group1 |  1 |    1 | Item1A 
       1 | Group1 |  1 |    2 | Item1B 
       2 | Group2 |  2 |    3 | Item2A 
       3 | Group1_v1 |  1 |    4 | Item1A_v1 
       3 | Group1_v1 |  1 |    5 | Item1B_v1 
       4 | Group2_v1 |  2 |    6 | Item2A_v1 
(6 rows)  
+0

Ich hatte gehofft, dies zu tun, ohne die Einführung eine neue Spalte, da ich keine Kontrolle über die DB selbst habe. Ist es möglich ohne, da dieser Vorschlag bedeutet, dass ich eine weitere Spalte zur Vorlagengruppentabelle hinzufügen muss. –

+0

Siehe die bearbeitete Antwort. – klin

Verwandte Themen