表格之间的重复数据保持参考ID

时间:2015-08-25 16:48:50

标签: sql database postgresql postgresql-9.1

我问你的意见,知道这是否可行,因为我是菜鸟,也许我正试图以完全错误的方式做到这一点。我搜索了很多但没有发现任何东西,也许没有使用正确的搜索条件 我正在使用Postgresql 9.1。我简化了情况以理解方法

我有3张桌子:

  • 表A(主人)
  • 表B(链接到表A)
  • 表C(链接到表B)

(参见架构)

表A

    id_A | data_A
    -----+--------
     A01 | dataA01
     A02 | dataA02

表B

    id_B | ref_id_A | data_B
    -----+----------+--------
     B01 |    A01   | dataB01
     B02 |    A01   | dataB02
     B03 |    A02   | dataB03
     B04 |    A02   | dataB04
     B05 |    A02   | dataB05
     B06 |    A02   | dataB06

表C

    id_C | ref_id_B | data_C
    -----+----------+--------
     C01 |    B01   | dataC01
     C02 |    B01   | dataC02
     C03 |    B02   | dataC03
     C04 |    B02   | dataC04

我要做的是复制链接到表A的所有数据,并使用新ID保存表B和C中存储的所有数据和参考。它应该像复制和粘贴一样工作,以便在处理新的

时维护旧版本

重复A01 - > A03

表A

    id_A | data_A
    -----+--------
     A01 | dataA01
     A02 | dataA02
     A03 | dataA01

表B

    id_B | ref_id_A | data_B
    -----+----------+--------
     B01 |    A01   | dataB01
     B02 |    A01   | dataB02
     B03 |    A02   | dataB03
     B04 |    A02   | dataB04
     B05 |    A02   | dataB05
     B06 |    A02   | dataB06
     B07 |    A03   | dataB01
     B08 |    A03   | dataB02

表C

    id_C | ref_id_B | data_C
    -----+----------+--------
     C01 |    B01   | dataC01
     C02 |    B01   | dataC02
     C03 |    B02   | dataC03
     C04 |    B02   | dataC04
     C05 |    B07   | dataC01
     C06 |    B07   | dataC02
     C07 |    B08   | dataC03
     C08 |    B08   | dataC04  

我写了这个查询来复制A01,它在表B中保存了完美的数据,但是我无法复制表C中的数据

WITH new_id_A as 
(insert into table_A (id_A, data_A) (select id_A, data_A from table_A where id_A='A01') returning id_A) 
 insert into table_B (ref_id_A, data_B) select (select id_A from new_id_A) as ref_id_A, data_B from table_B where ref_id_A='A01';

我尝试了不同的方法,但没有结果 我可以使用代码轻松完成任务,但我更愿意在单个事务中在数据库内完成它 谢谢你的关注

1 个答案:

答案 0 :(得分:0)

我认为你应该在临时表中为新行暂存ID,以简化:

WITH new_id_A as 
(insert into table_A (id_A, data_A) (select id_A, data_A from table_A where id_A='A01') returning id_A) 
SELECT 'A01' AS old_id, id_A AS new_id
INSERT INTO TEMP table_A_copy;

insert into table_B (ref_id_A, data_B) 
select cp.new_id, b.data_B
from 
 table_A_copy cp INNER JOIN
 table_B b ON b.ref_id_A = cp.old_id;

insert into table_C (ref_id_B, data_B) 
select b_new.id_B, c.data_C 
from 
 table_A_copy cp INNER JOIN
 table_b b_old on b_old.ref_id_a = cp.old_id inner join 
 table_b b_new on b_new.ref_id_a = cp.new_id inner join 
 table_C c ON c.ref_id_B = b_old.id_B;

Fabio更新:

drop table if exists table_a_copy; 
create temp table table_a_copy ("old_id" integer, "new_id" integer); 

with new_id_a as 
(insert into table_a (data_a) 
  (select data_a from table_a where id_a='1') returning id_a) 
 insert into table_a_copy select '1'::integer as old_id, 
  (select * from new_id_a) as new_id; 

-- Insert to table B
insert into table_b (ref_id_a, data_b) 
select cp.new_id, b.data_b 
from 
  table_a_copy cp inner join 
  table_b b on b.ref_id_a = cp.old_id;

-- Insert to table C
insert into table_c (ref_id_B, data_C) 
select b_new.id_b, c.data_c 
from 
  table_a_copy cp inner join 
  table_b b_old on b_old.ref_id_a = cp.old_id inner join 
  table_b b_new on b_new.ref_id_a = cp.new_id inner join 
  table_c c on c.ref_id_b = b_old.id_b;