Overview
I will give four solutions, starting with the simplest. With each solution I will explain the situations in which it would be applicable.
Each of these solutions assumes that databases A and B have the following tables:
create table Terms
(
ID int identity(1,1),
Text nvarchar(MAX)
)
create table Relationships
(
ParentID int,
ChildID int
)
Solution 1
This is the simplest solution. It should be used if:
- Terms with identical text may be merged together
The following will merge all terms and relationships from A into 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
Basically you first copy the terms, then copy the relationships mapping the old id to the new id based on the text.
Note: In your question you state the terms are disjoint between the two input databases. In that case the where
clause in the first insert into
may be omitted.
Solution 2
This is the next-simplest solution. It should be used if:
- Terms with the same Text must be kept distinct, and
- You can add a column to the destination table
First add an int column to your Terms table called "OldID", then use the following to merge all terms and relationships from A to 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
Solution 3
This solution uses iteration. It should be used if:
- Terms with the same Text must be kept distinct, and
- You cannot modify the destination table, and
- Either (a) your ID column is an identity column (in Oracle, this means it has a trigger that uses a sequence), or (b) you want a general method that will work with any database technology
The following will merge all terms and relationships from A into 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
Solution 4
This solution is Oracle-specific, requires you to know the sequence used to generate ID values, and is less efficient than some of the other solutions. It should be used if:
- Terms with the same Text must be kept distinct, and
- You cannot modify the destination table, and
- You have access to the sequence that generates your ID column, and
- You are ok using a techinique that will not port to a non-Oracle database technology
The following will merge all terms and relationships from A into 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