2008-09-12 33 views
5

Editar: Permítanme reformular esto por completo, porque no estoy seguro de que exista una forma XML como la que describí originalmente.Copia de datos relacionales de la base de datos a la base de datos

Aún otra edición: Esto tiene que ser un proceso repetible, y tiene que poder configurarse de manera que pueda llamarse en el código C#.

En la base de datos A, tengo un conjunto de tablas relacionadas por PK y FK. Una tabla principal, con tablas de hijos y nietos, digamos.

Quiero copiar un conjunto de filas de la base de datos A a la base de datos B, que tiene tablas y campos con el mismo nombre. Para cada tabla, quiero insertar en la misma tabla en la base de datos B. Pero no puedo restringirme a usar las mismas claves principales. La rutina de copia debe crear nuevos PK para cada fila en la base de datos B, y debe propagarlos a las filas secundarias. En otras palabras, mantengo las mismas relaciones entre los datos, pero no las mismas PK y FK exactas.

¿Cómo solucionaría esto? Estoy abierto a sugerencias. SSIS no está completamente descartado, pero no me parece que vaya a hacer esto exactamente. También estoy abierto a una solución en LINQ, o usando DataSets con tipo, o usando algo de XML, o casi cualquier cosa que funcione en SQL Server 2005 y/o C# (.NET 3.5). La mejor solución no requeriría SSIS, y no requeriría escribir mucho código. Pero concederé que esta "mejor" solución puede no existir.

(Yo no lo hacen esta tarea yo mismo, ni las limitaciones;. Ésta es la forma en que fue dado a mí)

+0

Supongo que se trata de una operación única y la replicación no es una opción. – Galwegian

+0

No, debe ser repetible; a largo plazo especificaremos qué elementos copiar (por PK en la base de datos original, por ejemplo). Como no podemos garantizar el pedido, los PK no deberían ser exactamente iguales en la nueva base de datos. La replicación no está fuera de discusión si es una buena solución. –

+0

¿Mantiene (o puede conservar) la ID de PK original en otro campo en la base de datos de destino? –

Respuesta

0

creo más probable es que lo que voy a utilizar conjuntos de datos se escribe. No será una solución generalizada; tendremos que regenerarlos si alguna de las tablas cambia. Pero basado en lo que me han dicho, eso no es un problema; no se espera que las tablas cambien mucho.

Los conjuntos de datos harán que sea razonablemente fácil recorrer los datos jerárquicamente y actualizar los PK de la base de datos después de la inserción.

0

volcar el enfoque de XML y utilizar el asistente de importación/SSIS.

+0

Preferiríamos alejarnos de DTS/SSIS si es posible. Estamos buscando algo que (empaquetado adecuadamente en el código) sea fácil de ejecutar para el usuario final seleccionando un conjunto de elementos para importar desde una lista. –

1

Primero, déjenme decir que SSIS es su mejor apuesta. Pero, para responder a la pregunta que hizo ...

No creo que pueda salirse con la suya creando nuevas identificaciones, aunque podría, pero tendría que tomar las identificaciones originales para usarlas en las búsquedas .

Lo mejor que puede obtener es una declaración de inserción para la tabla. Este es un ejemplo del código para hacer SELECT s para obtener los datos desde el XML de ejemplo:

declare @xml xml 
set @xml='<People Key="1" FirstName="Bob" LastName="Smith"> 
    <PeopleAddresses PeopleKey="1" AddressesKey="1"> 
    <Addresses Key="1" Street="123 Main" City="St Louis" State="MO" ZIP="12345" /> 
    </PeopleAddresses> 
</People> 
<People Key="2" FirstName="Harry" LastName="Jones"> 
    <PeopleAddresses PeopleKey="2" AddressesKey="2"> 
    <Addresses Key="2" Street="555 E 5th St" City="Chicago" State="IL" ZIP="23456" /> 
    </PeopleAddresses> 
</People> 
<People Key="3" FirstName="Sally" LastName="Smith"> 
    <PeopleAddresses PeopleKey="3" AddressesKey="1"> 
    <Addresses Key="1" Street="123 Main" City="St Louis" State="MO" ZIP="12345" /> 
    </PeopleAddresses> 
</People> 
<People Key="4" FirstName="Sara" LastName="Jones"> 
    <PeopleAddresses PeopleKey="4" AddressesKey="2"> 
    <Addresses Key="2" Street="555 E 5th St" City="Chicago" State="IL" ZIP="23456" /> 
    </PeopleAddresses> 
</People> 
' 

select t.b.value('./@Key', 'int') PeopleKey, 
    t.b.value('./@FirstName', 'nvarchar(50)') FirstName, 
    t.b.value('./@LastName', 'nvarchar(50)') LastName 
from @xml.nodes('//People') t(b) 

select t.b.value('../../@Key', 'int') PeopleKey, 
    t.b.value('./@Street', 'nvarchar(50)') Street, 
    t.b.value('./@City', 'nvarchar(50)') City, 
    t.b.value('./@State', 'char(2)') [State], 
    t.b.value('./@Zip', 'char(5)') Zip 
from 
@xml.nodes('//Addresses') t(b) 

