laowantong / mocodo

Modélisation Conceptuelle de Données. Nickel. Ni souris.
https://www.mocodo.net
MIT License
181 stars 51 forks source link

Clés candidates #79

Closed fduchatea closed 11 months ago

fduchatea commented 1 year ago

Mocodo permet de définir une clé primaire (simple ou composite, c'est à dire composée de plusieurs attributs). Mais Mocodo ne permet pas de définir plusieurs clés dans une relation.

Etudiant(num, nom, prénom, adresse, email)

Dans l'exemple ci-dessus, la clé primaire est num, mais email est aussi une clé (candidate) car ses instances ne peuvent pas inclure de doublon.

Résumé du concept de clé (tiré du livre "Fundamentals of Database Systems" page 170) :

Une superclé, c'est un ensemble d'attributs sans instance en doublon. L'ensemble des attributs d'une relation est une superclé par ex (sous l'hypothèse que la relation possède une clé primaire). Par contre, la plupart des superclés ne sont pas minimales. Une clé est donc un ensemble minimal d'attributs qui garantit l'absence de doublons et dans lequel on ne peut plus retirer un attribut (sans provoquer un doublon). Ces clés minimales sont appelées clés candidates. Et parmi ces clés minimales, on en choisit une pour être la clé primaire.

Comment ajouter ce concept de clé dans Mocodo ?

La visualisation est plutôt simple : les attributs soulignés ensemble (par un trait non interrompu) forment une clé . Par exemple (ne pouvant souligner, il faut survoler le lien pour voir le trait) :

Etudiant([num](), [nom, prénom](), adresse, [email]())

La relation Etudiant possède ici 3 clés : num, (nom, prénom) et email. La clé composite (nom, prénom) est évidemment peu réaliste... ses 2 attributs sont soulignés d'un trait plein. En terme de visibilité, ce n'est pas idéal quand même pour distinguer les différentes clés... Peut-être un souci : besoin de réorganiser les attributs pour mettre côte à côte ceux qui forment une clé composite afin de pouvoir les souligner ensemble par un même trait.

La partie la plus délicate est la représentation dans le fichier d'entrée Mocodo : puisqu'il peut y avoir plusieurs clés (composites ou non), il faudrait pouvoir différencier chaque groupe d'attributs formant une clé. Le système de parenthèses (ou autres délimiteurs) pourrait être une solution (qui résout le problème évoqué précédemment sur la réorganisation des attributs). Ca donnerait ça :

Etudiant : num, (nom, prénom), adresse, (email)

% ou (si on ne garde pas le raccourci du premier attribut qui est automatiquement clé primaire) :

Etudiant : (num), (nom, prénom), adresse, (email)

Pour des raisons de compatibilité (et là je pense à mes 30+ jeux de données ;), je préfère qu'on garde le raccourci. Peut-être que l'on peut utiliser le _ comme délimiteur de clé candidate et comme drapeau pour la clé primaire (composite) :

Etudiant : _num, _nom, prénom_, adresse, _email_
Arbre : idParcelle, _numéro, att3, _cc1a, cc1b_, att4

Dans l'exemple Arbre, la clé primaire serait composite (idParcelle, numéro) et une clé candidate serait (cc1a, cc1b). Ca permet de conserver le même fonctionnement qu'actuellement, et juste traiter le cas des '_' en tant que délimiteurs.

Un avantage pour conclure : Mocodo pourra générer des contraintes d'unicité sur les clés candidates (hors celle qui est clé primaire).

laowantong commented 1 year ago

Merci beaucoup pour cette description bien détaillée.

Pas d'inquiétude, j'essaie dans la mesure du possible d'assurer la rétro-compatibilité des fonctionnalités de base. Le soulignement implicite des identifiants est utile à 100 % des utilisateurs, tandis que la notion de clé alternative (i. e., si j'ai bien compris, clés candidates moins clés primaires) n'en intéressera probablement qu'assez peu.

Au final, le but semble juste de déclarer en SQL certaines colonnes ou certains groupes de colonnes comme uniques. L'intérêt de porter cette directive au niveau conceptuel ou relationnel ne me paraît pas forcément évident, mais bon, je ne suis qu'un utilisateur parmi d'autres.


Merci pour tes propositions de syntaxe basée sur des délimiteurs. Cependant, à vue de nez, je ne pense pas pouvoir les retenir, pour plusieurs raisons :


Au stade actuel de ma réflexion, je pense plutôt opter pour une représentation basée sur des numéros :

Cela te conviendrait-il ?

fduchatea commented 1 year ago

Je comprends pour les délimiteurs, et je suis d'accord que c'est un besoin très spécifique.

Par rapport à la solution proposée :

Pour le MCD, une solution trouvée ici, pages 21-22 et qu'on rencontre souvent dans des outils de modélisation : l'entité ne souligne que la clé primaire, et un nouveau cadre apparait en-dessous de celui des attributs pour lister toutes les clés. Quelque chose comme :

ETUDIANT

num nom prénom adresse ...

🔑 num 🔑 (nom, prénom)

Le cours suivant (sur le modèle relationnel) des mêmes auteurs évoque bien les clés candidates, mais aucun exemple n'est montré... En relationnel, le soulignement prolongé semble être la solution la plus fréquente pour indiquer les différentes clés :

ETUDIANT(num, nom, prénom, adresse, ...)

Peut-être que cette représentation relationnelle est la plus simple à mettre en oeuvre ? Considérant que c'est un besoin peu fréquent et que la sortie relationnelle peut de toute façon être modifiée (en écrivant un nouveau transformer, par ex si on veut mettre les clés entre crochets), on pourrait s'en contenter, non ?

laowantong commented 1 year ago

Oui, au niveau syntaxe ça a l'air de marcher (je l'ai implanté).

