Bonsoir,
Il est peut-être de temps de voir à quoi correspond la notion de clé primaire.
Je commencerai par citer Maurice Nivat, l’un des meilleurs spécialistes mondiaux en informatique théorique, qui définit l’informatique comme étant « la rencontre de la logique formelle et du fer à souder ».
Cela dit, la notion de clé primaire est un cas particulier de la notion de clé candidate, dont voici la définition :
Une clé candidate est un sous-ensemble d’attributs K de l’en-tête T* d’une table T et qui respecte les deux contraintes suivantes :
— Unicité. Deux lignes distinctes de T ne peuvent avoir même valeur de K.
— Irréductibilité. Il n’existe pas de sous-ensemble strict de K garantissant la règle d’unicité.
Ce que j’appelle en-tête correspond à l’ensemble des noms des attributs de la table, tandis que l’ensemble des lignes de la table en constitue le corps.
Quand j’utilise le terme « ensemble », je fais référence à la théorie des ensembles. Autrement dit, la notion de clé relève ici de la logique formelle.
Prenons l’exemple de votre table Groupes. Elle a pour en-tête {id_grp, titre, sujet}. Les singletons {id_grp} et {titre} sont des clés candidates, sinon on pourrait avoir des doublons aussi bien pour {id_grp} que {titre}.
Vous avez choisi {id_grp} pour être clé primaire, plutôt que {titre}. Cela veut dire que {id_grp} a l'immense qualité de la stabilité, parce les valeurs qu'elle prend sont non significatives, il s’agit le plus souvent d'entiers, et à chaque nouvelle ligne créée, on laisse le système incrémenter d’une unité.
Au contraire, un titre a une signification pour l’utilisateur et est a priori instable, au gré des modifications apportées par cet utilisateur. Supposez maintenant que {titre} soit clé primaire : au nom de l’intégrité référentielle, c'est-à-dire de la cohésion de la base de données, la table GrpUser devrait comporter elle aussi un attribut titre, et toute modification dans la table Groupes devrait automatiquement être répercutée dans la table GrpUser. On est en train de dériver vers l’aspect performances, mais il faut y penser.
Il est donc d’usage de choisir pour clé primaire celle qui parmi l’ensemble des clés candidates de la table offre cette stabilité si précieuse. Concernant la table Groupes, {id_grp} convient, tandis que {titre} est disqualifié et se trouve ravalé au rang de clé alternative.
Le code SQL correspondant doit ressembler à ceci :
1 2 3 4 5 6 7 8 9
|
CREATE TABLE Groupes
(
id_grp INT
, titre TEXT
, sujet TEXT
, Primary key (id_grp)
, UNIQUE (titre)
) ; |
(le terme UNIQUE est synonyme de clé alternative.)
La table Comptes présente les mêmes caractéristiques générales que la table Groupes.
Passons à la table GrpUser : elle a pour seule clé candidate la paire {id_groupe, id_compte}. Comme elle présente les qualités voulues de stabilité, elle convient comme clé primaire. Sinon, il aurait fallu ajouter à la table un attribut artificiel id_truc, de telle sorte que l’on ait pour clé primaire {id_truc} et pour clé alternative {id_groupe, id_compte}.
Le code SQL correspondant doit ressembler à ceci :
1 2 3 4 5 6 7 8 9
|
CREATE TABLE GrpUser
(
id_groupe INT
, id_compte INT
, Primary key (id_groupe, id_compte)
, Foreign Key (id_groupe) References Groupes (id_grp)
, Foreign Key (id_compte) References Comptes (id_compte)
) ; |
où l’on voit notamment que le miroir de id_grp est id_groupe. La clause FOREIGN KEY permet de sous-traiter au SGBD la cohérence des liens entre les tables Groupes et GrpUser d’une part, Comptes et GrpUser d’autre part.
Passons à la table Relations. Vous avez retenu comme clé primaire le triplet {id_relation, id_invite, id_recoit}. Le code SQL correspondant doit ressembler à quelque chose comme ceci :
1 2 3 4 5 6 7 8 9 10 11
|
CREATE TABLE Relations
(
id_relation INT
, id_invite INT
, id_recoit INT
, etat CHAR(10)
, Primary key (id_relation, id_invite, id_recoit)
, Foreign Key (id_invite) References Comptes (id_compte)
, Foreign Key (id_recoit) References Comptes (id_compte)
) ; |
Maintenant, de deux choses l’une :
1) Si la paire {id_invite, id_recoit} peut prendre plusieurs fois la même valeur (par exemple, Albert et Bernard peuvent être en relation plusieurs fois), le code est correct (et la clé primaire peut même être simplement constituée du singleton {id_relation} dans la mesure où le SGBD l’incrémente systématiquement).
2) Si la paire {id_invite, id_recoit} ne peut prendre qu’une valeur (Albert et Bernard ne peuvent être en relation qu’une seule fois), alors la règle d’irréductibilité de la clé candidate est enfreinte et l’attribut id_relation doit être dégagé de la clé (et même disparaître de la table, puisqu'il ne sert à rien, et souvenez de mon 2e message : « A noter que si Workbench crée une clé primaire ex nihilo, virez-la, elle fait double emploi. »).
Table Messages : même approche que pour la table Relations.
quand vous dites que la paire {CompteInviteId, CompteRecoitId} est une clef primaire, cela veut-il dire que sur PhpMyAdmin aussi, elles doivent être définies en clef primaire ?
J’ignore tout de ce que vous appelez « PhpMyAdmin » : manifestement on sort du cadre de la logique formelle pour dériver vers autre chose, à caractère sans doute technologique.
je plaçais des INDEX sur les id_expediteur et id_receveur. Même chose pour la table relations.
Est-ce la bonne marche à suivre ou quelque chose m'échappe ?
Les index relèvent carrément du fer à souder. Jusqu’ici, on faisait abstraction du temps et de l’espace. Les index sont là pour permettre d’avoir les meilleurs temps de réponse possibles pour les requêtes. Mais Sahib, ceci est une autre histoire, car vous devrez dresser la liste des requêtes les plus fréquemment utilisées, les plus sensibles. Accessoirement, les SGBD ont tendance à exiger des index pour — ce sont des feignants — garantir les contraintes d’unicité (des clés).
Bon 1er mai...
Partager