尝试将两个表从一个数据库迁移到另一个数据库时陷入困境

发布于 2024-07-24 16:00:42 字数 671 浏览 4 评论 0原文

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

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

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

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

严重注意:我无法更改新表的当前架构,因为新表没有任何“旧 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

i'm trying to migrate some data from two tables in an OLD database, to a NEW database.

The problem is that I wish to generate new Primary Key's in the new database, for the first table that is getting imported. That's simple.

But the 2nd table in the old database has a foreign key dependency on the first table. So when I want to migrate the old data from the second table, the foreign key's don't match any more.

Are there any tricks/best practices involved to help me migrate the data?

Serious Note: i cannot change the current schema of the new tables, which do not have any 'old id' column.

Lets use the following table schema :-

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)

So the table schema's are identical.

Thoughts?

EDIT:

For those that are asking, RDBMS is Sql Server 2008. I didn't specify the software because i was hoping i would get an agnostic answer with some generic T-Sql :P

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

咋地 2024-07-31 16:00:42

我认为您需要分两步完成此操作。

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

您可以通过导入到临时(即它们将被丢弃)表中,然后插入到永久表中来完成此操作,忽略旧的 id。

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

编辑:

好的,由于此处的评论和其他答案,我对您要查找的内容更加清楚了。 我敲了这个,我想它会做你想要的。

基本上没有游标,它会逐行遍历父表,并插入新的父行以及该父行的所有子行,从而保持新 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

希望这可以帮助,

I think you need to do this in 2 steps.

You need to import the old tables and keep the old ids (and generate new ones). Then once they're in the new database and they have both new and old ids you can use the old Id's to get associate the new ids, then you drop the old ids.

You can do this by importing into temporary (i.e. they will be thrown away) tables, then inserting into the permanent tables, leaving out the old ids.

Or import directy into the new tables (with schema modified to also hold old ids), then drop the old id's when they're no longer necessary.

EDIT:

OK, I'm a bit clearer on what you're looking for thanks to comments here and on other answers. I knocked this up, I think it'll do what you want.

Basically without cursors it steps through the parent table, row by row, and inserts the new partent row, and all the child rows for that parent row, keeping the new id's in sync.
I tried it out and it should work, it doesn't need exclusive access to the tables and should be orders of magniture faster than a cursor.

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

Hope this helps,

北城挽邺 2024-07-31 16:00:42

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

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

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

编辑:我试图提供一些示例代码来说明我的小技巧的含义,我不会更改原始数据库结构,但我现在使用临时表,

好的,您可以尝试以下操作:

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 复制到 NewTable2

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

这应该可以。 请注意,这只是伪 T-SQL 代码 - 我尚未在真正的数据库上对此进行测试! 但是,它应该接近您的需要。

Well, I guess you'll have to determine other criteria to create a map like oldPK => newPK (for example: Name field is equal?

Then you can determine the new PK that matches the old PK and adjust the ParentID accordingly.

You may also do a little trick: Add a new column to the original Table1 which stores the new PK value for a copied record. Then you can easily copy the values of Table2 pointing them to the value of the new column instead of the old PK.

EDIT: I'm trying to provide some sample code of what I meant by my little trick. I'm not altering the original database structure, but I'm using a temporary table now.

OK, you might try to following:

1) Create temporary table that holds the values of the old table, plus, it gets a new PK:

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

2) Insert all the values from your old table into the temporary table calculating a new PK, copying the old PK:

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

3) Copy the values to the new table

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

4) Copy the values from Table2 to NewTable2

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

This should do. Please note that this is only pseudo T-SQL Code - I have not tested this on a real database! However, it should come close to what you need.

青春有你 2024-07-31 16:00:42

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

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

Can you change the schema of the old tables? If so, you could put a "new id" column on the old tables, and use that as the reference.

You might have to do a row by row insert on the new table and then retrieve the scope_identity, store it in the old table1. But for table2, you can then join to the old table1 and grab the new_id.

甜柠檬 2024-07-31 16:00:42

首先 - 你甚至不能拥有一些稍后可以删除的临时模式吗?! 这会让生活变得更轻松。 假设你不能:

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

然后,您可以创建一个按行计数连接两个表的视图,以便您可以将键相互关联。 这样,您就可以更接近识别新 Table2 的“ParentId”。

First of all - can you not even have some temporary schema that you can later drop?! That would make life easier. Assuming you can't:

If you're lucky (and if you can guarantee that no other inserts will be happening at the same time) then when you insert the Table1's data into your new table you could perhaps cheat by relying on the sequential order of the inserts.

You could then create a view that joins the 2 tables on a row-count so that you have a way to correlate the keys to each other. That way you'd be one step closer to being able to identify the 'ParentId' for the new Table2.

岁月静好 2024-07-31 16:00:42

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

I'm not sure from your question what database software you're using, but if temporary tables are an option, create a temporary table containing the original primary key of table1 and the new primary key of table1. Then create another temporary table with a copy of table2, update the copy using the "old key, new key" table you created earlier, then use "insert into select from" (or whatever the appropriate command is for your database) to copy the revised temporary table into its permanent location.

天涯沦落人 2024-07-31 16:00:42

去年夏天,我有一个很好的机会深入研究迁移脚本。 我使用 Oracle 的 PL/SQL 来完成该任务。 但你没有提到你用的是什么技术? 您要将数据迁移到什么地方? SQL 服务器? 甲骨文? MySQL?

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

I had the wonderful opportunity to be dug deep in migration scripts last summer. I was using Oracle's PL/SQL for the task. But you did not mention what technology are you using? What are you migrating the data into? SQL Server? Oracle? MySQL?

The approach is to INSERT a row from table1 RETURING the new primary key generated (probably by a SEQUENCE [in Oracle]) and then INSERT the dependent records from table2, changing their foreign key value to the value returned by the first INSERT. Can't help you any better unless you can specify what DBMS are you migrating data into.

无法言说的痛 2024-07-31 16:00:42

以下伪代码应该适合您

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

The following Pseudo-ish code should work for you

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文