Le parcours d'un arbre en SQL repose souvent sur l'utilisation de procédures complexes et coûteuse en ressources ce qui fait qu'elles sont difficilement exploitables lorsque les arbres atteignent une certaine taille. Pour pallier ce problème, il faut pouvoir parcourir l'arbre avec de simples requêtes SQL. Cette méthode nécessite l'usage de structures particulières.

En effet, l'on pourrait se contenter de simplement une table qui stocke les liens père-fils et d'utiliser un algorithme pour reconstruire une repréentation de l'arbre grâce à des langages avancés (PL/SQL, etc.). Mais ces méthodes nécessitent souvent des méthodes utilisant des boucles imbriquées qui se révèlent rapidement très coûteuses en ressources pour le résultat obtenu.

Nous pouvons améliorer la méthode en améliorant les structures utilisées.

Arbre générique

Dans notre exemple, nous étudierons le cas d'un arbre générique, c'est-à-dire que chaque père peut avoir de 1 à n fils et chaque fils de 1 à n pères. Par exemple :


Arbre avec un seul tronc

Ou encore :

Arbre avec plusieurs troncs

Terminologie

Dans le reste de l'article, nous utiliserons la terminologie suivante :

Principe

Oracle propose une fonction de parcours d'arbre (connect by). Il s'agit d'un algorithme récursif. Il est possible de réaliser la même fonctionnalité, cependant l'exécution devient lente lorsque la quantité de données croît. Pour conserver de bonnes performances, il faut éviter la récursion.

Pour éviter toute récusion en SQL, une solution simple consiste à mettre l'arbre à plat. Ainsi, pour un noeud donné, on retrouve tous les éléments de l'arbre passant par ce noeud (si ce noeud est la racine, on retourne l'arbre en entier).

Cependant, si l'on met l'arbre à plat, on perd une partie de l'information, celle qui concerne notamment l'ordre hiérarchique des noeuds. Conserver le lien père-fils est donc primordial.

Un arbre générique sera donc stocké sous deux informations complémentaires :

Principe de stockage d'une représentation d'arbre

Le stockage d'une représentation d'arbre se fera de la façon suivante : Chaque noeud sera stocké avec tous ses descendants directs ou indirects.

Dans le cas du premier exemple d'arbre :


Arbre avec un seul tronc

Si nous nous attachons au parcours 1-2-4-7-8, cette décomposition donnera :


Décomposition d'arbre

Chaque niveau est stocké avec ses descendants.

Seuls les liens en double seront éliminés.

Cependant, pour savoir ce qui était directement relié et reconstituer l'arbre dans son intégralité, nous avons besoin de conserver les liens directs père-fils egalement.

Création des structures

Pour représenter cet arbre, trois tables sont nécessaires :

Table de dimension

Rien de plus simple pour la table de dimension. Elle contient la description individuelle de chaque noeud :

id Propriété
1 racine
2 noeud numéro 2
3 noeud numéro 3
4 ...

Table de lien direct

Les liens directs sont les relation père-fils uniquement. Il faut une table à elle seule car un fils peut avoir plusieurs pères, ce qui exclue de stocker cette information dans la table de dimension (ce qui serait le cas si un fils ne pouvait avoir qu'un seul et unique père, sauf pour la racine) :

père fils
1 2
2 3
2 4
2 5
4 7
7 8
5 6
6 8

Remarque

Notons que ces liens sont orientés. En effet, le lien 3-->2 n'est pas la même chose que le lien 2-->3. Ainsi, dans cet arbre, il est possible de faire des boucles. Il faudra donc prendre cela en compte lors du parcours pour éviter de tourner indéfiniment. Mais cette notion de sens est nécessaire, notamment dans le cas de liens à états.

La table des chemins

Pour parcourir l'arbre sans utiliser de boucle, il faut stocker les chemins possibles dans une table. Ainsi, le noeud 4 a pour antécédant le noeud 2 mais aussi le noeud 1 et pour successeur le noeud 7 mais pas le noeud 6. La description complète ressemblera donc à :

ascendant descendant
1 2
2 3
2 4
2 5
4 7
7 8
5 6
6 8
1 4
1 7
1 8
2 7
2 8
4 8
1 5
1 6
5 8

Chaque couple ascendant/descendant n'est noté qu'une seule fois. Une partie de la table de chemins est l'exacte reproduction de la table de liens directs. le supplément correspond à des chemins indirectes de 2ème, 3ème et nième niveau. Le chemin 1-8 (noté une seule fois) peut passer par 2-4-7 (2-4, 4-7, 2-7) ou par 2-5-6 (2-5, 5-6, 2-6). etc.

Comme on remarquera que la table chemin contient les mêmes informations père-fils que la table de lien, on peut fusionner ls deux tables en une seule avec la structure suivante :

champ description
ascendant stockage de l'ascendant
descendant stockage du descendant
type (boolean indexé) true si lien direct père-fils, false sinon

Ainsi, avec une simple vue ne sélectionnant que le type père-fils (type=true), nous recréons alors la table tache_lien et toute l'arborescence n'est stockée que dans une seule table.

Les manipulations de données ne se font plus alors que sur une seule table (ici tache_chemin). La table de lien n'étant qu'une vue de la table de chemins.

Alimentation des structures

Tout le potentiel de l'arbre stocké de cette façon repose sur l'alimentation. En effet, il est assez difficile de générer automatiquement d'un seul coup un arbre existant sous une autre forme (par exemple, uniquement sous la forme lien père-fils). En revanche, si l'arbre est construit depuis le départ étape par étape, à partir de rien, noeud par noeud, la cohérence est conservée et l'arbre devient manipulable aisément.

Ajout d'un lien/ d'un noeud

L'ajout d'un lien se traduit de la même façon que l'ajout d'un noeud.

Il y a deux contextes possible. Soit il s'agit de l'ajout d'un lien pour un nouveau noeud (le noeud fils est une feuille : il n'a pas de fils), soit il s'agit de la fusion de deux arbres ou deux branches (le noeud fils est relié à d'autres pères ou d'autres fils).

L'ajout d'un noeud dans l'arbre se fait par l'intermédiaire d'ajout de lien car c'est ce qui constitue l'arbre. Sans lien, pas d'arbre. Le noeud existe déjà dans la table de dimension (une simple insertion avec INSERT). Pour le lien père-fils, rien de plus simple non plus.

Paramètres $1 : père; $2 : fils.

Suppression d'un lien

Dans le cas d'un suppression de lien, le nombre de noeuds de l'arbre ne change pas. Seuls les chemmins qui menaient aux descendants de ce lien sont rompus également.

$1 : père; $2 : fils.


Suppression d'un lien

Suppression d'un noeud

$1 : père; $2 : fils.


Suppression d'un noeud

Modification d'un lien/ d'un noeud

Toute modification se faisant sur un lien bianire, il ne s'agirait en définitive que d'une opération de suppresssion + ajout.