Możesz rozwiązać ten problem w następujący sposób:
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)
);
Złożony klucz podstawowy
(comment_id, user_id)
w tabeli przecięcia
comments_votes
uniemożliwi użytkownikom wielokrotne głosowanie na te same komentarze.
Wstawmy trochę danych w powyższym schemacie:
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');
Teraz dodajmy trochę głosów dla użytkownika 1:
INSERT INTO comments_votes VALUES (1, 1, 1);
INSERT INTO comments_votes VALUES (2, 1, 1);
Powyższe oznacza, że użytkownik 1 oddał głos typu 1 na komentarze 1 i 2.
Jeśli ten sam użytkownik spróbuje ponownie zagłosować na jeden z tych komentarzy, baza danych go odrzuci:
INSERT INTO comments_votes VALUES (1, 1, 1);
ERROR 1062 (23000): Duplicate entry '1-1' for key 'PRIMARY'
Jeśli będziesz korzystać z InnoDB
silnika pamięci masowej, rozsądnie będzie również użyć klucza obcego
ograniczenia na comment_id
i user_id
pola tabeli przecięć. Należy jednak pamiętać, że MyISAM
, domyślny mechanizm przechowywania w MySQL, nie wymusza ograniczeń kluczy obcych:
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;
Te klucze obce gwarantują, że wiersz w comments_votes
nigdy nie będzie miał comment_id
lub user_id
wartość, która nie istnieje w comments
i users
tabele, odpowiednio. Klucze obce nie są wymagane do posiadania działającej relacyjnej bazy danych, ale są zdecydowanie niezbędne, aby uniknąć zerwania relacji i osieroconych wierszy (np. integralność referencyjna
).
W rzeczywistości integralność referencyjna jest czymś, co byłoby bardzo trudne do wyegzekwowania, gdybyś przechowywał zserializowane tablice w jednym polu bazy danych.