¿Cómo trato con las restricciones FK al importar datos usando el Asistente de importación / exportación DTS?

16

Estoy tratando de usar el Asistente de importación y exportación de SQL Server para copiar datos de mi base de datos de producción a mi base de datos de desarrollo, pero cuando lo hago falla el error "El estado INSERTAR está en conflicto con la restricción FOREIGN KEY" Tengo más de 40 tablas con lotes de las restricciones FK, ¿hay alguna manera fácil de lidiar con esto sin tener que escribir un script de restricción de caída / agregar restricción?

Editar: Acabo de descubrir que en la edición web de SQL Server, que es lo que estoy ejecutando, DTS no le permitirá guardar paquetes.


fuente

Respuestas:

28

Me dieron esta solución en SQLTeam.com:

Utilizar:

 EXEC sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT all'

Luego importa tus datos

EXEC sp_msforeachtable 'ALTER TABLE ? CHECK CONSTRAINT all'

Usando ese método pude importar todos los datos sin problemas.

Paul White 9
fuente
1
sp_msforeachtable(y sp_MSForEachDb) no está documentado ni soportado. No debe / evite usarlo. ¡Puede saltarse las mesas! Vea esta publicación de @AaronBertrand -> sqlblog.com/blogs/aaron_bertrand/archive/2010/12/29/… y este elemento de conexión - (MS indica que no lo solucionarán) -> connect.microsoft.com/SQLServer / feedback / details / 264677 /…
Kin Shah
Me funcionó perfectamente después de horas de golpearme el cerebro tratando de sortear las restricciones de FK para una exportación de datos.
levininja
Al ejecutar Azure SQL V12, aparece el error "No se pudo encontrar el procedimiento almacenado 'sp_msforeachtable'".
Dai
De todos modos no funciona: /
Douglas Gaskell
Eres el hombre salvavidas
Can Şahin Bakır
5

Produje una copia exacta de una base de datos en mi máquina desde un servidor que no controlaba.

Soy un imbécil , pero esto es lo que hice:

  1. Creé la base de datos a partir de mi script que estaba en control de origen (pista, pista). Si no tiene la secuencia de comandos, siempre puede generarla desde la base de datos existente a través de la Tasksopción.

  2. Si algún dato se insertó automáticamente en YourDB en la creación, ejecute a DELETE FROM YourDB.dbo.tblYourTable.

    • No puede truncar datos cuando existen claves foráneas, por lo que debe usar DELETE.
  3. Ejecute esto en su servidor de destino: USE YourDB; EXEC sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT all';

  4. Haga clic derecho en YourDB en Object Explorer. Haga clic en Tasks->Import Data...

  5. Las primeras pantallas del asistente se explican por sí mismas.

  6. En la Select Source Table and Viewspantalla del asistente, haga clic en la casilla de verificación junto a cada tabla que desee copiar.

  7. Para cada fila (tabla) en esa pantalla, haga clic en ella para que quede resaltada y luego haga clic Edit Mappings.

  8. Para cada fila (tabla), haga clic / verifique Append rows to the destination tabley Enable identity insert.

    • Si hace clic Delete rows in destination table, fallará porque no emite un DELETEcomando, emite un TRUNCATEcomando que aún entra en conflicto con nuestras claves externas porque TRUNCATEno se rige por el NOCHECK CONSTRAINTde antes.
  9. Haga clic en el resto del asistente y haga clic Finish.

  10. Esté atento a los errores ; Es probable que las advertencias estén bien ignoradas.

    • Si hay errores, haga clic en el Reportbotón y vea el informe. Tratar de suss lo que era una Success, Errory Stopped. Probablemente necesitará corregir la causa raíz del error que está oculto en ese informe en alguna parte. Entonces, probablemente necesites hacer un DELETE FROM YourDB.dbo.theErrorTable. Ahora haga clic en el botón Atrás en el asistente de importación y desmarque cada tabla que era un Success. Repetir ad infinitum.
  11. Ejecute esto en su servidor de destino: USE YourDB; EXEC sp_msforeachtable 'ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all';

    • Si hay errores, ... No lo sé, ¡pero corríjalos e inténtalo de nuevo!
  12. ¡Hurra! :)

Gracias a todos los que respondieron esta pregunta y preguntas similares a esta en la red SE por ayudarme a resolver esto.

Zach Mierzejewski
fuente
Eres un salvavidas
Tom Gullen
1
En serio muchas gracias, tenía una copia de seguridad en un disco dañado, no podía copiar la base de datos en ninguna parte (error de E / S). Importar los datos de unas pocas tablas a la vez de esta manera me ayudó a recuperar el 99%.
Tom Gullen
1
¡Tú Molas! Otro comando que me ayudó: EXEC sp_msforeachtable 'delete from? '; Si ocurre un error, elimine todo es la ley. El script sp_msforeachtable está aquí gist.githubusercontent.com/metaskills/893599/raw/…
Sanchitos el
4

