Comment générer DELETE en PL/SQL, sur la base des tableaux FK relations?
Est-il possible via un script ou un outil pour générer des authomatically de nombreux delete sur la base des tableaux fk relations, à l'aide de Oracle PL/SQL?
Dans l'exemple: j'ai la table: POULET (CHICKEN_CODE NOMBRE) et il y a 30 tables avec fk références à son CHICKEN_CODE que j'ai besoin de supprimer; il y a aussi d'autres 150 tables de clé étrangère liée à celle de 30 tables que j'ai besoin de supprimer en premier.
Est-il un outil ou un script PL/SQL que je peux courir dans le but de générer tout le nécessaire de les supprimer consolidés sur la base de la FK relations pour moi?
(en passant, je sais à propos de supprimer en cascade sur les relations, mais attention: je ne PEUX PAS l'UTILISER DANS MA BASE de données de PRODUCTION, parce que c'est dangereux!)
Je suis en utilisant la Base de données Oracle 10G R2.
S'il vous plaît prêter attention à ceci:
Générer de l'Instruction Delete à Partir des Relations de Clé Étrangère SQL 2008?
Un autre utilisateur a juste écrit-il dans SQL SERVER 2008, toute personne est en mesure de convertir vers Oracle 10G, PL/SQL?
Je ne suis pas capable de... 🙁
Veuillez supposer que V_CHICKEN et V_NATION sont les critères pour sélectionner le POULET à supprimer à partir de la racine de la table: la condition est: "où COD_CHICKEN = V_CHICKEN ET COD_NATION = V_NATION" à la racine de la table.
- Ce que vous proposez est un manuel de mise en œuvre de la CASACDE SUPPRIMER. Je ne vois pas comment cela pourrait être moins dangereux. De toute façon, la question essentielle est celle-ci: vous allez zap tous les enregistrements de POULET, ou seulement certains (un)?
- Dans ma situation, j'ai besoin de ZAPPER un seul enregistrement de la poule de la table... Mais a partir de cette simple enregistrement par le biais de l'intégrité référentielle, nous descendons à de nombreuses personnes et de nombreux tableaux en fonction de ça... je peux compter une env profondeur de niveau 7 (!!).
- J'ai mis à jour ma réponse avec un script pour vous d'essayer. Aucune garantie que...
- Je suis en train d'essayer le script. Peut-être qu'il ne gère pas la propagation de la intégrités référentielles à d'autres utilisateurs, comment puis-je résoudre ce problème? Dans l'intervalle, le script vient de générer plus de 3129 SUPPRIMER l'INSTRUCTION que j'étais attendue à écrire à la main! 🙂
- Merci de m'aider à comprendre pourquoi la procédure stockée est cyclying toujours sur le même 39 delete.....
- Vous savez quoi, je ne pense pas que c'est pas aussi dur que je le pensais. Je pourrais être en mesure de le corriger si j'ai du temps aujourd'hui.
- J'ai mis à jour ma réponse avec un nouveau script. Cela fonctionne pour moi mais je suspecte qu'il pourrait y avoir des problèmes si vous avez des relations complexes. Essayez-le et laissez-moi savoir comment ça se passe. 🙂
- Pourquoi êtes-vous à la programmation en "mode découverte"? C'est comme "je n'ai aucune idée de quel type de base de données, c'est, ni comment les tables sont disposées et connecté, je sais juste que j'ai besoin de supprimer une ligne dans l'un d'eux". Vous n'avez pas une bonne couche d'accès aux données de cette base de données?
- ... OP sez: "effacer en cascade sur les relations ...je ne PEUX PAS l'UTILISER DANS MA BASE de données de PRODUCTION, parce que c'est dangereux!". Et vous pensez que l'obtention d'un script à partir de l'internet (OK, DONC) et en cours d'exécution sur votre base de données de production est moins dangereux? En fin de compte, vous allez comprendre quelque soit la solution que vous accepter dans le détail parce que c'est ta peau en jeu.
- Je vous demande de vous rendre clair, je ne comprends pas votre dernière phrase.
- "Je vais comprendre quelque soit la solution que j'accepte dans le détail parce que c'est ma cacher en jeu"???? ÇA VEUT DIRE QUOI? Je comprends les mots, mais pas le sens de la phrase complète.
- Il signifie que lorsque votre bout est sur la ligne (de votre travail est à risque), vous allez ASSUREZ-vous que le code que vous utilisez est sûr, indépendamment de l'endroit où vous l'avez obtenu.
- Merci pour la traduction, Charles 🙂 je n'ai jamais vu/entendu l'expression "ton cul est sur la ligne" 🙂 Mais maintenant, c'est clair. J'ai essayé de nombreuses fois de votre procédure et il fonctionne très bien, bien sûr, je ne décolle pas de la supprimer sans avoir au préalable soigneusement les lire!!! 😉 Je utiliser pour stocker la suppression dans une table temporaire, puis les enregistrer dans un fichier, et puis j'ai lu attentivement eux à l'aide d'UltraEdit ou le CRAPAUD de l'Éditeur SQL.
Vous devez vous connecter pour publier un commentaire.
(Ma première réponse est devenu trop long et difficile à modifier, et il a obtenu de la Communauté Wikified, ce qui est vraiment gênant. Voici la dernière version du script.)
Ce script tente d'effectuer une suppression en cascade à travers la récursivité. Il devrait éviter les boucles infinies quand il y a des références circulaires. Mais il exige que toutes les circulaires des contraintes référentielles ont
ON DELETE SET NULL
ouON DELETE CASCADE
.Le problème est que si le haut niveau de la colonne de la clé n'est pas propagées tout le chemin vers le bas.
Si vous pouvez faire SUPPRIMER à PARTIR d'un petit-enfant OÙ parent_id = :1, c'est bien.
Si vous avez à faire,
puis de descendre six ou sept profonde va vous donner moche (et probablement lente) des requêtes.
Alors que vous avez dit que vous ne pouvez pas faire les contraintes CASCADE, pouvez-vous leur faire reportable initally immédiate ? De cette façon, code existant ne doit pas être touchés. Votre 'supprimer' session ferait toutes les contraintes différé. Puis supprimez de la mère, de supprimer de l'enfant, là où le disque n'est pas dans le parent, supprimer de l'enfant où il n'y a pas de correspondance dans l'enfant, etc...
C'est un excellent exercice pour le développement de vos PL/SQL compétences et général de l'Oracle de la connaissance!
Vous devez identifier toutes les contraintes de colonnes de toutes les tables avec des relations décroissant à partir de votre tableau de maître. Vous pouvez obtenir toutes les informations dont vous avez besoin à partir de deux points de vue: ALL_CONSTRAINTS et ALL_CONS_COLUMNS. (Si toutes les tables sont dans le même schéma que l'utilisateur qui exécute le script, vous pouvez utiliser USER_CONSTRAINTS et USER_CONS_COLUMNS si vous préférez)
Cette requête trouvera toutes les contraintes de clé étrangère qui renvoie à une table donnée (
CUSTOMER
dans cet exemple):Maintenant, pour chacun des résultats à partir de cette requête, vous pouvez utiliser le
CONSTRAINT_NAME
colonne pour obtenir une table et le nom de la colonne que vous pouvez utiliser pour écrire des instructions de SUPPRESSION pour supprimer toutes les lignes enfants dans toutes les tables enfants.Cet exemple renvoie la table et de colonne nom pour une contrainte appelé
CUSTOMER_FK1
De sorte que vous pouvez faire, par exemple:
ou
Mais votre enfant des tables aussi demander à l'enfant de tables, donc bien sûr, vous devrez supprimer ceux lignes enfants (appel de leur petit-enfant de lignes) en premier. Supposons qu'il y est une table appelée reservation_detail qui a une relation de clé étrangère avec de la réservation de votre commande supprimer pour reservation_detail pourrait ressembler à:
Et si reservation_detail a aussi des enfants... vous voyez l'idée. Bien sûr, vous pourriez utiliser des jointures au lieu de requêtes imbriquées, mais le principe est le même: les niveaux plus profonds de vos dépendances, plus complexe votre supprimer des commandes.
Donc, maintenant vous savez comment le faire, le défi est d'écrire un générique PL/SQL script pour supprimer toutes les lignes enfants, petits-enfants lignes, arrière-petit-enfant de lignes ... (à l'infini) d'une table, de bas en haut. Vous devrez employer la récursivité. Devrait être un programme amusant à écrire!
(Dernière édition: supprimé le script; voir mon autre réponse pour la solution finale.)
select * FROM all_constraints
et de regarder la REPORTABLE colonne des contraintes sur l'ensemble de vos tables.AND delete_rule = 'NO ACTION'
, c'est plus simple.and table_name <> parent_table
de retour dans la requête.C -> B -> A -> C
où TOUTES les contraintes sont SUR DELETE SET NULL, et le C->B et B->Une des contraintes sur les valeurs null colonnes.