2009-11-07 9 views
0

primaire existante je une table définie comme suit:mysql - Capable de saisir plusieurs valeurs, même si la nouvelle valeur est égale à une clé

CREATE TABLE `mydb`.`users` (
    `userID` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `userName` varchar(100) COLLATE utf8_unicode_ci NOT NULL, 
    `createdDate` datetime NOT NULL, 
    `active` tinyint(1) NOT NULL, 
    `lastUpdatedDate` datetime NOT NULL, 
    PRIMARY KEY (`userID`,`userName`) USING BTREE 
) 

Cependant, quand je lance cette requête:

REPLACE INTO users SET userName ='Joe', active=1, lastUpdatedDate=now() 

il insère plusieurs lignes avec un nom d'utilisateur Joe même s'il s'agit d'une clé primaire. Je pense que parce que userID et userName sont des clés primaires, la clé est seulement quand les deux correspondent. Toutefois, je ne peux pas supprimer la clé primaire sur l'ID utilisateur car mysql renvoie une erreur. Je veux que userName soit distinct de sorte qu'il n'y ait qu'un seul enregistrement pour chaque nom d'utilisateur, et je veux que l'instruction replace mette à jour lastUpdatedDate si le nom d'utilisateur existe déjà (ou insérez-le s'il n'existe pas). Comment puis-je accomplir cela?

Répondre

3

L'ID utilisateur et le nom d'utilisateur corrects constituent la clé primaire. Votre remplacer en crée automatiquement la valeur userID créant ainsi des clés valides uniques

(1,joe) 
(2,joe) 
.... 

Délivrez ce

ALTER TABLE `mydb`.`users` ADD CONSTRAINT UNIQUE uniqueusername (`userName`); 

Ce qui ajoute la contrainte voulue sur votre table. De plus, (userID, userName) étant la clé primaire, la colonne userName ne peut contenir que des valeurs uniques.

Vous pouvez utiliser cette requête et obtenir le comportement souhaité (il met à jour lastUpdatedDate et est actif lorsque le nomUtilisateur existe et insère une nouvelle entrée avec lastUpdatedDate et createdDate défini sur now()).

INSERT INTO `users` (`userName`, `createdDate`, `active`, `lastUpdatedDate`) 
VALUES ('Joe', now(), 1, now()) 
ON DUPLICATE KEY UPDATE `lastUpdatedDate` = now(), active = 1; 
+0

Cela fonctionne maintenant que je n'ai qu'un seul enregistrement pour chaque nom d'utilisateur, mais lorsque j'exécute la commande REPLACE INTO, le champ ID utilisateur est mis à jour. Je veux que cela reste le même quand j'ai inséré l'enregistrement pour la première fois et que j'ai juste changé la valeur lastUpdatedDate. Est-ce que ce n'est pas possible? –

+0

La requête a été modifiée pour ne pas modifier l'ID utilisateur et le paramètre createdDate lorsque les utilisateurs existent, mais uniquement pour mettre à jour lastUpdatedDate et être actifs. Vous devriez être capable d'adopter cette requête pour répondre à vos besoins spécifiques – jitter

1

Vous avez répondu à votre question, je pense - userName n'est pas "une" clé primaire, userName est partie dela clé primaire. Il semble que vous voulez quelque chose comme:

CREATE TABLE `mydb`.`users` (
`userID` int(10) unsigned NOT NULL AUTO_INCREMENT, 
`userName` varchar(100) COLLATE utf8_unicode_ci NOT NULL, 
`createdDate` datetime NOT NULL, 
`active` tinyint(1) NOT NULL, 
`lastUpdatedDate` datetime NOT NULL, 
PRIMARY KEY (`userID`) USING BTREE 
UNIQUE KEY (`userName`) 
) 

(pas de syntaxe cochée)

0

Tout d'abord, vérifiez votre table pour Dupliquons d'id;

select userName 
from users 
group by userName 
having count(*) > 1 

Supprimer les lignes jusqu'à ce qu'il n'y ait pas de doublons. Ensuite, retirez la clé primaire existante:

alter table users drop primary key 

Et recréer la clé primaire que vous souhaitez:

alter table users add primary key (userName) 

Cela devrait fonctionner, car il ne sont plus plusieurs lignes avec le même nom d'utilisateur.

+0

J'ai supprimé toutes les données de la table, mais lorsque je lance la première commande alter pour supprimer la clé primaire, je reçois ce message: ERROR 1075 (42000): Table incorrecte définition; il ne peut y avoir qu'une seule colonne auto et elle doit être définie comme une clé –

+0

Je vois la réponse de Tjofras (http://stackoverflow.com/questions/1691371/mysql-able-to-enter-multiple-values-even-when -new-value-equals-an-existing-prim/1691430 # 1691430) que cela aboutira à un nouvel ID utilisateur. –

+0

@David Buckley: Intéressant. Peut-être que vous pouvez supprimer modifier la colonne id pour supprimer AUTO_INCREMENT en quelque sorte, mais comme vous avez déjà supprimé toutes les données, vous pouvez supprimer et recorriger la table. – Andomar

1
CREATE TABLE `mydb`.`users` (
    `userID` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `userName` varchar(100) COLLATE utf8_unicode_ci NOT NULL, 
    `createdDate` datetime NOT NULL, 
    `active` tinyint(1) NOT NULL, 
    `lastUpdatedDate` datetime NOT NULL, 
    PRIMARY KEY (`userId`) USING BTREE, 
    UNIQUE KEY (`userName`) 
) 

Quelque chose à savoir est que REPLACE supprimera réellement la ligne et en ajoutera une nouvelle. Cela entraînera un nouvel ID utilisateur (en raison de l'AUTO_INCREMENT)

+0

Il n'y a donc aucun moyen de mettre à jour lastUpdateddate sans modifier l'ID utilisateur? –

+0

En fait, il y avait un blog intéressant sur ce que REPLACE fait vraiment .. peut-être pas ce que vous pensez: http://jpipes.com/index.php?/archives/303-The-Deal-with-REPLACE-..- Ou-est-ce-UPDATE.html – Maas

Questions connexes