Tout ce qui est visualisation demande à être réfléchi.

Par ailleurs, question : deux clés candidates peuvent-elles avoir un attribut commun ? A priori je ne vois pas ce qui pourrait s'y opposer.

laowantong commented 1 year ago

Candidat Markdown :

**Client** (<ins>réf. client</ins>, nom<sup>u1</sup>, prénom<sup>u1</sup>, adresse, mail<sup>u2</sup>)

Rendu :

Client (réf. client, nomu1, prénomu1, adresse, mailu2)

fduchatea commented 1 year ago

Oui, la version avec clés en exposé est lisible et prête moins à confusion.

Deux clés candidates peuvent avoir un attribut commun.

COURS(id_enseignant, id_promo, id_cours, date)

Deux clés candidates avec des attributs communs : (id_enseignant, id_promo, date) et (id_enseignant, id_cours, date).

laowantong commented 1 year ago

Joli exemple. Syntaxiquement, j'aurais la possibilité d'exprimer ça comme ça :

COURS: 12_id_enseignant, 1_id_promo, 2_id_cours, 12_date

Je lis COURS comme SÉANCE (sinon, il serait identifié par id_cours). C'est manifestement une table issue d'une association. Et là, je ne vois pas a priori comment exprimer élégamment les contraintes d'unicité au niveau conceptuel. Sans compter que le même cas peut également se poser dans une table issue d'une entité (i. e., avec au moins une clé étrangère).

Il y aurait une solution consistant à dupliquer (fictivement) certains attributs dans les associations concernées, à seule fin de les décorer d'un ou plusieurs numéros de groupe. Ça me paraît horrible à plusieurs points de vue.

Je crains donc que la prise en charge des clés candidates par Mocodo ne s'arrête à celles qui font partie d'une même entité :wink:

fduchatea commented 1 year ago

Au niveau conceptuel, je trouve peu de représentations des clés candidates. Ce ne serait pas pertinent de dupliquer les attributs dans les associations pour indiquer une appartenance à une clé candidate... Donc ok pour se limiter aux entités.

fduchatea commented 1 year ago

En fait, l'exemple précédent poserait un souci de modélisation. Comme SÉANCE est une relation issue d'une association, ce n'est pas possible d'avoir plusieurs clés candidates (par définition, l'association étant identifiée par l'ensemble des identifiants de ses entités porteuses). Pour résoudre ce problème de modélisation, il faudrait utiliser une agrégation par ex. Donc ce cas-là ne pose plus de problème.

laowantong commented 1 year ago

Oui, même si l'exemple était séduisant, on était déjà plus au niveau relationnel que conceptuel. Certains problèmes sont plus simples à résoudre à ce niveau, qui évite de recourir à des représentations graphiques tarabiscotées et difficiles à interpréter.

Si vous voulez jeter un coup d'œil, j'ai quasiment fini le travail sur cet aspect dans la branche parsing. Ça m'a pris plus de temps que je n'aurais voulu, pas sûr d'avoir bien géré les priorités.

image

fduchatea commented 1 year ago

Suite à une discussion avec les collègues, le cas d'une entité avec clé étrangère comme clé candidate est peu fréquent. A-priori, c'est uniquement quand les cardinalités d'une asso sont 1,1 de chaque côté.

PERSONNES: id, nom
PE, 11 PERSONNES, 11 EMAILS
EMAILS : email, x, y

Dans ce cas, Mocodo devrait détecter que email (ou id selon la traduction) est une clé candidate (et donc lui assigner la représentation appropriée), et déclarer l'attribut en UNIQUE (+ NOT NULL) dans le code SQL.

S'il y a une cardinalité 0,1 alors ça ne fonctionne pas (on peut mettre la contrainte UNIQUE mais ce n'est pas forcément une clé puisque les NULL sont possibles). S'il y a une cardinalité 0,n d'un côté, alors ça ne peut pas être une clé.

laowantong commented 1 year ago

C'est un genre d'association que j'interdis explicitement à mes étudiants. Mocodo le tolère, j'ai retrouvé ça dans la doc :

Autre point litigieux: dans les dépendances fonctionnelles à double sens ((1,1) des deux côtés), la priorité est donnée à la première des entités énumérées dans l'association. Même chose quand deux (0,1) sont en concurrence.

Donc, ça donne de façon déterministe :

EMAILS (email, x, y) PERSONNES (id, nom, #email)

Oui, Mocodo pourrait (devrait) alors ajouter les contraintes UNIQUE + NOT NULL sur l'attribut email.

Je vais ouvrir une issue séparée, c'est vraiment un point de détail dans un point de détail, et je ne veux pas me retarder davantage dans mon travail.