Вы можете решить это следующим образом:
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)
);
композиционный primary key(comment_id, user_id)
на intersection tablecomments_votes
не позволит пользователям голосовать несколько раз за одни и те же комментарии.
Давайте вставить некоторые данные в приведенной выше схеме:
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');
Теперь давайте добавим несколько голосов для пользователя 1:
INSERT INTO comments_votes VALUES (1, 1, 1);
INSERT INTO comments_votes VALUES (2, 1, 1);
выше означает, что пользователь 1 дал вотум 1-го типа на комментарии 1 и 2.
Если один и тот же пользователь попытается проголосовать еще раз за один из этих комментариев, база данных отклонит его:
INSERT INTO comments_votes VALUES (1, 1, 1);
ERROR 1062 (23000): Duplicate entry '1-1' for key 'PRIMARY'
Если вы будете использовать двигатель InnoDB хранения, он также будет разумно использовать foreign key ограничения на comment_id
и user_id
полей таблицы пересечений. Однако обратите внимание, что MyISAM, двигатель хранения по умолчанию в MySQL, не навязывает ограничения внешнего ключа:
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;
Эти внешние ключи гарантируют, что строка в comments_votes
никогда не будет иметь comment_id
или user_id
значение, которое не существует в comments
и users
таблиц, соответственно. Внешним ключам не требуется иметь рабочую реляционную базу данных, но они, безусловно, необходимы для предотвращения нарушенных отношений и сиротских строк (то есть referential integrity).
На самом деле, ссылочная целостность - это то, что было бы очень сложно обеспечить, если бы вы храпили сериализованные массивы в одно поле базы данных.
Я знаю, что это легкая задача, чтобы предотвратить несколько отзывов от одного пользователя, но мне нужно, чтобы отобразить инвалид иконки для пользователей, которые уже проголосовали на конкретном комментарии и использовать как несколько MySQL запросов. Как я вижу, функция сериализации справится с этой проблемой ... –
Есть ли причина, по которой вы считаете, что будет сложно, если вы будете использовать нормализованный подход? –
@ Даниэль Вассалло Что значит нормализованный подход? –