Vous voudrez peut-être résoudre ce problème comme suit :
CREATE TABLE comments (
comment_id int,
body varchar(100),
PRIMARY KEY (comment_id)
);
CREATE TABLE users (
user_id int,
username varchar(20),
PRIMARY KEY (user_id)
);
CREATE TABLE comments_votes (
comment_id int,
user_id int,
vote_type int,
PRIMARY KEY (comment_id, user_id)
);
La clé primaire
composée (comment_id, user_id)
sur la table d'intersection
comments_votes
empêchera les utilisateurs de voter plusieurs fois sur les mêmes commentaires.
Insérons quelques données dans le schéma ci-dessus :
INSERT INTO comments VALUES (1, 'first comment');
INSERT INTO comments VALUES (2, 'second comment');
INSERT INTO comments VALUES (3, 'third comment');
INSERT INTO users VALUES (1, 'user_a');
INSERT INTO users VALUES (2, 'user_b');
INSERT INTO users VALUES (3, 'user_c');
Ajoutons maintenant quelques votes pour l'utilisateur 1 :
INSERT INTO comments_votes VALUES (1, 1, 1);
INSERT INTO comments_votes VALUES (2, 1, 1);
Ce qui précède signifie que l'utilisateur 1 a donné un vote de type 1 sur les commentaires 1 et 2.
Si le même utilisateur essaie de voter à nouveau sur l'un de ces commentaires, la base de données le rejettera :
INSERT INTO comments_votes VALUES (1, 1, 1);
ERROR 1062 (23000): Duplicate entry '1-1' for key 'PRIMARY'
Si vous utilisez InnoDB
moteur de stockage, il sera également judicieux d'utiliser la clé étrangère
contraintes sur le comment_id
et user_id
champs de la table de croisement. Cependant, notez que MyISAM
, le moteur de stockage par défaut de MySQL, n'impose pas de contraintes de clé étrangère :
CREATE TABLE comments (
comment_id int,
body varchar(100),
PRIMARY KEY (comment_id)
) ENGINE=INNODB;
CREATE TABLE users (
user_id int,
username varchar(20),
PRIMARY KEY (user_id)
) ENGINE=INNODB;
CREATE TABLE comments_votes (
comment_id int,
user_id int,
vote_type int,
PRIMARY KEY (comment_id, user_id),
FOREIGN KEY (comment_id) REFERENCES comments (comment_id),
FOREIGN KEY (user_id) REFERENCES users (user_id)
) ENGINE=INNODB;
Ces clés étrangères garantissent qu'une ligne dans comments_votes
n'aura jamais de comment_id
ou user_id
valeur qui n'existe pas dans les comments
et users
tableaux, respectivement. Les clés étrangères ne sont pas nécessaires pour avoir une base de données relationnelle fonctionnelle, mais elles sont absolument essentielles pour éviter les relations rompues et les lignes orphelines (c'est-à-dire intégrité référentielle
).
En fait, l'intégrité référentielle est quelque chose qui aurait été très difficile à appliquer si vous deviez stocker des tableaux sérialisés dans un seul champ de base de données.