• Aucun résultat trouvé

Les requêtes sur des structures de données cycliques

Dans le document BASES DE DONNÉES ET MODÈLES DE CALCUL (Page 96-100)

Le langage SQL DML

5.4 EXTRACTION DE DONNÉES DE PLUSIEURS TABLES (JOINTURE)

5.4.5 Les requêtes sur des structures de données cycliques

On qualifie de cyclique (ou récursive) une structure de données qui fait, directement ou non, référence à elle-même. La table PERSONNE illustrée à la figure 5.2 présente une structure cyclique car la colonne RESPONSABLE est une clé étrangère vers la table PERSONNE elle-même. Le rôle de cette colonne est de désigner le responsable direct de chaque personne, s’il existe.

Figure 5.2 - Un schéma cyclique : la table PERSONNE se référence elle-même

23. L’opération évoquée ici, qui retient les lignes d’une table qui sont joignables avec celles d’une autre table, est appelée, très logiquement, semi-jointure.

5.4 Extraction de données de plusieurs tables (jointure) 97

© Dunod – La photocopie non autorisée est un délit.

Ce responsable étant lui-même une personne peut donc aussi avoir un responsable24, et ainsi de suite. Cette table est déclarée comme suit :

create table PERSONNE ( NPERS char (4) not null, NOM char(25) not null, RESPONSABLE char (4),

primary key (NPERS), foreign key (RESPONSABLE) references PERSONNE)

La figure 5.3 représente un exemple de contenu de la table PERSONNE. On y lit notamment que les personnes p1 et p2 n’ont pas de responsable, que le responsable de p3 et p4 est p1, et que p4 est responsable de p5 et p6, qui elle-même est respon-sable de p7. On dessinera les relations définies dans la table afin de maîtriser ces concepts.

Cette table permet, par exemple, de répondre à la question suivante : donner, pour chaque personne (S, pour subordonné) ayant un responsable (R), le numéro et le nom de celui-ci. Il vient :

select S.NPERS, R.NPERS, R.NOM from PERSONNE S, PERSONNE R where S.RESPONSABLE = R.NPERS

Figure 5.3 - Un exemple de contenu de la table PERSONNE25

24. On considère souvent implicitement que le domaine d’application décrit par une structure cyclique est soumis à des conditions sur le graphe des objets et de leurs inter-relations. Dans cet exemple, on admettra qu’une personne ne peut être son propre responsable, ni directement ni indirectement. En d’autres termes, si on représente la relation a-pour-responsable (correspon-dant à la clé étrangère RESPONSABLE) par un arc orienté d’une personne vers son responsable, ce graphe ne peut présenter de circuits. En fait, cette contrainte ne peut être exprimée en SQL, ni être vérifiée par le SGBD. Si des données définissant un tel circuit venaient à être introduites, certains programmes d’application pourraient présenter un comportement anormal (bouclage infini).

25. Dans un but de lisibilité, les valeurs <null> ont été représentées par "- -".

Cette requête construit des couples de personnes, la première étant la personne subordonnée (S) et la seconde son responsable (R). Elle réalise donc la jointure de la table PERSONNE avec elle-même, ce qu’on appelle une auto-jointure.

La requête suivante donne, pour chaque personne de nom Dupont, son numéro, ainsi que le numéro et le nom de son responsable s’il existe.

select S.NPERS, R.NPERS, R.NOM from PERSONNE S, PERSONNE R where S.RESPONSABLE = R.NPERS and S.NOM = 'Dupont'

union

select NPERS, '--', '--' from PERSONNE

where RESPONSABLE is null and NOM = 'Dupont'

Seule la première partie de la requête peut poser un problème (la seconde complète la réponse en indiquant les personnes sans responsable, à la manière d’une jointure externe). Pour l’interpréter, supposons qu’on dispose de deux tables décrivant les personnes (figure 5.4). L’une, de nom PERSONNE, représente toutes les personnes;

l’autre, de nom SUPERIEUR, ne représente que les personnes qui sont responsables.

