数据迁移旧数据库到新数据库 - 触发器?输出条款?什么?

时间:2013-02-13 03:53:37

标签: sql-server

我想将旧数据库中父表和子表的数据迁移到新数据库中的类似表中。旧的和新的模式是不同的。

在旧DB中,父条目具有(ID,...),子条目各有(ID,pid,...),其中pid是相应父行的ID。

问题是,如何在目标数据库中连接它们?我被卡住了。我曾经想过要做的就是创建一个表格,将每个元素的oldID映射到newID;但是,我无法弄清楚如何使用触发器,输出子句或我看过的任何其他内容。

还有其他我想迁移的表,因此oldID到newID映射表会很方便。除非有更好的解决方案。

进一步解释...旧数据库中存在需要在新数据库中保留的外键关系。但是当一行被复制到新的DB时,它会得到一个新的PK。子表中的行具有父行的旧PK作为FK。为了将旧数据库中的子行复制到新数据库中,我必须使用父项的旧PK从旧数据库中选择它们,但是将它们插入到具有父项新PK的新数据库中。这是我无法弄清楚如何处理SQL的部分。

谢谢, 埃里克

3 个答案:

答案 0 :(得分:1)

我们不能用旧DB中的SELECT为新数据库写一个INSERT查询吗?

这样的事情应该有效:

INSERT INTO NewDB.schema.TableName (newCol1, newCol2, ... ,newColN)
SELECT oldCol1, oldCol2, ... , oldColN 
FROM OldDB.schema.TableName

我还认为高端数据比较工具(如ApexSQL Data DiffSQL Data Compare)提供某种高级表映射,允许您自动执行此操作。我真的认为你不需要这些工具,但它们可能会有用。

答案 1 :(得分:0)

好的,我有一个解决方案;但是,似乎编码。无论如何,在以下循环运行之后,fidToGroupId表可以将旧的DB ID映射到新的DB ID。现在,其FK曾经指向旧系列ID的家庭成员现在可以通过JOIN映射到新的组ID并插入新数据库

我希望有一种更优雅(也不那么繁琐!)的解决方案,而不仅仅是研磨这样的行。

use phdb 

declare @GroupId int
declare @UserId int
declare @ClientId char( 11 )

select @ClientId = min( ID ) from mcndb.dbo.tClient where IsPerson=0
while @ClientId is not null
begin
    -- Old.Family becomes New.Group
    insert into Groups (GroupName, GroupKind)
        select (fname + ' ' + lname) as GroupName, 'Family' 
            from mcndb.dbo.tClient where ID = @ClientId
    set @GroupId = SCOPE_IDENTITY()

    -- Map fid to GroupId for later use
    insert into mcndb.dbo.fidToGroupId (fid, GroupId)
    values (@ClientId, @GroupId)

    -- Create a user for parent of the family group 
    insert into Users (FirstName, LastName, IsFemale, DoB, ProviderUserKey)
        select fname, lname, 0, '1977-07-07', '00000000-0000-0000-0000-000000000000'
            from mcndb.dbo.tClient where ID = @ClientId 
    set @UserId = SCOPE_IDENTITY()

    -- Connect the parent into the group
    insert into UsersInGroups (Group_ID, [User_ID], [Role])
        values (@GroupId, @UserId, 'PayingParent')

    -- Next row
    select @ClientId = min( id ) from mcndb.dbo.tClient 
        where ID > @ClientId and IsPerson = 0
end

答案 2 :(得分:0)

这是另一种方法:

只需将IDMap列添加到目标数据库表,然后根据联接将相关表插入IDMap

E.g。对于表格

CREATE TABLE db1.dbo.Parent
(
  Id int identity,
  description varchar(max),
  PRIMARY KEY(Id)
)

CREATE TABLE db1.dbo.Child
(
  Id int identity,
  ParentId int NOT NULL,
  SomeChar char(1),
  PRIMARY KEY(Id),
  FOREIGN KEY(ParentId) REFERENCES db1.dbo.Parent(Id)
)

CREATE TABLE db2.dbo.Parent
(
  Id int identity,
  description varchar(max),
  PRIMARY KEY(Id)
)

CREATE TABLE db2.dbo.Child
(
  Id int identity,
  ParentId int NOT NULL,
  SomeChar char(1),
  PRIMARY KEY(Id),
  FOREIGN KEY(ParentId) REFERENCES db2.dbo.Parent(Id)
)

您的导入脚本可能是:

ALTER TABLE db2.dbo.Parent ADD IDMap INT
--might consider adding an index for performance, might help, might hurt.
GO

INSERT INTO db2.dbo.Parent (description, IDMap)
SELECT description, Id FROM db1.dbo.Parent

INSERT INTO db2.dbo.Child (ParentId, SomeChar)
SELECT db2.dbo.Parent.Id, db1.dbo.Child.SomeChar
FROM db1.dbo.Child
INNER JOIN db2.dbo.Parent ON db2.dbo.Parent.IDMap = db1.dbo.Child.ParentId

这里有一个SQL Fiddle演示了上述内容(严格来说,由于sql小提琴的限制而不是严格意义上的跨数据库,但是应该给你一个想法。)

然后,您可以删除IDMap列,或者如果您希望将其留作后代,请保留该列。