DB-MAIN - Identification relative
par
, 27/03/2016 à 20h57 (4136 Affichages)
_____________________________________________________________________________________________________
On a vu comment créer des entités-types et leurs associations avec DB-MAIN. Il s’agit ici de montrer comment identifier une entité-type sémantiquement réputée faible (weak entity-type) relativement à une entité-type réputée plus forte. Par exemple, si une discussion est ouverte chez developpez.com, il est possible (et même souhaité...) qu’elle suscite des réponses, mais celles-ci n’existent qu’en dépendance totale, relativement à la discussion : une réponse sans discussion ça n’a pas de sens, une réponse est fondamentalement une propriété d’une discussion. Techniquement, une possibilité de mettre en évidence qu’une entité-type (REPONSE en l’occurrence) est faible par rapport à une autre entité-type (DISCUSSION), qu’elle en dépend, est d’utiliser l’identification relative.
(1) Cas des associations de un à plusieurs
Partons de l’exemple dans lequel une discussion peut susciter de 0 à N réponses :
![]()
Le mode d’identification utilisé pour l’entité-type REPONSE est absolu, cette entité-type a pour identifiant {ReponseId}. Pour passer à l’identification relative, l’association SUSCITER doit participer à l’identifiant. Pour cela, on commence par un clic sur l’identifiant ReponseId de l’entité-type REPONSE, ce qui provoque l’ouverture de la boîte de propriétés associée à cet identifiant, et dans laquelle on s’intéressera à la propriété components :
![]()
Dans la boîte de propriétés, on clique sur « ReponseId » (propriété components), ce qui fait apparaître le boutonqui permettra l’ouverture de la fenêtre « Multiple choice dialog » :
![]()
En cliquant sur le bouton, on provoque effectivement l’ouverture de la fenêtre « Multiple choice dialog », dans laquelle figurent à gauche les éléments participant à l’identification de l’entité-type REPONSE, et à droite les éléments pouvant y participer :
![]()
On sélectionne l’association SUSCITER, et au moyen du bouton « Add First », on la fait passer à gauche, en tant que 1er composant de l’identifiant de l’entité-type REPONSE :
![]()
Après qu’on a fait OK, l’association SUSCITER fait bien partie de l’identifiant de l’entité-type REPONSE :
![]()
=>
![]()
Pour voir à quoi ressemble le script SQL de création des tables, on commence par dériver le MCD en MLD (cf. le billet expliquant la génération d’un MLD et d’un script SQL de création des tables) :
![]()
Puis on demande la génération du script SQL :
![]()
Au résultat :
create table DISCUSSION ( DiscussionId int not null, DiscussionTexte varchar(255) not null, constraint ID_DISCUSSION primary key (DiscussionId)); create table REPONSE ( DiscussionId int not null, ReponseId int not null, ReponseTexte varchar(255) not null, constraint ID_REPONSE primary key (DiscussionId, ReponseId)); alter table REPONSE add constraint SUSCITER_FK foreign key (DiscussionId) references DISCUSSION (DiscussionId);
En notant qu’il sera opportun d’ajouter à la contrainte SUSCITER_FK une action de compensation CASCADE, l’instruction ALTER TABLE étant alors à remplacer par la suivante :
alter table REPONSE add constraint SUSCITER_FK foreign key (DiscussionId) references DISCUSSION (DiscussionId) on delete CASCADE ;
(2) Cas des associations de un à plusieurs : variante
Partons du MCD suivant, dont l’objet est la modélisation de commandes de produits par des clients de l’entreprise Dubicobit :
![]()
En dépit du diagramme ci-dessus, selon lequel le rôle d’une ligne de commande consisterait seulement à associer une commande et un produit, on peut aussi considérer qu’une ligne de commande est une propriété multivaluée d’une commande. Quoi qu’il en soit, on peut être contraint à considérer qu’une ligne de commande fait l’objet non pas d’une association, mais d’une entité-type faible.
Supposons en effet que, pour chaque ligne de commande, Dubicobit s'engage en fonction des disponibilités des produits en stock, en cours de fabrication, des approvisionnements en cours, etc. : techniquement parlant, l’association LIGNE_CDE ne permet pas de prendre en compte les engagements de Dubicobit : on est conduit à s’orienter vers une modélisation telle que :
[COMMANDE]--1,N------------1,1--[LIGNE_CDE]--1,N------------1,1--[ENGAGEMENT]
En conséquence, on transforme l’association LIGNE_CDE en entité-type. Par exemple en passant par la barre de menus :
TRANSFORM > Rel-type > RT -> Entity type
![]()
L’AGL permet de renommer ce qui va être une nouvelle entité-type et ses associations (rel-types) avec COMMANDE et PRODUIT :
![]()
Renommons donc :
![]()
En conséquence de quoi, le diagramme devient le suivant :
![]()
La nouvelle entité-type LIGNE_CDE est automatiquement identifiée relativement à COMMANDE et PRODUIT, mais si on considère que LIGNE_CDE est une entité-type faible par rapport à COMMANDE, c'est-à-dire une propriété multivaluée de celle-ci, on considérera qu’identifier relativement à COMMANDE suffit, l’association avec PRODUIT ne correspondant qu’à une référence tout ce qu’il y a d’ordinaire. On supprimera donc LIGNE_CDE_PRO_PRODUIT de l’identifiant de LIGNE_CDE. Mais comme une commande peut comporter plusieurs lignes, on compensera en ajoutant un attribut LigneCdeId à cette entité-type et en le faisant participer à l’identifiant.
Techniquement : dans un 1er temps, on sélectionne, dans la boîte de propriétés qui lui est associée, les composants (components) de l’identifiant :
![]()
En cliquant sur le bouton, on ouvre la fenêtre « Multiple choice dialog » :
![]()
Dans laquelle on fait passer (par Remove) r.LIGNE_CDE_PRO.PRODUIT à droite et (par Add Next) LigneCdeId à gauche :
![]()
Au résultat, l’entité-type LIGNE_CDE est identifiée relativement à l’entité-type COMMANDE :
![]()
Pour voir à quoi ressemble le script SQL de création des tables, on commence par dériver le MCD en MLD (cf. le billet expliquant la génération d’un MLD et d’un script SQL de création des tables) :
![]()
Script SQL (MySQL) :
create table PRODUIT ( ProduitId int not null, ProduitReference char(12) not null, ProduitLibelle varchar(32) not null, constraint PRODUIT_PK primary key (ProduitId), constraint PRODUIT_Reference_AK unique (ProduitReference)); create table CLIENT ( ClientId int not null auto_increment, ClientNom varchar(32) not null, ClientSiret bigint not null, ClientIban varchar(27) not null, constraint CLIENT_PK primary key (ClientId), constraint CLIENT_SIRET_AK unique (ClientSiret), constraint CLIENT_IBAN_AK unique (ClientIban)); create table COMMANDE ( CommandeId int not null, CommandeNo char(8) not null, CommandeDate date not null, ClientId int not null, constraint COMMANDE_PK primary key (CommandeId), constraint COMMANDE_CommandeNo_AK unique (CommandeNo)); create table LIGNE_CDE ( CommandeId int not null, LigneCdeId int not null, Quantite int not null, ProduitId int not null, constraint LIGNE_CDE_PK primary key (CommandeId, LigneCdeId)); alter table COMMANDE add constraint COMMANDE_CLIENT_FK foreign key (ClientId) references CLIENT (ClientId); alter table LIGNE_CDE add constraint LIGNE_CDE_PRODUIT_FK foreign key (ProduitId) references PRODUIT (ProduitId); alter table LIGNE_CDE add constraint LIGNE_CDE_COMMANDE_FK foreign key (CommandeId) references COMMANDE (CommandeId);
(3) Cas des associations de un à un
Partons de la règle de gestion des données suivante :
Un client peut avoir au plus un site Web :
[CLIENT]--0,1------------(Avoir)------------1,1--[SITE_WEB]
![]()
On peut procéder à l’identification de l’entité-type SITE_WEB relativement à l’entité-type CLIENT. Dans le cas de DB-MAIN, il y a un os, car celui-ci exige que la cardinalité maximale portée par la patte connectant cette entité-type et l’association AVOIR soit non pas 0,1 mais 0,N, sinon on a droit à une remarque désagréable :
![]()
Il s’ensuit que pour résoudre le problème, contraint et forcé, le temps de la manip on va donc remplacer la cardinalité 0,1 par 0,N. Qui plus est, l’entité-type SITE_WEB devra être dotée d’un attribut participant à l’identification : justement c’est ce qu’on ne veut pas ! (On veut bien d’un identifiant alternatif, par exemple l’URL du site, mais c’est tout). Quoi qu’il en soit, on crée un attribut xxx identifiant de l’entité-type SITE_WEB, là encore le temps de la manip : quand on en aura terminé, on supprimera cet attribut.
(a) L’attribut xxx participe à l’identifiant de l’entité-type SITE_WEB :
![]()
(b) L’association Avoir participe bien sûr aussi à l’identifiant de l’entité-type SITE_WEB :
![]()
Au résultat :
![]()
(c) Maintenant, il s’agit de supprimer l’attribut xxx. Si on commence par vouloir l’évacuer de l’identifiant, on est gratifié d’un message d’erreur :
![]()
Mais si on tente la suppression de l’attribut xxx lui-même, ça passe (au moins avec la version 9.3.0 de l’AGL...) :
![]()
Reste à remplacer la cardinalité 0,N par 0,1 initiale, ça passe :
![]()
Accessoirement, on rend {Url} identifiant alternatif (cf. le billet traitant du sujet) :
![]()
Pour voir à quoi ressemble le script SQL de création des tables, on commence par dériver le MCD en MLD (cf. le billet expliquant la génération d’un MLD et d’un script SQL de création des tables) :
![]()
Code SQL correspondant (MySQL) :
create table CLIENT ( ClientId int not null auto_increment, ClientNom varchar(32) not null, ClientSiret bigint not null, ClientIban varchar(27) not null, constraint CLIENT_PK primary key (ClientId), constraint SID_CLIENT_1 unique (ClientSiret), constraint SID_CLIENT unique (ClientIban)); create table SITE_WEB ( ClientId int not null, Url varchar(32) not null, constraint SITE_WEB_PK primary key (ClientId), constraint SITE_WEB_URL_AK unique (Url)); alter table SITE_WEB add constraint SITE_WEB_CLIENT_FK foreign key (ClientId) references CLIENT (ClientId);
Cela dit, on arrive évidemment au même résultat en utilisant la spécialisation de l’entité-type CLIENT :
__________________________________________________________________________