general
daré cuatro soluciones, empezando por la más simple. Con cada solución explicaré las situaciones en las que sería aplicable.
Cada una de estas soluciones de bases de datos asume que A y B tienen las siguientes tablas:
create table Terms
(
ID int identity(1,1),
Text nvarchar(MAX)
)
create table Relationships
(
ParentID int,
ChildID int
)
solución al 1
Ésta es la solución más sencilla. Se debe utilizar si:
- Palabras con texto idéntico se pueden combinar entre sí
A continuación se fusionarán todos los términos y las relaciones de A 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
Básicamente primera copia los términos, luego copie las relaciones mapeando la identificación anterior a la nueva identificación basada en el texto.
Nota: En su pregunta indica que los términos son disjuntos entre las dos bases de datos de entrada. En ese caso, se puede omitir la cláusula where
en el primer insert into
.
Solución 2
Ésta es la solución más simple, al lado. Se debe utilizar si:
- Palabras con el mismo texto deben mantenerse separados, y
- Usted puede agregar una columna a la tabla de destino
Primero se debe agregar una columna int a su mesa Términos llamado "oldid", a continuación, utilizar el siguiente para combinar todos los términos y las relaciones de a 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
Solución 3
Esta solución usa iteración.Se debe utilizar si:
- Palabras con el mismo texto deben mantenerse separados, y
- Usted no puede modificar la tabla de destino, y
- De cualquier (a) su columna de ID es una columna de identidad (en Oracle, esto significa que tiene un disparador que utiliza una secuencia), o (b) desea un método general que funcionará con cualquier tecnología de base de datos
a continuación se fusionarán todos los términos y relat ionships de A en 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
Solución 4
Esta solución es Oracle-específico, se requiere conocer la secuencia utilizada para generar valores de ID, y es menos eficiente que algunas de las otras soluciones . Debe utilizarse si:
- Palabras con el mismo texto deben mantenerse separados, y
- Usted no puede modificar la tabla de destino, y
- tiene acceso a la secuencia que genera su columna de identificación, y
- estás bien utilizando un techinique que no va a puerto a una tecnología de base de datos de Oracle no
a continuación se fusionarán todos los términos y las relaciones de a 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
realmente una respuesta, pero han considerado el uso de un script Perl o Python para manejar el movimiento? – Pace
Me temo que SQL a las estructuras de árbol es realmente como una clavija cuadrada a un agujero redondo. Solo se puede hacer usando cantidades excesivas de fuerza bruta. –
No es una respuesta a su pregunta, pero ¿hay alguna razón específica para tener sus relaciones padre/hijo en una tabla separada? Si cada término puede tener solo un padre, entonces la tabla de términos podría tener una columna principal. Cuando necesite encontrar niños, puede usar una declaración 'select-from-connect by-start with'. Esto también haría que los nodos raíz sean más obvios, ya que su columna Parent sería nula. – Aaron