SQL copia recursivamente filas de varias tablas siguiendo relaciones PK FK

Me asignaron la tarea de crear un procedimiento almacenado para copiar todos los datos asociados con una identificación determinada en nuestra base de datos. Estos datos abarcan docenas de tablas. cada tabla puede tener docenas de filas coincidentes.

ejemplo:

cuenta de mesa
pk = AccountID

Configuración de cuenta de tabla
FK = AccountID

Usuarios de mesa
PK = ID de usuario
FK = AccountID

Contenido de usuario de tabla
PK = UserContentID
FK = ID de usuario

Quiero crear una copia de todo lo que está asociado con un AccountID (que atravesará casi todas las tablas). La copia tendrá un nuevo AccountID y UserContentID pero tendrá el mismo UserID. los nuevos datos deben estar en su tabla respectiva. :) divertido ¿verdad?

Lo anterior es solo una muestra, pero lo haré para 50 o 60 tablas. He investigado el uso de CTE, pero todavía estoy un poco confuso. ese puede resultar ser el mejor método. MIS habilidades de SQL son ... bueno, he trabajado con él durante aproximadamente 40 horas registradas hasta ahora :)

Cualquier consejo o dirección sobre dónde buscar será muy apreciado. Además, no me opongo a hacer esto a través de C # si eso fuera posible o mejor.

Gracias de antemano por cualquier ayuda de información.

preguntado el 09 de marzo de 12 a las 21:03

en su ejemplo, 1 cuenta puede tener 0-n usuarios, pero 1 usuario solo puede tener 0-1 cuentas => no sería posible tener el mismo ID de usuario para la segunda cuenta (si no desea eliminar la conexión del usuario a la primera cuenta, por supuesto) -

Guau. NO lo haría de esta manera. Los CTE solo se repetirán 100 veces, por lo que podría exceder esto. ¿Por qué no simplemente continuar agregando a una tabla temporal basada en claves externas de tablas en la tabla temporal hasta que no se agreguen filas nuevas? -

@saarp: ¿por qué los CTE solo se repiten 100 veces? esa es una suposición ridícula. -

¿Qué DBMS estás usando? PostgreSQL? ¿Oráculo? DB2? -

@a_horse_with_no_name: No es una suposición, sino un hecho. Ver msdn justo encima de los ejemplos del parámetro MAXRECURSION (predeterminado 100, entre 0 y 32767). -

1 Respuestas

La forma más sencilla de resolver esto es la forma de la fuerza bruta: escriba un proceso muy largo que procese cada tabla individualmente. Esto será propenso a errores y muy difícil de mantener. Pero tendrá la ventaja de no depender de la base de datos o de los metadatos de la base de datos para estar en un estado particularmente consistente.

Si quieres algo que funcione basado en metadatos, las cosas son más interesantes. Tienes tres desafíos allí:

  1. Debe identificar mediante programación todas las tablas relacionadas.
  2. Necesita generar declaraciones de inserción para los 50 o 60.
  3. Debe capturar los identificadores generados para aquellas tablas que están a más de uno o dos pasos de la tabla Cuenta, para que a su vez puedan usarse como claves externas en aún más registros copiados.

He analizado este problema en el pasado y, aunque no puedo ofrecerle un algoritmo hermético, puedo ofrecerle una heurística general. En otras palabras: así es como lo abordaría.

  1. Con una versión posterior de MS Entity Framework (dijo que estaría dispuesto a usar C #), cree un modelo de la tabla Cuenta y todas las tablas relacionadas.
  2. Revisa todo lo que puedas. Si su base de datos es como muchas, algunas de las relaciones que asumen sus aplicaciones, por el motivo que sea, no tendrán una relación de clave externa real configurada en la base de datos. Créelos en su modelo de todos modos.
  3. Escriba una pequeña rutina recursiva en C # que pueda tomar un objeto Cuenta y recorrer todas las tablas relacionadas. Elija un par de instancias de Cuenta y haga que descargue el nombre de la tabla y la información clave en un archivo. Revise que esté completo y sea plausible.
  4. Una vez que esté satisfecho de tener un buen modelo y un buen algoritmo que lo capta todo, es hora de empezar a descifrar el código. Necesita escribir un algoritmo más complicado que pueda leer una cuenta y clonar recursivamente todos los registros que hacen referencia a ella. Probablemente necesitará reflexionar para hacer esto, pero no es tan difícil: todos los metadatos que necesita estarán allí, en algún lugar.
  5. Prueba tu código. Deje suficiente tiempo para la depuración.
  6. Utilice su primer algoritmo, en el paso 3, para comparar los resultados en cuanto a integridad y precisión.

La ventaja del enfoque EF: a medida que cambia la base de datos, también puede cambiar su modelo, y si su código está basado en metadatos, debería poder adaptarse.

La desventaja: si tiene fenómenos tales como campos que son "realmente" iguales pero de diferentes tipos, o relaciones complejas de tres vías que no están modeladas correctamente, o listas CSV incrustadas que necesitaría analizar, esto ganó no funciona. Solo funciona si su base de datos está en buen estado y bien modelada. De lo contrario, deberá recurrir a la fuerza bruta.

Respondido el 07 de Septiembre de 12 a las 23:09

Gracias. Terminé escribiendo todo el camino largo. Es bastante grande alrededor de 1800 líneas pero funciona muy bien. Mantenerlo actualizado será un fastidio. Gracias por sus pensamientos sobre esto. - user1260249

+1 Buen consejo. Terminé usando EF en mi solución, fue mucho más fácil de lo que esperaba originalmente, por lo que definitivamente recomendaría usarlo. Además de eso, es mucho más fácil de mantener e incluso ampliar. - frascaroli

@tfrascaroli ¡Gracias por las felicitaciones! ¡Me alegro de que mi consejo haya sido útil! - Ann L.

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.