MySQL avec des contraintes de suppression douce, de clé Unique et de clé étrangère

Dire que j'ai deux tables, user et comment. Ils ont des définitions de table qui ressemblent à ceci:

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;

c'est génial pour faire respecter l'intégrité des données et tout ça, mais je veux pouvoir "supprimer" un utilisateur et garder tous ses commentaires (pour référence).

a cette fin, j'ai ajouté deleted pour que je puisse SET deleted = 1 sur un disque. Par faire la liste de tout ce deleted = 0 par défaut, je peux cacher tous les enregistrements supprimés jusqu'à ce que j'ai besoin ils.

jusqu'ici tout va bien.

Le problème vient quand:

  • Un utilisateur se connecte avec un nom d'utilisateur (par exemple, "Sam"),
  • je soft-supprimer l'utilisateur (pour des raisons non liées), et
  • Quelqu'un d'autre vient s'inscrire comme Sam, et soudainement nous avons violé la contrainte UNIQUE sur user.

je veux que les utilisateurs puissent éditer leurs propres noms d'utilisateur, donc je ne devrais pas faire username la clé primaire, et nous allons encore ont le même problème lors de la suppression d'utilisateurs.

des idées?

Modifier pour plus de précision: ajouté à la suite de la réponse et des commentaires de RedFilter ci-dessous.

Je m'inquiète du cas où les utilisateurs" supprimés " et les commentaires ne sont pas visibles au public, mais sont seulement des administrateurs visibles, ou sont conservés aux fins du calcul des statistiques.

Cette question est une expérience de pensée, l'utilisateur et le commentaire des tables juste sont des exemples. Encore, username n'était pas le meilleur à utiliser; RedFilter fait des points valables sur l'identité de l'utilisateur, en particulier lorsque les enregistrements sont présentés dans un contexte public.

Concernant les " pourquoi le nom d'utilisateur n'est-il pas la clé principale?": ce n'est qu'un exemple, mais si je l'applique à un problème réel, j'aurai besoin de travailler dans les contraintes d'un système existant qui suppose l'existence d'une clé primaire de substitution.

12
demandé sur Rob Howard 2010-08-16 14:57:07

2 réponses

ajouter une contrainte unique sur les champs (Nom d'utilisateur, supprimé) Changer le type de champ pour "supprimé" en entier.

pendant l'opération de suppression (cela peut être fait dans trigger, ou dans une partie du code où vous devez supprimer l'utilisateur), copiez la valeur du champ id dans le champ supprimé.

Cette approche permettra de vous:

  • conserver des noms uniques pour les utilisateurs actifs (supprimé = 0)
  • permet de supprimer des utilisateurs avec le même nom d'utilisateur plusieurs fois

Zone "Supprimé" ne peut pas avoir seulement 2 valeur parce que le scénario suivant ne fonctionnera pas:

  1. vous créez l'utilisateur 'Sam'
  2. L'utilisateur Sam est supprimé
  3. vous créez un nouvel utilisateur avec le nom D'utilisateur 'Sam'
  4. vous essayez de supprimer l'utilisateur avec le nom d'utilisateur 'Sam' - fail. Vous avez déjà record userName = 'Sam' et deleted = '1'
23
répondu Michael Pakhantsov 2010-08-16 12:22:43

il suffit de garder l'index unique ou une contrainte sur username. Vous ne voulez pas que les nouveaux utilisateurs soient en mesure d'utiliser le nom supprimé, car non seulement il pourrait y avoir une confusion générale sur l'identité, mais si vous montrez toujours les anciens messages de l'utilisateur supprimé, alors ils seront compris par erreur être posté par le nouvel utilisateur avec le même nom.

quand un nouvel utilisateur s'enregistre, vous devriez normalement vérifier pour voir si le nom est en usage avant de permettre l'enregistrement pour compléter, donc il devrait y avoir pas de conflit ici.

.

3
répondu RedFilter 2010-08-25 12:10:15