【发布时间】:2016-01-14 23:09:16
【问题描述】:
我想知道在将表拆分为多对多关系时如何最好地迁移我的数据。我做了一个简化的例子,我也会发布一些我想出的解决方案。 我正在使用 Postgresql 数据库。
迁移前
桌人
ID Name Pet PetName
1 Follett Cat Garfield
2 Rowling Hamster Furry
3 Martin Cat Tom
4 Cage Cat Tom
迁移后
桌人
ID Name
1 Follett
2 Rowling
3 Martin
4 Cage
餐桌宠物
ID Pet PetName
6 Cat Garfield
7 Hamster Furry
8 Cat Tom
9 Cat Tom
桌人宠物
FK_Person FK_Pet
1 6
2 7
3 8
4 9
注意事项:
- 我将专门复制 Pet Table 中的条目(因为在我的情况下 - 由于其他相关数据 - 其中一个可能仍可供客户编辑,而另一个可能不能)。
- 没有唯一标识“宠物”记录的列。
- 对我来说,3-8 和 4-9 是在 PersonPet 表中链接还是在 3-9 和 4-8 中链接并不重要。
- 此外,我省略了处理表架构更改的所有代码,因为在我的理解中,这与这个问题无关。
我的解决方案
- 在创建 Pet Table 时临时添加一列,其中包含用于创建此条目的 Person Table 的 ID。
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;
- 避免临时修改 Pet 表
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;
问题
- 两种解决方案都正确吗? (我已经测试了第二种解决方案,结果似乎是正确的,但我可能错过了一些极端情况)
- 这两种解决方案的优缺点是什么?
- 是否有更简单的方法来执行相同的数据迁移? (出于我的好奇心,我也会对稍微修改我的约束的答案感兴趣(例如 Pet 表中没有重复的条目),但请指出哪些 :))。
【问题讨论】:
标签: sql postgresql many-to-many database-migration