2013-06-11 3 views
0

À des fins de test, je voudrais générer un script d'insertion pour tous les enregistrements de toutes les tables associées à un enregistrement particulier dans l'une des tables racines. Par exemple, je pourrais avoir une table "Participant", qui a un nombre quelconque d'entrées associées dans la table "Documents", qui à son tour a un certain nombre d'entrées associées dans la table "PrintRequests" et ainsi de suite. J'ai des centaines de ces tables dans la base de données.Comment obtenir tous les enregistrements associés à un enregistrement dans une table racine agrégée

Existe-t-il un moyen de sélectionner/scripter tous les enregistrements de toutes les tables associées, par exemple ParticipantId = 1? De cette façon, pour un participant représentatif, je peux extraire tous les enregistrements associés dans toutes les tables. Une de mes idées était de restaurer une sauvegarde de la base de données complète, de modifier toutes les contraintes de clé étrangère pour supprimer en cascade puis de supprimer tout ce qui n'est pas participantid = 1 et de laisser la base de données supprimer tout ce qui n'est pas lié au participant d'intérêt, puis script sur l'ensemble de la base de données de ce qui reste. Pour cela, il se peut que je doive abandonner et recréer toutes les contraintes que je ne sais pas comment faire dans toute la base de données.

Sinon, y a-t-il d'autres outils qui pourraient le faire? Un outil de migration par exemple qui peut prendre une requête et migrer uniquement les enregistrements et les enregistrements enfants associés de cette requête?

Répondre

0

Bien qu'il soit tout à fait possible de générer des scripts pour parcourir toutes les contraintes de clé primaire et clé étrangère et de générer ces scripts via une utilisation généreuse du SQL dynamique, cela serait une tâche non triviale. Je soupçonne fortement que vous seriez mieux servi en utilisant un produit comme DataBee pour générer votre sous-ensemble de données.

+0

Outil intéressant. L'une des principales raisons d'utiliser le sous-ensemble de la production pour nous est que cela facilite les tests. Nous pouvons regarder l'application de production et savoir par exemple que "John Smith" a 30 documents dont 12 sont des commandes d'achat. En outre, lorsque des utilisateurs/testeurs soumettent des bogues qui disent quelque chose comme "le code postal d'Alice Smith ne peut pas être modifié", nous pouvons le répliquer plus facilement. – Chaitanya

+0

@Chaitanya - Je sais que c'est des années après votre commentaire, mais je fais des recherches sur un nouvel outil Redgate, SQL Clone, et cela m'aiderait à savoir pourquoi vous n'utilisez pas actuellement une restauration complète de la production pour les tests. Merci! –

+0

@DavidAtkinson - Taille et temps. La restauration complète de la production db convient aux environnements CI/UAT/Test, mais pas à la machine locale de dev. En déboguant un problème ou en essayant de nouvelles idées/refacteurs, il est difficile de restaurer une base de données complète. – Chaitanya

0

Vous pouvez le créer en script en créant des instructions SQL dynamiques, mais je pense que c'est beaucoup de travail. Je pense que vous serez plus rapide pour trouver juste toutes les tables avec une colonne « ParticipantId » avec quelque chose comme ça

select * from all_tab_columns where column_name = 'PARTICIPANTID' 

Et puis faire un peu modifier rapidement/remplacer/autre sorte d'action de script pour vous-même générer les instructions de suppression.

En ce qui concerne les contraintes. C'est similaire. Obtenir toutes les contraintes avec

SELECT owner, table_name, constraint_name 
    FROM dba_constraints 
where table_name in (select table_name from all_tab_columns where column_name = 'PARTICIPANTID') 

Vous allumer et d'éteindre les contraintes en utilisant

ALTER TABLE <table name> ENABLE/DISABLE constraint <constraint name>; 

Peut-être que vous pourriez faire avec une boucle. L'emprunt de cette page

begin 
    for i in 
(select constraint_name, table_name from user_constraints where table_name in (select table_name from all_tab_columns where column_name = 'PARTICIPANTID') 
) LOOP 
    execute immediate 'alter table '||i.table_name||' disable constraint '||i.constraint_name||''; 
    end loop; 
end; 

Je ne suis pas sûr de votre suppression en cascade chose, mais ce qui précède donne un peu une idée comment la suppression ressemblerait à ceci:

begin 
    for i in 
(select constraint_name, table_name from user_constraints where table_name in (select table_name from all_tab_columns where column_name = 'PARTICIPANTID') 
) LOOP 
    execute immediate 'delete from '||i.table_name||' where participantid = ''1'' '; 
    end loop; 
end; 

Hope it helps.

+0

Cela fonctionne uniquement sur les tables qui référencent directement la table des participants (c'est-à-dire les tables enfant). Mais qu'en est-il des tables qui, à leur tour, font référence à ces tables et ainsi de suite (petits-enfants, arrière-petits-enfants, etc.)? Avec près de 600 tables dans mon application, le web est assez complexe. J'ai besoin de quelque chose qui peut automatiquement marcher sur cet arbre sans que je doive explicitement connaître ou spécifier chacune de ces relations. – Chaitanya

+0

Mais comment relient-ils ensemble, pouvez-vous donner un exemple de deux tables? – hol

+0

J'ai fourni un dans la question. Par exemple, un participant a n'importe quel nombre d'enregistrements dans la table "Document". Chacun des enregistrements "Document" contient un nombre quelconque d'enregistrements dans la table "PrintRequest". La table "PrintRequest" n'a donc pas de colonne ParticipantId, mais elle est liée au participant via la table Document. Il existe une table "Imprimantes" qui à son tour est référencée par la table "PrintRequest". Donc, avant de pouvoir insérer des enregistrements dans la table "PrintRequest", je dois insérer les enregistrements appropriés dans la table "Printer", et ainsi de suite. – Chaitanya

Questions connexes