J'utilise MySQL 5.1.56, MyISAM. Ma table ressemble à ceci:
CREATE TABLE IF NOT EXISTS `my_table` (
`number` int(11) NOT NULL,
`name` varchar(50) NOT NULL,
`money` int(11) NOT NULL,
PRIMARY KEY (`number`,`name`)
) ENGINE=MyISAM;
Il contient ces deux lignes:
INSERT INTO `my_table` (`number`, `name`, `money`) VALUES
(1, 'S. Name', 150), (2, 'Another Name', 284);
J'essaie maintenant d'insérer une autre ligne:
INSERT INTO `my_table` (`number`, `name`, `money`) VALUES
(2, 'S. Name', 240);
Et MySQL ne l'insère pas en me disant ceci:
#1062 - Duplicate entry '2-S. Name' for key 'PRIMARY'
Je ne comprends vraiment pas. La clé primaire se trouve sur les deux premières colonnes (les deux), donc la ligne que je tente d'insérer est une clé primaire unique, n'est-ce pas?
J'ai essayé de réparer la table, j'ai essayé d'optimiser la table, tout en vain. Veuillez également noter que je ne peux pas passer de MyISAM à InnoDB.
Est-ce que je manque quelque chose ou est-ce un bogue de MySQL ou MyISAM? Merci.
Pour résumer et souligner le problème (même s’il ne devrait pas en être ainsi), selon moi: La table a une clé primaire sur deux colonnes. J'essaie d'insérer une ligne avec une nouvelle combinaison de valeurs dans ces deux colonnes, mais la valeur dans la première colonne est déjà dans une ligne et la valeur dans la deuxième colonne est déjà dans une autre ligne. Mais ils ne sont combinés nulle part. Je pense donc que cela est censé fonctionner et que je suis très confus de voir que cela ne fonctionne pas.
Votre code et votre schéma sont corrects. Vous essayez probablement sur la version précédente de la table.
http://sqlfiddle.com/#!2/9dc64/1/0
Votre table n'a même pas d'UNIQUE, de sorte que l'erreur est impossible sur cette table.
Sauvegardez les données de cette table, supprimez-les et recréez.
Peut-être avez-vous essayé d'exécuter ce CREATE TABLE IF NOT EXIST
. Il n'a pas été créé, vous avez l'ancienne version, mais il n'y a pas eu d'erreur à cause de IF NOT EXIST
.
Vous pouvez exécuter SQL comme ceci pour voir la structure actuelle de la table:
DESCRIBE my_table;
Edit - ajouté plus tard:
Essayez de lancer ceci:
DROP TABLE `my_table`; --make backup - it deletes table
CREATE TABLE `my_table` (
`number` int(11) NOT NULL,
`name` varchar(50) NOT NULL,
`money` int(11) NOT NULL,
PRIMARY KEY (`number`,`name`),
UNIQUE (`number`, `name`) --added unique on 2 rows
) ENGINE=MyISAM;
Je sais que ce n'était pas le problème dans ce cas, mais j'avais un problème similaire de "Entrée en double" lors de la création d'une clé primaire composite:
ALTER TABLE table ADD PRIMARY KEY(fieldA,fieldB);
L'erreur était quelque chose comme:
#1062 Duplicate entry 'valueA-valueB' for key 'PRIMARY'
Alors j'ai cherché:
select * from table where fieldA='valueA' and fieldB='valueB'
Et la sortie ne montre qu’une rangée, pas de duplication!
Après un certain temps, j'ai découvert que si vous avez des valeurs NULL dans ces champs, vous recevez ces erreurs. En fin de compte, le message d'erreur m'a en quelque sorte induit en erreur.
Dans mon cas, l'erreur était due au schéma obsolète. L'une des colonnes était à l'origine varchar(50)
, mais le vidage que j'essayais d'importer a été créé à partir d'une version modifiée du schéma qui a varchar(70)
pour cette colonne utilisant plus de 50 caractères).
Au cours de l'importation, certaines clés ont été tronquées et la version tronquée n'était plus unique. J'ai mis du temps à comprendre ça, j'étais comme "mais cette clé supposée dupliquée n'existe même pas!".
Votre code fonctionne bien sur cette démo:
Je pense que vous faites la deuxième requête (insérer ...) deux fois. Essayer
select * from my_table
avant d'insérer une nouvelle ligne et vous obtiendrez que vos données existent déjà ou non.
Au cas où cela aiderait quelqu'un d'autre que l'OP, j'avais un problème similaire avec InnoDB .
Pour moi, ce qui se passait réellement était un échec de contrainte de clé étrangère. Je faisais référence à une clé étrangère qui n'existait pas.
En d'autres termes, l'erreur était complètement éteinte. La clé primaire était correcte et l'insertion de la clé étrangère a d'abord résolu le problème. Aucune idée pourquoi MySQL s'est trompé soudainement.
Ce problème est souvent créé lors de l'ajout d'une colonne ou de l'utilisation d'une colonne existante en tant que clé primaire. Il n'est pas créé en raison d'une clé primaire existante qui n'a jamais été créée ou en raison d'un dommage à la table.
En réalité, l'erreur indique qu'une valeur de clé en attente est vide.
La solution consiste à renseigner la colonne avec des valeurs uniques, puis à recréer la clé primaire. Il ne peut y avoir aucune valeur vide, nulle ou en double, sinon cette erreur trompeuse apparaîtra.
Essayez avec incrémentation automatique:
CREATE TABLE IF NOT EXISTS `my_table` (
`number` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`money` int(11) NOT NULL,
PRIMARY KEY (`number`,`name`)
) ENGINE=MyISAM;
Si quelqu'un d'autre trouve ce fil avec mon problème, j'utilisais un type de colonne "entier" dans MySQL. La ligne que j'essayais d'insérer avait une clé primaire avec une valeur supérieure à celle autorisée par un entier. Le passage à "bigint" a résolu le problème.
Dans mon cas, l'erreur était très trompeuse. Le problème était que PHPMyAdmin utilise "ALTER TABLE" lorsque vous cliquez sur le bouton "Créer un unique" au lieu de "ALTER IGNORE TABLE", je devais donc le faire manuellement, comme dans:
ALTER TABLE mytbl ADD UNIQUE (columnName);
je viens d'essayer, et si vous avez des données et une table de récréation ne fonctionnerait pas, changez simplement de table en InnoDB et essayez encore, cela résoudrait le problème
Selon votre code, votre "numéro" et votre "nom" sont des clés primaires et vous insérez S.NAME dans les deux lignes, ce qui créera un conflit. Nous utilisons une clé primaire pour accéder à des données complètes. Ici, vous ne pouvez pas accéder aux données en utilisant la clé primaire 'nom'.
im un débutant et je pense que cela pourrait être l'erreur.