Lo que esto hace es tomar los nodos del XML y analizar los datos. Para obtener la identificación relacional de personas, utilizamos ../../ para subir la cadena.

0

Con mucho, la forma más fácil es la comparación de datos SQL de Red Gate. Puede configurarlo para hacer exactamente lo que describió en un minuto o dos.

0

Me encanta la comparación de SQL de Red Gate y la comparación de datos también pero no cumplirá con sus requisitos para las claves principales cambiantes hasta donde yo sé.

Si las consultas de bases de datos cruzadas/servidores vinculados son una opción, puede hacer esto con un procedimiento almacenado que copia los registros del padre/hijo en DB A en tablas temporales en DB B y luego agrega una columna para la nueva clave primaria la tabla secundaria temporal que actualizaría después de insertar los encabezados.

Mi pregunta es si los registros no tienen la misma clave principal ¿cómo se puede saber si se trata de un nuevo registro? ¿Hay alguna otra clave candidata? Si se trata de tablas nuevas, ¿por qué no pueden tener la misma clave principal?

0

he creado lo mismo con un conjunto de procedimientos almacenados.

La base de datos B tendrá sus propias claves principales, pero almacenará las claves principales de la base de datos A, para fines de depuración. ¡Significa que puedo tener más de una base de datos A!

Los datos se copian a través de un servidor vinculado. No tan rápido; SSIS es más rápido. Pero SSIS no es para principiantes, y no es fácil codificar algo que funciona con el cambio de tablas fuente.

Y es fácil llamar a un procedimiento almacenado desde C#.

0

que había guión en un procedimiento almacenado, el uso de inserciones a hacer el trabajo duro. Su código tomará las PK de la Tabla A (presumiblemente a través de @@ Scope_Identity) - ¿Supongo que la PK de la Tabla A es un campo de Identidad?

Puede usar tablas temporales, cursores o quizás prefiera usar el CLR, ya que podría prestarse a este tipo de operación.

Me sorprendería encontrar una herramienta que podría hacerlo fuera de la plataforma, ya sea a) claves pre-determinado, o b) campos de identidad (claramente las Tablas B & C no tenerlos).

0

¿Está limpiando las tablas de destino cada vez y luego comenzar de nuevo? Eso marcará una gran diferencia en la solución que necesita implementar. Si está haciendo una reimportación completa cada vez, entonces podría hacer algo como lo siguiente:

Cree una tabla temporal o una variable de tabla para registrar las claves primarias antiguas y nuevas para la tabla padre.

Inserte los datos de la tabla padre en el destino y use la cláusula OUTPUT para capturar los nuevos ID e insertarlos con los ID anteriores en la tabla temporal. NOTA: El uso de la cláusula de salida es eficiente y le permite hacer la inserción en bloque sin pasar por cada registro que se va a insertar.

Inserte los datos de la tabla secundaria. Únase a la tabla temporal para recuperar la nueva clave externa requerida.

El proceso anterior se puede hacer utilizando T-SQL Script, código C# o SSIS. Mi preferencia sería para SSIS.

+0

No, estoy agregando datos existentes en las tablas. –

0

Si está agregando cada vez puede necesitar mantener una tabla permanente para rastrear la relación entre las claves primarias de la base de datos de origen y las claves primarias de la base de datos de destino (al menos para la tabla padre). Si necesitaba mantener este tipo de datos fuera de la base de datos de destino, podría obtener SSIS para almacenarlos/recuperarlos de algún tipo de base de datos de registro o incluso de un archivo plano.

Probablemente pueda evitar el escenario anterior si hay una combinación de campos en la tabla principal que se pueden usar para identificar de manera única ese registro y, por lo tanto, "encontrar" la clave primaria para ese registro en la base de datos de destino.

0

Cuando se trata de tareas similares que simplemente crea un conjunto de procedimientos almacenados para hacer el trabajo.

Como la tarea que ha especificado es bastante personalizada, no es probable que encuentre la solución "lista para usar".

sólo para dar algunas sugerencias:

  • Si las bases de datos están en diferentes servidores utilizan servidores vinculados para que pueda acceder a ambas tablas de origen y de destino, simplemente a través de TSQL

En el procedimiento almacenado:

  • Identifique los elementos principales que deben copiarse: ha dicho que las claves principales son diferentes, por lo que debe usar restricciones únicas en su lugar (debe poder definirlos si las tablas están normalizadas)
  • Identifique los elementos secundarios que deben copiarse en función de los padres identificados, para verificar si algunos de ellos ya están en el destino. Utilice nuevamente el enfoque de restricciones únicas.
  • Identificar los elementos nieto (misma lógica que con padres e hijos)
  • Copiar datos sobre empezando por el nivel más bajo (nietos, hijos, padres)

no hay necesidad de cursores, etc, simplemente almacenar los resultados inmediatos en la tabla temporal (o variable de tabla si se trabaja dentro de un procedimiento almacenado)

Ese enfoque funcionó bastante bien para mí.

Por supuesto, puede agregar un parámetro al procedimiento almacenado principal para que pueda copiar todos los registros nuevos o solo los que especifique.

Avísame si te sirve de algo.

Cuestiones relacionadas