试图将两个表从一个DB迁移到另一个DB

时间:2009-06-15 13:05:31

标签: sql sql-server migration

我正在尝试将一些数据从OLD数据库中的两个表迁移到一个新数据库。

问题是我希望在新数据库中为第一个导入的表生成新的主键。这很简单。

但是旧数据库中的第二个表对第一个表具有外键依赖性。因此,当我想从第二个表迁移旧数据时,外键不再匹配。

是否有任何技巧/最佳实践可帮助我迁移数据?

严重注意:我无法更改新表的当前架构,这些架构没有任何“旧ID”列。

让我们使用下表模式: -

Old Table1              New Table1
ParentId INT PK         ParentId INT PK
Name VARCHAR(50)        Name VARCHAR(50)

Old Table 2             New Table 2
ChildId INT PK          ChildId INT PK
ParentId INT FK         ParentId INT FK     
Foo VARCHAR(50)         Foo VARCHAR(50)

所以表模式是相同的。

思想?

编辑:

对于那些要问的人,RDBMS是Sql Server 2008.我没有指定软件,因为我希望我会得到一些通用T-Sql的不可知答案:P

7 个答案:

答案 0 :(得分:4)

我认为你需要分两步完成。

您需要导入旧表并保留旧ID(并生成新表)。然后,一旦他们进入新数据库并且他们同时拥有新旧ID,您可以使用旧ID来关联新ID,然后删除旧ID。

你可以通过导入临时(即它们将被丢弃)表格,然后插入永久表格,省去旧的ID。

或者将directy导入到新表中(修改了架构以保存旧ID),然后在不再需要时删除旧ID。

修改

好的,由于这里的评论和其他答案,我对你正在寻找的东西更清楚一点。我把它搞砸了,我认为它会做你想要的。

基本上没有游标,它逐行遍历父表,并插入新的partent行,以及该父行的所有子行,保持新id同步。 我试了一下它应该可以工作,它不需要对表的独占访问,并且应该比光标更快的订单。

declare @oldId as int
declare @newId as int

select @oldId = Min(ParentId) from OldTable1 

while not @oldId is null
begin
    Insert Into NewTable1 (Name)
    Select Name from OldTable1 where ParentId = @oldId

    Select @newId = SCOPE_IDENTITY()

    Insert Into NewTable2 (ParentId, Foo)
    Select @newId, Foo From OldTable2 Where ParentId = @oldId

    select @oldId = Min(ParentId) from OldTable1 where ParentId > @oldId

end

希望这有帮助,

答案 1 :(得分:1)

好吧,我想你必须确定其他标准来创建像oldPK =>这样的地图。 newPK(例如:Name字段相等?

然后您可以确定与旧PK匹配的新PK并相应地调整ParentID

你也可以做一个小技巧:在原始Table1中添加一个新列,它存储复制记录的新PK值。然后,您可以轻松地复制Table2的值,将它们指向新列的值而不是旧的PK。

编辑:我正在尝试提供一些示例代码,说明我的小技巧。我没有改变原来的数据库结构,但我现在正在使用临时表。

好的,您可以尝试以下方式:

1)创建保存旧表值的临时表,并获得新的PK:

CREATE TABLE #tempTable1
(
    newPKField INT,
    oldPKField INT,
    Name VARCHAR(50)
)

2)将旧表中的所有值插入到计算新PK的临时表中,复制旧PK:

INSERT INTO #tempTable1
SELECT
   newPKValueHere AS newPKField,
   ParentID as oldPKField,
   Name
FROM
   Table1

3)将值复制到新表

INSERT INTO NewTable1
SELECT
   newPKField as ParentId,
   Name
FROM
   #tempTable1

4)将值从Table2复制到NewT​​able2

INSERT INTO NewTable2
SELECT
   ChildID,
   t.newPKField AS ParentId,
   Foo
FROM 
   Table2
   INNER JOIN #tempTable1 t ON t.ParentId = parentId

这应该做。请注意,这只是伪T-SQL代码 - 我没有在真实数据库上测试过这个!但是,它应该接近你所需要的。

答案 2 :(得分:0)

您可以更改旧表的架构吗?如果是这样,您可以在旧表上放置一个“新id”列,并将其用作参考。

您可能必须在新表上逐行插入,然后检索scope_identity,将其存储在旧table1中。但是对于table2,您可以加入旧的table1并获取new_id。

答案 3 :(得分:0)

首先 - 你甚至不能拥有一些你可以在以后放弃的临时架构吗?!这会让生活更轻松。假设你不能:

如果你很幸运(如果你能保证不会同时发生其他插入)那么当你将Table1的数据插入到新表中时,你可能会依赖插入的顺序来作弊

然后,您可以创建一个在行数上连接2个表的视图,以便您可以将密钥相互关联。这样你就可以更接近于为新Table2识别'ParentId'。

答案 4 :(得分:0)

我不确定您的问题是什么数据库软件正在使用,但如果临时表是一个选项,请创建一个临时表,其中包含table1的原始主键和table1的新主键。然后使用table2的副本创建另一个临时表,使用您之前创建的“旧密钥,新密钥”表更新副本,然后使用“insert into select from”(或任何适用于您的数据库的命令)来复制修改临时表到其永久位置。

答案 5 :(得分:0)

去年夏天,我有很好的机会深入挖掘迁移脚本。我正在使用Oracle的PL / SQL来完成任务。但你没有提到你使用的是什么技术?你在将数据迁移到什么? SQL Server?甲骨文? MySQL的?

方法是从table1中插入一行返回生成的新主键(可能是由SEQUENCE [在Oracle中]),然后从table2中插入相关记录,将其外键值更改为第一个INSERT返回的值。除非您可以指定将数据迁移到哪个DBMS,否则无法帮助您。

答案 6 :(得分:0)

以下Pseudo-ish代码应该适合您

CREATE TABLE newtable1
  ParentId INT PK
  OldId   INT
  Name     VARCHAR(50)

CREATE TABLE newtable2
  ChildId    INT pk
  ParentId   INT FK
  OldParent  INT
  Foo        VARCHAR(50)   

  INSERT INTO newtable1(OldId, Name)
  SELECT  ParentId, Name FROM oldtable1

  INSERT INTO newtable2(OldParent, Foo)
  SELECT ParentId, Foo FROM oldtable2

UPDATE newtable2 SET ParentId = (
  SELECT n.ParentId 
  FROM   newtable1 AS n
  WHERE  n.OldId = newtable2.oldParent
)

ALTER TABLE newtable1 DROP OldId
ALTER TABLE newtable2 DROP OldParent