En el asistente de importación, puede eliminar las filas primero y, si tiene campos de identidad, puede habilitar la inserción de identidad de la siguiente manera

ingrese la descripción de la imagen aquí

Si desea deshabilitar la restricción de verificación, cuando el asistente le solicite que guarde el paquete, guárdelo y luego edite el administrador de conexión de la siguiente manera:

ingrese la descripción de la imagen aquí

Nota: No puede TRUNCAR la tabla cuando hay claves foráneas definidas.

Kin Shah
fuente
3

No sueltes las restricciones.

Lo que debe hacer es guardar el paquete SSIS que crea el asistente y luego editarlo en BIDS / SSDT. Cuando edite el paquete, podrá controlar el orden en que se procesan las tablas para poder procesar las tablas principales y luego procesar las tablas secundarias cuando todas las tablas principales estén listas.

mrdenny
fuente
3
Eso tampoco es realmente efectivo, en este momento llevaría casi una hora modificar el paquete para asegurarse de que todo esté en el orden correcto, e incluso entonces no puedo estar seguro. Esto se volvería más engorroso a medida que crezca la base de datos y hacerlo siempre, no gracias. Tiene que haber una manera simple de hacer esto.
1

Problemas como este nos muestran que las personas que hacen el servidor SQL nunca han usado su producto. Esta es una omisión tan evidente que uno tiene que preguntarse qué más se olvidaron de hacer correctamente (tengo una lista de otros 30 problemas enloquecedores como este que tuve que superar para que esto funcione como lo hacen otros DB) de la caja; incluido el hecho de que necesitamos un pésimo asistente para hacer esto en primer lugar [si tuviera el tiempo que he pasado esperando que este asistente se conecte y enumere las mismas tablas para el mismo DB, cada vez, de regreso ... tendría tiempo para unas buenas vacaciones]).

Soy muy vago y no quiero escribir EXEC sp_msforeachtable ...dos veces cada vez que hago esto. Mi trabajo ha sido dejar las restricciones en el servidor de producción y eliminarlas del servidor de desarrollo. Esto evitará el error, pero este método tiene algunos efectos secundarios MUY GRANDES. Primero, ya no podrá restaurar una copia de seguridad completa en su servidor de desarrollo (a menos que esté de acuerdo con eliminarlos de nuevo). En segundo lugar, esto funciona mejor cuando está seguro de que los consumidores de sus datos también imponen estas restricciones (o no les importan). En mi caso, solo tenemos un consumidor (nuestro sitio web), por lo que también hemos incorporado estas restricciones en el código del sitio (es decir, antes de eliminar un registro de usuario, primero eliminamos todos los registros telefónicos de ese usuario). Si, esto esencialmente niega la necesidad de restricciones en primer lugar y duplica el trabajo que necesito hacer, pero también me da la oportunidad de verificar que mi código funcione con o sin restricciones basadas en DBMS (el hecho es que todavía están en el producto servidor solo como un plan de contingencia). Podría llamar a esto una falla en mi diseño, pero prefiero llamarlo una solución para un DBMS defectuoso. En cualquier caso, aún es más rápido y fácil hacerlo en cualquier otro lugar que desde MSSQL porque no puede hacer frente a su propio diseño.

krowe2
fuente
0

Creo que no puede realizar copias de seguridad y restaurar desde el servidor de producción, ya que son datos cruciales. Bueno, sin los derechos adecuados, realmente se vuelve más complicado. Pero si tiene db backup n restore en este momento, puede hacerlo.

O bien, una forma que recomendaría es eliminar todas sus restricciones e índices y luego agregarlos nuevamente una vez que los datos se hayan importado o exportado.

No es una respuesta exacta, pero se procesará rápidamente.

usuario2404431
fuente
Gracias, pero específicamente dije que no quiero escribir un script de restricción drop / create.
0

Solo lee ese tema. Es una publicación antigua, pero esto es lo que hice para ayudar a las futuras personas a leer esto.

En mi caso, quería importar a una tabla idéntica vacía. Al editar el mapeo, selecciono <ignore>la clave principal. Todo mi contenido se agrega automáticamente de manera agradable.

Espero que ayude a alguien

Greg
fuente
1
¿Ignorar la clave primaria ayudaría con las claves externas?
dezso
En mi caso sí, ya que en realidad estaba duplicando una tabla. Así que terminé con las mismas claves primarias. Entonces, las teclas foráneas que apuntan a mi mesa todavía corresponden a la entrada correcta
Greg