2010-03-18 11 views
0

J'ai une table hiérarchique sur Oracle pl/sql. quelque chose comme:Procédure pour modifier et mettre à jour la table sur la relation hiérarchique pour voir s'il y a des enfants

create table hierarchical (
    id    integer primary key, 
    parent_id   references hierarchical , 
    name   varchar(100)); 

Je dois créer une procédure pour modifier cette table si je reçois un nouveau champ qui indique, pour chaque nœud, si elle a des enfants ou non.

Est-il possible de faire l'alt et la mise à jour en une seule procédure? Tous les échantillons de code seraient très appréciés.

Merci

Répondre

2

Vous ne pouvez pas faire le ALTER TABLE (DDL) et la UPDATE (DML) en une seule étape. Vous devrez faire le ALTER TABLE, suivi du UPDATE.

BEGIN 
    EXECUTE IMMEDIATE 'ALTER TABLE hierarchical ADD child_count INTEGER'; 
    -- 
    EXECUTE IMMEDIATE ' 
    UPDATE hierarchical h 
    SET child_count = (SELECT COUNT(*) 
         FROM hierarchical h2 
         WHERE h2.parent_id = h.id)'; 
END; 

Réfléchissez à deux fois avant de le faire bien. Vous pouvez facilement savoir maintenant si un id a des enfants avec une requête.

Celui-ci vous donnera l'enfant comptage de tous les principaux nœuds par exemple:

SELECT h.id, h.name, COUNT(childs.id) child_count 
FROM hierarchical h 
LEFT JOIN hierarchical childs ON (childs.parent_id = h.id) 
WHERE h.parent_id IS NULL 
GROUP BY h.id, h.name 

Ajout d'une colonne supplémentaire avec des données redondantes fera changer vos données plus difficile, car vous aurez toujours à jour le parent aussi, lors de l'ajout/suppression d'enfants.

+0

Les données du tableau ne changeront pas souvent. En fait c'est possible, ça ne changera jamais. Le problème à propos de cette requête est que si je reçois par exemple tous les nœuds racine et que je veux savoir pour chacun s'ils ont des enfants, je devrai faire la requête le même nombre de fois que le nombre de nœuds racine. N'est-il pas possible d'utiliser quelque chose comme: exécutez immédiatement 'alter table' ... pour faire les deux en une seule étape? – user295744

+0

@ tr-raziel: J'ai édité ma réponse pour expliquer comment cela fonctionne en utilisant 'EXECUTE IMMEDIATE', mais j'ai aussi ajouté une requête qui devrait vous donner les comptes corrects pour tous les nœuds-racines. –

+0

merci beaucoup. Je comprends ce que vous essayiez de dire maintenant. – user295744

0

Si vous avez juste besoin de savoir si des enfants existent, la requête suivante peut le faire sans la boucle ou la colonne dénormalisée.

select h.*, connect_by_isleaf as No_children_exist 
     from hierarchical h 
start with parent_id is null 
connect by prior id = parent_id; 

CONNECT_BY_LEAF renvoie 0 si la ligne a des enfants, 1 si ce n'est pas le cas.

Je pense que vous pourriez probablement obtenir le nombre exact d'enfants grâce à une utilisation intelligente des fonctions analytiques et de la pseudo-colonne LEVEL, mais je ne suis pas sûr.