Comment gérer les contraintes FK lors de l'importation de données à l'aide de l'assistant d'importation / exportation DTS?

16

J'essaie d'utiliser l'assistant d'importation et d'exportation SQL Server pour copier les données de ma base de données de production vers ma base de données de développement, mais lorsque je le fais, cela échoue avec l'erreur "L'instruction INSERT est en conflit avec la contrainte FOREIGN KEY" J'ai plus de 40 tables avec beaucoup des contraintes FK, existe-t-il un moyen facile de gérer cela sans avoir à écrire un script de contrainte de suppression / ajout de constrat?

Edit: je viens de découvrir que dans l'édition Web de SQL Server, qui est ce que j'exécute, DTS ne vous permettra pas d'enregistrer des packages.


la source

Réponses:

28

On m'a donné cette solution sur SQLTeam.com:

Utilisation:

 EXEC sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT all'

Importez ensuite vos données

EXEC sp_msforeachtable 'ALTER TABLE ? CHECK CONSTRAINT all'

En utilisant cette méthode, j'ai pu importer toutes les données sans aucun problème.

Paul White 9
la source
1
sp_msforeachtable(et sp_MSForEachDb) n'est pas documenté et n'est pas pris en charge. Vous ne devez pas / éviter de l'utiliser. Cela pourrait sauter les tables !! Voir cet article de @AaronBertrand -> sqlblog.com/blogs/aaron_bertrand/archive/2010/12/29/… et cet élément de connexion - (MS indiquant qu'ils ne le corrigeront pas) -> connect.microsoft.com/SQLServer / feedback / details / 264677 /…
Kin Shah
A parfaitement fonctionné pour moi après des heures à me battre la tête en essayant de contourner les contraintes FK pour une exportation de données.
levininja
En cours d'exécution sur Azure SQL V12, j'obtiens l'erreur "Impossible de trouver la procédure stockée 'sp_msforeachtable'."
Dai
Ne fonctionne pas quand même: /
Douglas Gaskell
Vous êtes l'homme qui sauve des vies
Can Şahin Bakır
5

J'ai produit une copie exacte d'une base de données sur ma machine à partir d'un serveur que je ne contrôlais pas.

Je suis un schmuck , mais c'est ce que j'ai fait:

  1. Création de la base de données à partir de mon script qui était sous contrôle de code source (indice, indice!) Si vous n'avez pas le script, vous pouvez toujours le générer à partir de la base de données existante via l' Tasksoption.

  2. Si des données ont été insérées automatiquement dans YourDB lors de la création, exécutez a DELETE FROM YourDB.dbo.tblYourTable.

    • Vous ne pouvez pas tronquer les données lorsque des clés étrangères existent, vous devez donc les utiliser DELETE.
  3. Exécutez ceci sur votre serveur de destination: USE YourDB; EXEC sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT all';

  4. Faites un clic droit sur YourDB dans Object Explorer. Cliquez sur Tasks->Import Data...

  5. Les premiers écrans de l'assistant sont explicites.

  6. Sur l' Select Source Table and Viewsécran de l'assistant, cochez la case à côté de chaque table que vous souhaitez copier.

  7. Pour chaque ligne (tableau) de cet écran, cliquez dessus pour la mettre en surbrillance, puis cliquez sur Edit Mappings.

  8. Pour chaque ligne (tableau), cliquez / cochez Append rows to the destination tableet Enable identity insert.

    • Si vous cliquez Delete rows in destination tabledessus, il échouera car il n'exécute pas de DELETEcommande, il émet une TRUNCATEcommande qui est toujours en conflit avec nos clés étrangères car elle TRUNCATEn'est pas régie par leNOCHECK CONSTRAINT précédente.
  9. Cliquez sur le reste de l'assistant et cliquez sur Finish .

  10. Surveiller erreurs ; les avertissements peuvent probablement être ignorés.

    • S'il y a des erreurs, cliquez sur le Reportbouton et affichez le rapport. Essayez et Suss ce qui était une Success, Erroret Stopped. Vous devrez probablement corriger la cause première de l'erreur qui est enfouie quelque part dans ce rapport. Ensuite, vous devrez probablement faire un DELETE FROM YourDB.dbo.theErrorTable. Maintenant, cliquez sur le bouton de retour de l'assistant d'importation et décochez chaque table qui était unSuccess . Répétez à l'infini.
  11. Exécutez ceci sur votre serveur de destination: USE YourDB; EXEC sp_msforeachtable 'ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all';

    • S'il y a des erreurs, ... je ne sais pas, mais corrigez-les et réessayez!
  12. Yay! :)

Merci à tous ceux qui ont répondu à cette question et aux questions similaires à celle-ci sur le réseau SE de m'avoir aidé à comprendre cela.

