I. Modélisation sans héritage▲
Pour comprendre l'intérêt de la modélisation par héritage, commençons par une application très banale qui devra contenir des prospects, des clients et des employés. Une gestion commerciale, par exemple.
Voici un exemple de modèle de données :
Nous constatons que certaines entités possèdent des attributs identiques : NOM, PRENOM se retrouvent dans EMPLOYE, CLIENT et PROSPECT. De même, NUMxxx et DATE se retrouvent dans COMMANDE et FACTURE.
Enfin, les deux associations « portent sur » contiennent elles aussi les mêmes attributs.
Ce modèle possède plusieurs inconvénients majeurs :
- Si un prospect devient un client, les informations doivent être recopiées ;
- Un employé peut aussi être un client de sa propre entreprise, ce qui oblige aussi à recopier les informations ;
- Un client ne peut avoir qu'une seule adresse alors qu'il arrive qu'un même client ait besoin d'être livré à une adresse donnée et facturée à une autre.
La première idée consiste à rassembler tous les individus dans une seule et même table. Il faut ensuite les décliner en client, prospect et employé. C'est la technique de l'héritage.
II. Modélisation d'un héritage de personnes▲
Nous voyons désormais que les entités PROSPECT, EMPLOYE et CLIENT n'ont plus de clef. C'est normal, ces entités vont hériter des données de la table PERSONNE contenant une clef.
À ce stade, il existe deux possibilités :
- chacune des tables filles (PROSPECT, EMPLOYE, CLIENT) hérite de tous les attributs de PERSONNE lors du passage au modèle physique ;
- les tables filles n'héritent que de la clef de la table PERSONNE et il faut faire une jointure entre tables fille et mère pour retrouver toutes les données.
III. Un héritage induit▲
Précisons encore notre modèle en faisant un héritage avec les tables COMMANDE et FACTURE :
Contrat est une table qui rassemble aussi bien les commandes que les factures. Ce qui permettra de distinguer une commande d'une facture sera le contenu de la colonne NATURE.
C'est aussi une modélisation d'héritage d'une autre forme.
Enfin, pour résoudre la problématique des adresses multiples, rien ne nous empêche d'externaliser les adresses dans une table à part :
La nature des adresses est soit explicite (attribut UTILITE de l'association « possède »), soit implicite du fait de la relation avec la table des contrats (adresse de facturation ou de commande).
Regardez comme ce modèle est devenu simple ! Nous sommes passés de 46 attributs à 33 tout en augmentant le nombre de rubriques pour les différentes entités. Par exemple, par rapport au premier modèle un prospect n'avait pas de titre !
IV. Transposition en modèle physique▲
En générant le modèle physique d'après le modèle ci-dessus, nous obtenons le diagramme suivant :
On note que les entités PROSPECT, EMPLOYE et CLIENT héritent de la colonne clef de la table mère PERSONNE.
V. Héritage avec exclusion mutuelle▲
Une autre possibilité dans l'utilisation des héritages est de faire en sorte qu'il n'existe qu'un seul héritier dans les diverses tables filles. Cela s'avère parfois indispensable.
Comme un bon exemple est souvent plus explicite qu'un long discours, modélisons les différents types de location de véhicule d'une agence comme Hertz, Budget ou EuropCar. Ce qui nous intéresse, c'est une entité générique des véhicules et des entités filles par type de véhicule (moto, voiture ou camion).
Voici un premier exemple d'une telle modélisation :
Veuillez noter dans ce modèle la présence de la croix dans le symbole de l'héritage. Il indique une exclusion mutuelle entre les entités filles.Mais comment résoudre cette exclusion mutuelle ?
La simple technique des intégrités référentielles est insuffisante à gérer ce cas de figure. Il faut recourir à un ensemble de triggers (déclencheurs).
Voyons d'abord comment le modèle physique est construit à partir du modèle conceptuel :
Dans le principe, il faut pour chaque insertion dans l'une des tables filles s'assurer que le véhicule n'est pas déjà utilisé par les autres tables.
Voici les triggers d'insertion et modification pour les trois tables filles, dans le langage Transact SQL de SQL Server :
Sélectionnez
|
Sélectionnez
|
Sélectionnez
|
Notez que SQL Server utilise la pseudo-table INSERTED pour les insertions en cours. Certains SGBDR utilisent la table NEW (norme SQL).
Il faut aussi créer un trigger dans la table mère afin d'empêcher la suppression si le véhicule est référencé dans l'une des tables filles.
/* Trigger TRG_DEL_VEHICULE pour contrôler la suppression dans la table "T_VEHICULE_VHC" */
CREATE
TRIGGER
TRG_DEL_VEHICULE
ON
T_VEHICULE_VHC
FOR
DELETE
AS
BEGIN
DECLARE
@errno INTEGER
,
@errmsg VARCHAR
(
255
)
/* Suppression interdite s'il existe un fils dans une des tables filles */
IF
EXISTS
(
SELECT
*
FROM
(
SELECT
VHC_ID
FROM
T_CAMION_CMN
UNION
ALL
SELECT
VHC_ID
FROM
T_MOTO_MTO
UNION
ALL
SELECT
VHC_ID
FROM
T_VOITURE_VTR)
T
WHERE
VHC_ID IN
(
SELECT
VHC_ID
FROM
INSERTED))
BEGIN
SET
@errno =
30006
SET
@errmsg =
'Ce véhicule est encore référencé dans une des tables filles. Suppression impossible.'
GOTO
LBL_ERROR
END
RETURN
/* Gestion d'erreurs */
LBL_ERROR:
RAISERROR @errno @errmsg
ROLLBACK
TRANSACTION
END
GO
Pour vérifier ce fonctionnement, vous pouvez utiliser le jeu de données suivant :
INSERT
INTO
T_VEHICULE_VHC VALUES
(
1
, '1234 AB 56'
)
INSERT
INTO
T_VEHICULE_VHC VALUES
(
2
, '9876 ZY 54'
)
INSERT
INTO
T_VEHICULE_VHC VALUES
(
3
, '7777 MN 33'
)
INSERT
INTO
T_MOTO_MTO VALUES
(
1
, 750
)
INSERT
INTO
T_CAMION_CMN VALUES
(
2
, 38
)
VI. Héritage conditionnel▲
Plus rarement implémenté, voici l'héritage conditionnel. Il s'agit de rajouter dans la table mère une colonne particulière permettant de spécifier quelle est la table fille héritière. Cela peut se faire de deux manières :
- par construction d'une vue ;
- dans la structure même de la table mère.
VI-A. Avec une vue▲
Reprenons notre exemple précédent. Ajoutons la vue suivante :
CREATE
VIEW
V_VEHICULE_VHC
AS
SELECT
VHC_ID, VTR_NOMBRE_PLACE, NULL
AS
MTO_CYLINDREE, NULL
AS
CMN_TONNAGE, 1
AS
TYPE_VEHICULE
FROM
T_VOITURE_VTR
UNION
ALL
SELECT
VHC_ID, NULL
VTR_NOMBRE_PLACE, MTO_CYLINDREE, NULL
AS
CMN_TONNAGE, 2
AS
TYPE_VEHICULE
FROM
T_MOTO_MTO
UNION
ALL
SELECT
VHC_ID, NULL
VTR_NOMBRE_PLACE, NULL
AS
MTO_CYLINDREE, CMN_TONNAGE, 3
AS
TYPE_VEHICULE
FROM
T_CAMION_CMN
Les avantages sont considérables. On peut simplifier les jointures du fait qu'il suffit d'utiliser la jointure de véhicule sur la vue pour obtenir toutes les informations sur tous les véhicules, quels que soient leurs types :
Sélectionnez
|
Sélectionnez
|
VI-B. Avec ajout de colonne▲
Bien entendu, si l'on a opté pour l'ajout d'une colonne spécifique dans la table mère, il faudra la renseigner lors de l'exécution du trigger d'insertion et de modification.
VII. Quelques liens pour en savoir plus▲
Héritage :
http://dchaffiol.free.fr/info/langages/obj/art_obj_HeritAssoc_r.htm
Base d'UML et comparaisons :
http://www.usask.ca/frenchciv/ronald/la_boite_a_objets/modelisation_avec_uml.html
PowerDesigner :
http://medias.obs-mip.fr/www/Activite/Formation/Informatique/Bdweb2/bdweb2003.html
Modélisation :
http://philippe.guezelou.free.fr/mcd/modelis.htm