我有一个包含2个表的基本数据库模式;一个是简单的ID – >术语的文本列表,另一个有2列,父和子.第一个表中的ID是在db序列插入时生成的,而第二个表包含用于存储层次结构的“结构”的键之间的映射.
我的问题是我有时可能希望将树从一个数据库移动到另一个数据库.如果我有2个DB,每个有10个术语(数据库A的术语!=数据库B的术语,并且没有重叠),我只是将数据从A复制到B然后我会遇到一个明显的问题,即术语将是重新编号,但关系不会.显然,在这个例子中,只需在所有关系键上添加10即可,但有没有人知道这样做的通用算法?
DB是oracle 11g,oracle特定的解决方案很好……
解决方法
概观
我将给出四个解决方案,从最简单的开始.对于每个解决方案,我将解释它适用的情况.
create table Terms ( ID int identity(1,1),Text nvarchar(MAX) ) create table Relationships ( ParentID int,ChildID int )
解决方案1
这是最简单的解决方案.它应该用于:
>具有相同文本的术语可以合并在一起
以下将合并从A到B的所有术语和关系:
insert into A.Terms (Text) select Text from A.Terms where Text not in (select Text from B.Terms) insert into B.Relationships (ParentID,ChildID) select (select ID from B.Terms BTerms inner join A.Terms ATerms on BTerms.Text = ATerms.Text where ATerms.ID = Relationships.ParentID),(select ID from B.Terms BTerms inner join A.Terms ATerms on BTerms.Text = ATerms.Text where ATerms.ID = Relationships.ChildID) from A.Relationships
基本上你首先复制这些术语,然后根据文本复制将旧id映射到新id的关系.
注意:在您的问题中,您说明两个输入数据库之间的术语是不相交的.在这种情况下,可以省略第一个插入中的where子句.
解决方案2
>具有相同文本的术语必须保持不同,并且
>您可以向目标表添加列
首先在您的Terms表中添加一个名为“OldID”的int列,然后使用以下内容合并从A到B的所有术语和关系:
insert into A.Terms (Text,OldID) select Text,ID from A.Terms where Text not in (select Text from B.Terms) insert into B.Relationships (ParentID,ChildID) select (select ID from B.Terms where OldID = ParentID),(select ID from B.Terms where OldID = ChildID) from A.Relationships
解决方案3
该解决方案使用迭代.它应该用于:
>具有相同文本的术语必须保持不同,并且
>您无法修改目标表,和
>(a)你的ID列是一个标识列(在Oracle中,这意味着它有一个使用序列的触发器),或者(b)你想要一个适用于任何数据库技术的通用方法
以下将合并从A到B的所有术语和关系:
declare TermsCursor sys_refcursor; begin -- Create temporary mapping table create table #Temporary (OldID int,NewID int) -- Add terms one at a time,remembering the id mapping open TermsCursor for select * from A.Terms; for term in TermsCursor loop insert into B.Terms (Text) values ( term.Text ) returning ID into NewID; insert into Temporary ( OldID,NewID ) values ( term.ID,NewID ); end loop; -- Transfer the relationships insert into B.Relationships (ParentID,ChildID) select (select ID from B.Terms BTerms inner join Temporary on BTerms.ID = Temporary.NewID where Temporary.OldID = Relationships.ParentID),(select ID from B.Terms BTerms inner join Temporary on BTerms.ID = Temporary.NewID where Temporary.OldID = Relationships.ChildID),from A.Relationships -- Drop the temporary table drop table #Temporary end
解决方案4
此解决方案特定于Oracle,要求您了解用于生成ID值的序列,并且效率低于某些其他解决方案.它应该用于:
>具有相同文本的术语必须保持不同,和
>您可以访问生成ID列的序列,以及
>您可以使用不会移植到非Oracle数据库技术的技术
以下将合并从A到B的所有术语和关系:
-- Create temporary mapping table create table #Temporary (OldID int,NewID int) -- Add terms to temporary mapping table insert into #Tempoarary ( OldID,NewID ) select ID,sequence.nexval from A.Terms -- Transfer the terms insert into B.Terms ( ID,Text ) select NewID,Text from A.Terms inner join Temporary on ID = OldID -- Transfer the relationships insert into B.Relationships (ParentID,from A.Relationships -- Drop the temporary table drop table #Temporary