Обзор
Я дам четыре решения, начиная с самого простого. С каждым решением я объясню ситуации, в которых оно будет применимо.
В каждом из этих решений предполагается, что базы данных A и B имеют следующие таблицы:
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
Обычно вы сначала копируете термины, а затем копируете отношения, отображающие старый идентификатор в новый идентификатор на основе текста.
Примечание. В своем вопросе вы утверждаете, что термины не связаны между двумя входными базами данных. В этом случае предложение where
в первом insert into
может быть опущено.
Решение 2
Это следующее простейшее решение. Следует использовать, если:
- Термины с тем же текстом должны быть различны, а
- Вы можете добавить столбец в таблицу назначения
Сначала добавьте столбец int в таблицу «Термины» с именем «OldID», а затем используйте следующее для объединения всех терминов и отношений от А до В:
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) ваш столбец идентификатора является столбцом идентификаторов (в 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, требует, чтобы вы знали последовательность, используемую для генерации значений идентификаторов, и менее эффективно, чем некоторые другие решения. Следует использовать, если:
- Термины с одним и тем же текстом должны быть различны, а
- Вы не можете изменить таблицу назначения, а
- У вас есть доступ к последовательности, которая генерирует столбец идентификатора, и
- Вы в порядке, используя технику, которая не будет портировать на не-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, 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