tar*_*aki 12 sql postgresql many-to-many database-migration
我想知道在将表拆分成多对多关系时如何最好地迁移我的数据.我已经做了一个简化的例子,我还会发布一些我想出的解决方案.我正在使用Postgresql数据库.
迁移之前
表人
ID Name Pet PetName
1 Follett Cat Garfield
2 Rowling Hamster Furry
3 Martin Cat Tom
4 Cage Cat Tom
Run Code Online (Sandbox Code Playgroud)
迁移后
表人
ID Name
1 Follett
2 Rowling
3 Martin
4 Cage
Run Code Online (Sandbox Code Playgroud)
表宠物
ID Pet PetName
6 Cat Garfield
7 Hamster Furry
8 Cat Tom
9 Cat Tom
Run Code Online (Sandbox Code Playgroud)
表PersonPet
FK_Person FK_Pet
1 6
2 7
3 8
4 9
Run Code Online (Sandbox Code Playgroud)
笔记:
我的解决方案
ALTER TABLE Pet ADD COLUMN IdPerson INTEGER;
INSERT INTO Pet (Pet, PetName, IdPerson)
SELECT Pet, PetName, ID
FROM Person;
INSERT INTO PersonPet (FK_Person, FK_Pet)
SELECT ID, IdPerson
FROM Pet;
ALTER TABLE Pet DROP Column IdPerson;
Run Code Online (Sandbox Code Playgroud)
INSERT INTO Pet (Pet, PetName)
SELECT Pet, PetName
FROM Person;
WITH
CTE_Person
AS
(SELECT
Id, Pet, PetName
,ROW_NUMBER() OVER (PARTITION BY Pet, PetName ORDER BY Id) AS row_number
FROM Person
)
,CTE_Pet
AS
(SELECT
Id, Pet, PetName
,ROW_NUMBER() OVER (PARTITION BY Pet, PetName ORDER BY Id) AS row_number
FROM Pet
)
,CTE_Joined
AS
(SELECT
CTE_Person.Id AS Person_Id,
CTE_Pet.Id AS Pet_Id
FROM
CTE_Person
INNER JOIN CTE_Pet ON
CTE_Person.Pet = CTE_Pet.Pet
CTE_Person.PetName = CTE_Pet.PetName
AND CTE_Person.row_number = CTE_Pet.row_number
)
INSERT INTO PersonPet (FK_Person, FK_Pet)
SELECT Person_Id, Pet_Id from CTE_Joined;
Run Code Online (Sandbox Code Playgroud)
问题
实现您所描述的效果的另一种解决方案(在我看来是最简单的一种;没有任何CTE-s或其他列):
create table Pet as
select
Id,
Pet,
PetName
from
Person;
create table PersonPet as
select
Id as FK_Person,
Id as FK_Pet
from
Person;
create sequence PetSeq;
update PersonPet set FK_Pet=nextval('PetSeq'::regclass);
update Pet p set Id=FK_Pet from PersonPet pp where p.Id=pp.FK_Person;
alter table Pet alter column Id set default nextval('PetSeq'::regclass);
alter table Pet add constraint PK_Pet primary key (Id);
alter table PersonPet add constraint FK_Pet foreign key (FK_Pet) references Pet(Id);
Run Code Online (Sandbox Code Playgroud)
除非我们使用序列生成一个id,否则我们只是使用现有的person id作为宠物的临时id.
编辑
也可以使用我已经完成模式更改的方法:
insert into Pet(Id, Pet, PetName)
select
Id,
Pet,
PetName
from
Person;
insert into PersonPet(FK_Person, FK_Pet)
select
Id,
Id
from
Person;
select setval('PetSeq'::regclass, (select max(Id) from Person));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1266 次 |
| 最近记录: |