Dire que l'utilisation de "Composite keys as PRIMARY KEY is bad practice"
est totalement absurde!
Les composites PRIMARY KEY
sont souvent une très bonne chose et la seule façon de modéliser des situations naturelles qui se produisent dans la vie de tous les jours!
Pensez à l'exemple classique d'enseignement des bases de données des étudiants et des cours et aux nombreux cours suivis par de nombreux étudiants!
Créer un cours de tables et étudiant:
CREATE TABLE course
(
course_id SERIAL,
course_year SMALLINT NOT NULL,
course_name VARCHAR (100) NOT NULL,
CONSTRAINT course_pk PRIMARY KEY (course_id)
);
CREATE TABLE student
(
student_id SERIAL,
student_name VARCHAR (50),
CONSTRAINT student_pk PRIMARY KEY (student_id)
);
Je vais vous donner l'exemple dans le dialecte PostgreSQL (et MySQL ) - devrait fonctionner pour n'importe quel serveur avec un peu de peaufinage.
Maintenant, vous voulez évidemment savoir quel étudiant suit quel cours - vous avez donc ce qu'on appelle un joining table
(aussi appelé linking
, many-to-many
ou m-to-n
tables). Ils sont aussi connus comme associative entities
dans un jargon plus technique!
1 cours peut avoir de nombreux étudiants.
1 étudiant peut suivre de nombreux cours.
Donc, vous créez une table de jonction
CREATE TABLE course_student
(
cs_course_id INTEGER NOT NULL,
cs_student_id INTEGER NOT NULL,
-- now for FK constraints - have to ensure that the student
-- actually exists, ditto for the course.
CREATE CONSTRAINT cs_course_fk FOREIGN KEY (cs_course_id) REFERENCES course (course_id),
CREATE CONSTRAINT cs_student_fk FOREIGN KEY (cs_student_id) REFERENCES student (student_id)
);
Maintenant, la seule façon de donner un sens à cette table PRIMARY KEY
est d'en faire KEY
une combinaison de cours et d'étudiant. De cette façon, vous ne pouvez pas obtenir:
un double de la combinaison étudiant / cours
un cours ne peut avoir le même étudiant inscrit qu'une seule fois, et
un étudiant ne peut s'inscrire au même cours qu'une seule fois
vous avez également une recherche prête à l'emploi KEY
sur le cours par étudiant - AKA un index de couverture ,
il est trivial de trouver des cours sans étudiants et sans étudiants!
- L' exemple db-fiddle a la contrainte PK repliée dans la CREATE TABLE - Cela peut être fait dans les deux sens. Je préfère avoir tout dans l'instruction CREATE TABLE.
ALTER TABLE course_student
ADD CONSTRAINT course_student_pk
PRIMARY KEY (cs_course_id, cs_student_id);
Maintenant, vous pourriez, si vous trouviez que les recherches d'étudiants par cours étaient lentes, utiliser un UNIQUE INDEX
on (sc_student_id, sc_course_id).
ALTER TABLE course_student
ADD CONSTRAINT course_student_sc_uq
UNIQUE (cs_student_id, cs_course_id);
Il n'y a pas de solution miracle pour l' ajout d' index - ils vont faire INSERT
l et UPDATE
est plus lent, mais au grand avantage de énormement décroissanteSELECT
fois! C'est au développeur de décider d'indexer en fonction de ses connaissances et de son expérience, mais dire que les composites PRIMARY KEY
sont toujours mauvais est tout simplement faux.
Dans le cas de joindre des tables, ce sont généralement les seules PRIMARY KEY
qui ont du sens! Rejoindre des tables est aussi très souvent le seul moyen de modéliser ce qui se passe en entreprise ou dans la nature ou dans pratiquement tous les domaines auxquels je peux penser!
Ce PK est également utilisé comme un covering index
qui peut aider à accélérer les recherches. Dans ce cas, il serait particulièrement utile de rechercher régulièrement (course_id, student_id) ce qui, on pourrait l'imaginer, peut souvent être le cas!
Ceci est juste un petit exemple où un composite PRIMARY KEY
peut être une très bonne idée, et la seule façon sensée de modéliser la réalité! Du haut de ma tête, je peux penser à beaucoup d' autres.
Un exemple de mon propre travail!
Considérez une table de vol contenant un flight_id, une liste des aéroports de départ et d'arrivée et les heures pertinentes, puis aussi une table de cabine avec des membres d'équipage!
La seule façon raisonnable de modéliser cela est d'avoir une table flight_crew avec les attributs flight_id et crew_id et la seule raison PRIMARY KEY
est d'utiliser la clé composite des deux champs!