数据库重构为多对多关系

时间:2014-10-22 10:49:52

标签: postgresql postgresql-9.3

在某些数据库重构中,我需要引入未来的多对多关系,我偶然发现了我认为必须有可能的事情。

给出原始表:

CREATE TABLE a (
  id serial NOT NULL,
  field1 varchar, 
  field2 varchar, 
  field3 varchar 
);

和新创建的表:

CREATE TABLE b (
  id serial NOT NULL,
  field1 varchar, 
  field2 varchar 
);

我想将field1和field2的内容​​从a移动到b。为了适应多对多关系,还可以使用关联表:

CREATE TABLE a_b (
  aid serial NOT NULL,
  bid serial NOT NULL
);

这里原始的a-id和新创建的b-id应该结束。

因此,如果我开始使用像这样的a-table

| 33 | John | Jane | Juli |
| 34 | Fred | Carl | Josh |

我希望看到它最终出现在b-table中:

| 1 | John | Jane
| 2 | Fred | Carl

和关联a_b

| 33 | 1 |
| 34 | 2 | 

然后原始表将删除field1和field2,因此我将看起来像这样

| 1 | Juli |
| 2 | Josh |

我立即想到使用with-queries,但却找不到让它工作的方法。 这显然不起作用:

WITH new AS (
    INSERT INTO b (field1, field2) 
    SELECT field1, field2 FROM a
    RETURNING id
  )
INSERT INTO a_b (???, bid) SELECT * FROM new;

但说明了问题。我发现没有办法插入b,同时保持与相应的a-id的关系。我认为一定是可能的。

有什么想法?

Søren

PS我为了简洁而忽略了外键之类的东西。

1 个答案:

答案 0 :(得分:0)

简洁不是你的朋友。当缺少某些东西时,我们无法判断您是否简短或是否犯了大错。

CREATE TABLE a (
  id serial primary key,
  field1 varchar, 
  field2 varchar, 
  field3 varchar 
);

CREATE TABLE b (
  id serial primary key,
  field1 varchar, 
  field2 varchar 
);

"协会"表存储外键;你的应该存储来自" a"以及来自" b"的身份证号码。所以它应该像这样声明。

CREATE TABLE a_b (
  aid integer NOT NULL,
  bid integer NOT NULL,
  primary key (aid, bid),
  foreign key (aid) references a (id),
  foreign key (bid) references b (id)
);

让我们在" a"中添加几行。仔细观察下面第二和第三行中的重复," Fred"和"卡尔"。

insert into a (field1, field2, field3) values
('John', 'Jane', 'Juli'),
('Fred', 'Carl', 'Josh'),
('Fred', 'Carl', 'Abby'),
('Art', 'Carl', 'Abby');

要填充" b",请插入来自。

的不同(唯一)组合
insert into b (field1, field2)
select distinct field1, field2 
from a;

select * from b;
id  field1  field2
--
1   John    Jane
2   Art     Carl
3   Fred    Carl

"协会"表格需要来自" a"的ID号码,以及来自" b"的相应ID号码。你需要加入" a"和" b"。

insert into a_b
select a.id aid, b.id bid
from a
inner join b on a.field1 = b.field1 and a.field2 = b.field2

现在您可以加入这三个表来查看完整的关联。基于像这样的查询创建视图通常很有用。

select b.id bid, b.field1, b.field2, a.id aid, a.field3
from a_b
inner join a on a.id = a_b.aid
inner join b on b.id = a_b.bid
order by a.id;
bid  field1  field2 aid  field3
--
1    John    Jane   1    Juli
3    Fred    Carl   2    Josh
3    Fred    Carl   3    Abby
2    Art     Carl   4    Abby

如果您对数据是正确的感到满意,可以删除列" field1"和" field2"来自a。