Il est évident que les personnes qui sont responsables d’autres personnes sont réper-toriées dans les deux tables. En fonction du contenu de la table PERSONNE proposé ci-dessus, ces tables contiendraient les données de la figure 5.4. La première partie de la requête précédente s’écrirait alors comme suit.

select S.NPERS, R.NPERS, R.NOM from PERSONNE S, SUPERIEUR R where S.RESPONSABLE = R.NPERS and S.NOM = 'Dupont'

Figure 5.4 - La table SUPERIEUR est un extrait de la table PERSONNE

On observe que la requête donnerait le même résultat si le contenu de SUPERIEUR était le même que celui de PERSONNE. En remplaçant SUPERIEUR par PERSONNE, on obtient alors la requête initiale.

Une table qui, pour la personne de numéro 'p4', contiendrait le numéro et le nom de 'p4', ainsi que le numéro et le nom de ses subordonnés de deuxième niveau

5.4 Extraction de données de plusieurs tables (jointure) 99

© Dunod – La photocopie non autorisée est un délit.

(c’est-à-dire des personnes qui ont pour responsable une personne dont 'p4' est le responsable) s’obtiendrait par une double jointure (on ignore les personnes qui n’ont pas de responsable) :

select R.NPERS, R.NOM, SS.NPERS, SS.NOM from PERSONNE R, PERSONNE S, PERSONNE SS where R.NPERS = 'p4'

and R.NPERS = S.RESPONSABLE and S.NPERS = SS.RESPONSABLE

Ces requêtes montrent que SQL ne permet pas d’obtenir facilement tous les respon-sables, directs et indirects, d’une personne déterminée, ni les personnes qui dépendent, directement ou indirectement, d’une personne déterminée, du moins sans recourir à la programmation procédurale. On dira que SQL, dans ses versions actuelles les plus répandues, ne permet pas d’exprimer des requêtes récursives26.

Un autre exemple classique de structure cyclique décrit une nomenclature de produits. On y indique la composition de chaque produit en sous-produits, ces derniers pouvant également être décomposés en autres sous-produits, et ainsi de suite. Le schéma de la figure 5.5 illustre cette structure. On notera que les relations entre produits ne peuvent plus s’exprimer par une simple clé étrangère ajoutée à la table PRODUIT comme nous l’avions fait pour la table PERSONNE. En effet, alors qu’une personne n’a qu’un seul responsable, un produit peut être constitué de plusieurs composants et entrer dans la composition de plusieurs autres produits.

C’est la table COMPOSITION qui représente les relations de composition entre produits. Une ligne <h,b,q> indique que le produit b est un composant du produit h, et qu’il faut q unités de b pour fabriquer 1 unité de h. On peut ainsi représenter le fait qu’une unité du produit p2 contient 8 unités du produit p7 et 2 unités du produit p8 (la figure 5.6 représente un exemple de nomenclature).

Figure 5.5 - Une structure indirectement cyclique : nomenclature d’une gamme de produits

L’identifiant indique qu’un produit n’est renseigné qu’une seule fois comme compo-sant direct d’un même produit. Les matières premières ont un prix et un poids unitaires qui doivent être fixés; le prix et le poids des autres produits peuvent être calculés à partir des caractéristiques de leurs composants.

26. ORACLE propose une version spécifique de la requête SFW permettant de calculer une join-ture cyclique. Nous l’examinerons dans la section 6.3.3. Le lecteur intéressé par les requêtes (récursives) appliquées aux structures de graphes consultera utilement les chapitres 26 et 27 de [Celko,2000].

Figure 5.6 - Un exemple de nomenclature de produits. Les prix et poids unitaires des produits finis et semi-finis, qui sont calculables, n’ont pas été enregistrés explicitement

La requête ci-dessous donne des informations sur le produit 'p4', ainsi que sur sa composition27 :

select H.NPRO,H.LIBELLE,C.QTE,B.NPRO,B.LIBELLE from PRODUIT H, COMPOSITION C, PRODUIT B where C.COMPOSE = H.NPRO

and C.COMPOSANT = B.NPRO and H.NPRO = 'p4'

Considérant le contenu des tables représenté à la figure 5.6, on obtient :

Dans le document BASES DE DONNÉES ET MODÈLES DE CALCUL (Page 96-100)