Zach Mierzejewski
la source
Vous êtes un épargnant de vie
Tom Gullen
1
Sérieusement merci beaucoup, avait une sauvegarde sur un lecteur corrompu, n'a pas pu copier la base de données n'importe où (erreur d'e / s). L'importation des données quelques tables à la fois de cette façon m'a aidé à en récupérer 99%.
Tom Gullen
1
Tu gères! Une autre commande qui m'a aidé: EXEC sp_msforeachtable 'supprimer de? » Si une erreur se produit, tout est supprimé. Le script sp_msforeachtable est ici gist.githubusercontent.com/metaskills/893599/raw/…
Sanchitos
4

Dans l'assistant d'importation, vous pouvez d'abord supprimer les lignes et si vous avez des champs d'identité, vous pouvez ensuite activer l'insertion d'identité comme ci-dessous

entrez la description de l'image ici

Si vous souhaitez désactiver la contrainte de vérification, lorsque l'assistant vous demande d'enregistrer le package, enregistrez-le, puis modifiez le gestionnaire de connexions comme ci-dessous:

entrez la description de l'image ici

Remarque: vous ne pouvez pas TRONCER la table lorsque des clés étrangères sont définies.

Kin Shah
la source
3

Ne laissez pas tomber les contraintes.

Ce que vous devez faire est d'enregistrer le package SSIS créé par l'assistant, puis de le modifier dans BIDS / SSDT. Lorsque vous modifiez le package, vous pourrez contrôler l'ordre dans lequel les tables sont traitées afin que vous puissiez traiter les tables parentes puis traiter les tables enfants lorsque toutes les tables parentes sont terminées.

mrdenny
la source
3
Ce n'est pas vraiment efficace non plus, il faudrait presque une heure pour modifier le paquet pour s'assurer que tout est dans le bon ordre, et même alors je ne peux pas en être sûr. Cela deviendrait plus encombrant à mesure que la base de données grandit et à le faire à chaque fois, non merci. Il doit y avoir un moyen simple de procéder.
1

Des problèmes comme celui-ci nous montrent que les personnes qui créent SQL Server n'ont jamais réellement utilisé leur produit. C'est une omission tellement flagrante qu'il faut se demander ce qu'ils ont simplement oublié de faire correctement (j'ai une liste d'environ 30 autres problèmes exaspérants comme celui-ci que j'ai dû surmonter pour que cela fonctionne comme d'autres DB le font de la boîte; y compris le fait que nous avons besoin d'un assistant pour le faire en premier lieu [si j'avais le temps que j'ai passé à attendre que cet assistant se connecte et énumère les mêmes tables pour la même base de données, à chaque fois, retour ... j'aurais le temps pour de belles vacances]).

Je suis très paresseux et je ne veux pas taper EXEC sp_msforeachtable ...deux fois à chaque fois que je fais ça. Mon travail a consisté à laisser les contraintes sur le serveur de production et à les supprimer du serveur de développement. Cela empêchera l'erreur mais cette méthode a quelques TRÈS GRANDS effets secondaires. Tout d'abord, vous ne pourrez plus simplement restaurer une sauvegarde complète sur votre serveur de développement (sauf si vous êtes prêt à les supprimer à nouveau). Deuxièmement, cela fonctionne mieux lorsque vous êtes sûr que les consommateurs de vos données appliquent également ces contraintes (ou ne s'en soucient pas). Dans mon cas, nous n'avons qu'un seul consommateur (notre site Web), nous avons donc également intégré ces contraintes dans le code du site (c'est-à-dire avant de supprimer un enregistrement d'utilisateur, nous supprimons d'abord tous les enregistrements téléphoniques de cet utilisateur). Oui, cela annule essentiellement le besoin de contraintes en premier lieu et double le travail que je dois faire, mais cela me donne également une chance de vérifier que mon code fonctionne avec ou sans contraintes basées sur le SGBD (le fait est qu'elles sont toujours sur le prod serveur uniquement comme plan d’urgence). Vous pouvez appeler cela une faille dans ma conception, mais je préfère appeler cela une solution de contournement pour un SGBD défectueux. Quoi qu'il en soit, il est toujours plus rapide et plus facile de le faire ailleurs que dans MSSQL car il est incapable de faire face à sa propre conception.

krowe2
la source
0

Je pense que vous ne pouvez pas effectuer de sauvegarde et de restauration à partir du serveur de production car il s'agit d'une donnée cruciale. Eh bien, sans les droits appropriés, cela devient vraiment plus compliqué. Mais si vous avez droit à la sauvegarde et à la restauration de la base de données, vous pouvez l'exécuter.

Ou bien, une façon que je recommanderais est de supprimer toutes vos contraintes et index, puis de les ajouter à nouveau une fois les données importées ou exportées.

Pas une réponse exacte, mais elle sera traitée rapidement.

user2404431
la source
Merci, mais j'ai dit en particulier que je ne veux pas créer de script de contrainte drop / create.
0

Lisez simplement ce sujet. C'est un vieux post mais voici ce que j'ai fait pour aider les futures personnes à lire ceci.

Dans mon cas, je voulais importer dans une table identique vide. Lors de la modification du mappage, je sélectionne <ignore>la clé primaire. Tout mon contenu est bien ajouté automatiquement.

J'espère que cela aide quelqu'un

Greg
la source
1
Ignorer la clé primaire aiderait avec les clés étrangères?
dezso
Dans mon cas, oui puisque je dupliquais en fait une table. J'ai donc fini avec les mêmes clés primaires. Les clés étrangères pointant vers ma table correspondent donc toujours à la bonne entrée
Greg