MySQL с Soft-Deletion, уникальным ключом и ограничениями внешнего ключа - PullRequest
15 голосов
/ 16 августа 2010

Скажем, у меня есть две таблицы, user и comment.У них есть определения таблиц, которые выглядят следующим образом:

CREATE TABLE `user` (
  `id`       INTEGER NOT NULL AUTO_INCREMENT,
  `username` VARCHAR(255) NOT NULL,
  `deleted`  TINYINT(1) NOT NULL DEFAULT 0,
  PRIMARY KEY (`id`),
  UNIQUE KEY (`username`)
) ENGINE=InnoDB;
CREATE TABLE `comment` (
  `id`      INTEGER NOT NULL AUTO_INCREMENT,
  `user_id` INTEGER NOT NULL,
  `comment` TEXT,
  `deleted` TINYINT(1) NOT NULL DEFAULT 0,
  PRIMARY KEY (`id`),
  CONSTRAINT `fk_comment_user_id` FOREIGN KEY (`user_id`)
    REFERENCES `user` (`id`)
    ON DELETE CASCADE
    ON UPDATE CASCADE
) ENGINE=InnoDB;

Это отлично подходит для обеспечения целостности данных и всего такого, но я хочу иметь возможность "удалить" пользователя и сохранить все его комментарии (для справки).

С этой целью я добавил deleted, чтобы я мог SET deleted = 1 в записи.Перечисляя все с помощью deleted = 0 по умолчанию, я могу скрыть все удаленные записи, пока они мне не понадобятся.

Пока все хорошо.

Проблема возникает, когда:

  • Пользователь подписывается с именем пользователя (скажем, "Сэм"),
  • Я удаляю этого пользователя (по несвязанным причинам) и
  • Кто-то другой приходит, чтобы подписатькак Сэм, и вдруг мы нарушили уникальное ограничение на user.

Я хочу, чтобы пользователи могли редактировать свои собственные имена пользователей, поэтому я не должен делать username первичными у нас все еще будет та же проблема при удалении пользователей.

Есть мысли?

Редактировать для уточнения: Добавлено после ответа RedFilter и комментариев ниже.

Я обеспокоен случаем, когда «удаленные» пользователи и комментарии не видны публике, но видны только администраторам или хранятся для целей статистики.

Этот вопросэто мысленный эксперимент, с пользователем и комментарием тв состоянии просто быть примерами.Тем не менее, username не был лучшим для использования;RedFilter делает правильные замечания о личности пользователя, особенно когда записи представлены в открытом контексте.

Относительно " Почему имя пользователя не является первичным ключом? ": это всего лишь пример,но если я применю это к реальной проблеме, мне нужно будет работать в рамках ограничений существующей системы, предполагающей существование суррогатного первичного ключа.

Ответы [ 2 ]

26 голосов
/ 16 августа 2010

Добавить уникальное ограничение на поля (имя пользователя, удалено) Измените тип поля для «удаленных» на INTEGER.

Во время операции удаления (это может быть выполнено в триггере или в части кода, где вам действительно нужно удалить пользователя) скопируйте значение поля id в удаленное поле.

Такой подход позволяет вам:

  • сохранить уникальные имена для активных пользователей (удалено = 0)
  • разрешить удаление пользователей с одним и тем же именем пользователя несколько раз

Поле 'Удалено' не может иметь только 2 значения, потому что следующий сценарий не будет работать:

  1. Вы создаете пользователя 'Sam'
  2. Пользователь Сэм удален
  3. Вы создаете нового пользователя с именем пользователя 'Sam'
  4. Вы пытаетесь удалить пользователя с именем пользователя 'Sam' - не удалось. У вас уже есть запись userName = 'Sam' и удаленный = '1'
4 голосов
/ 16 августа 2010

Просто сохраните уникальный индекс или ограничение на username.Вы не хотите, чтобы новые пользователи могли использовать удаленное имя, поскольку не только может возникать общая путаница с идентификацией, но если вы все еще показываете старые сообщения от удаленного пользователя, то они будут ошибочно восприняты как отправленныеновый пользователь с тем же именем.

Когда новый пользователь регистрируется, вы обычно проверяете, используется ли имя, прежде чем разрешить регистрацию, поэтому здесь не должно быть конфликтов.

.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...