J'ai une table avec une clé primaire qui est un varchar (255). Dans certains cas, 255 caractères ne suffisent pas. J'ai essayé de changer le champ en texte, mais j'obtiens l'erreur suivante:
BLOB/TEXT column 'message_id' used in key specification without a key length
Comment puis-je réparer cela?
edit: je dois également souligner que cette table a une clé primaire composite avec plusieurs colonnes.
UNIQUE
clés?Réponses:
L'erreur se produit car MySQL ne peut indexer que les N premiers caractères d'un BLOB ou d'une
TEXT
colonne. Donc , l'erreur se produit principalement quand il y a un type champ / colonneTEXT
ou blob ou appartiennent à ceuxTEXT
ouBLOB
types tels queTINYBLOB
,MEDIUMBLOB
,LONGBLOB
,TINYTEXT
,MEDIUMTEXT
etLONGTEXT
que vous essayez de faire une clé primaire ou un index. Avec pleineBLOB
ouTEXT
sans valeur de longueur, MySQL n'est pas en mesure de garantir l'unicité de la colonne car elle est de taille variable et dynamique. Ainsi, lors de l'utilisation deBLOB
ou deTEXT
types comme index, la valeur de N doit être fournie afin que MySQL puisse déterminer la longueur de clé. Cependant, MySQL ne prend pas en charge une limite de longueur de clé surTEXT
ouBLOB
.TEXT(88)
ne fonctionnera tout simplement pas.L'erreur s'affichera également lorsque vous tenterez de convertir une colonne de table à partir de
non-TEXT
et denon-BLOB
taper commeVARCHAR
etENUM
versTEXT
ou deBLOB
type, la colonne étant déjà définie en tant que contraintes ou index uniques. La commande Alter Table SQL échouera.La solution au problème consiste à supprimer la colonne
TEXT
ouBLOB
de l'index ou de la contrainte unique ou à définir un autre champ comme clé primaire. Si vous ne pouvez pas le faire et que vous souhaitez placer une limite sur la colonneTEXT
ouBLOB
, essayez d'utiliserVARCHAR
type et placez-y une limite de longueur. Par défaut,VARCHAR
est limité à un maximum de 255 caractères et sa limite doit être spécifiée implicitement dans une parenthèse juste après sa déclaration, c'est-à-direVARCHAR(200)
qu'il la limitera à 200 caractères seulement.Parfois, même si vous ne l' utilisez
TEXT
ou leBLOB
type connexes dans votre table, l'erreur 1170 peut également apparaître. Cela se produit dans une situation telle que lorsque vous spécifiez laVARCHAR
colonne comme clé primaire, mais que vous définissez à tort sa longueur ou la taille des caractères.VARCHAR
ne peut accepter que jusqu'à 256 caractères, donc tout ceVARCHAR(512)
qui forcera MySQL à convertir automatiquement leVARCHAR(512)
en unSMALLTEXT
type de données, qui échoue par la suite avec une erreur 1170 sur la longueur de la clé si la colonne est utilisée comme clé primaire ou index unique ou non unique. Pour résoudre ce problème, spécifiez un chiffre inférieur à 256 comme taille pourVARCHAR
champ.Référence: erreur MySQL 1170 (42000): colonne BLOB / TEXT utilisée dans la spécification de clé sans longueur de clé
la source
Vous devez définir la première partie d'une
TEXT
colonne que vous souhaitez indexer.InnoDB
a une limitation d'768
octets par clé d'index et vous ne pourrez pas créer un index plus long que cela.Cela fonctionnera bien:
Notez que la valeur maximale de la taille de clé dépend du jeu de caractères de la colonne. Ce sont des
767
caractères pour un jeu de caractères à un octet commeLATIN1
et uniquement des255
caractères pourUTF8
(MySQL
uniquement les utilisationsBMP
qui nécessitent au plus3
octets par caractère)Si vous avez besoin que votre colonne entière soit
PRIMARY KEY
, calculezSHA1
ouMD5
hachez et utilisez-la comme aPRIMARY KEY
.la source
REDUNDANT
ouCOMPACT
. Par exemple, vous pouvez atteindre cette limite avec un index de préfixe de colonne de plus de 255 caractères sur une colonneTEXT
orVARCHAR
, en supposant un jeu de caractères utf8mb3 et un maximum de 3 octets pour chaque caractère.REDUNDANT
etCOMPACT
étaient les seuls formats disponibles au moment où cette réponse a été donnée.Vous pouvez spécifier la longueur de clé dans la demande de modification de table, quelque chose comme:
la source
L' indexation d' une valeur MySQL exclut du financement complet de
BLOB
,TEXT
et de longuesVARCHAR
colonnes parce que les données qu'elles contiennent peuvent être énormes, et implicitement l' indice DB sera grand, ce qui signifie aucun avantage de l' indice.MySQL nécessite que vous définissiez les N premiers caractères à indexer, et l'astuce consiste à choisir un nombre N suffisamment long pour donner une bonne sélectivité, mais suffisamment court pour économiser de l'espace. Le préfixe doit être suffisamment long pour rendre l'index presque aussi utile qu'il le serait si vous aviez indexé la colonne entière.
Avant d'aller plus loin, définissons quelques termes importants. La sélectivité d'index est le rapport du total des valeurs indexées distinctes et du nombre total de lignes . Voici un exemple de table de test:
Si nous indexons uniquement le premier caractère (N = 1), la table d'index ressemblera au tableau suivant:
Dans ce cas, la sélectivité de l'indice est égale à IS = 1/3 = 0,33.
Voyons maintenant ce qui se passera si nous augmentons le nombre de caractères indexés à deux (N = 2).
Dans ce scénario, IS = 2/3 = 0,66, ce qui signifie que nous avons augmenté la sélectivité de l'indice, mais nous avons également augmenté la taille de l'indice. L'astuce consiste à trouver le nombre minimal N qui se traduira par une sélectivité d'indice maximale .
Vous pouvez effectuer deux calculs pour votre table de base de données. Je ferai une démonstration sur le vidage de cette base de données .
Disons que nous voulons ajouter la colonne last_name dans les employés de la table à l'index, et nous voulons définir le plus petit nombre N qui produira la meilleure sélectivité d'index.
Identifions d'abord les noms de famille les plus fréquents:
Comme vous pouvez le voir, le nom de famille Baba est le plus fréquent. Nous allons maintenant trouver les préfixes last_name les plus fréquents , en commençant par les préfixes à cinq lettres.
Il y a beaucoup plus d'occurrences de chaque préfixe, ce qui signifie que nous devons augmenter le nombre N jusqu'à ce que les valeurs soient presque les mêmes que dans l'exemple précédent.
Voici les résultats pour N = 9
Voici les résultats pour N = 10.
Ce sont de très bons résultats. Cela signifie que nous pouvons faire l'index sur la colonne
last_name
en n'indexant que les 10 premiers caractères. Dans la colonne de définition de tablelast_name
est définie commeVARCHAR(16)
, et cela signifie que nous avons enregistré 6 octets (ou plus s'il y a des caractères UTF8 dans le nom de famille) par entrée. Dans ce tableau, il y a 1637 valeurs distinctes multipliées par 6 octets soit environ 9 Ko, et imaginez comment ce nombre augmenterait si notre tableau contient des millions de lignes.Vous pouvez lire d'autres façons de calculer le nombre de N dans mes post index préfixés dans MySQL .
la source
J'ai eu cette erreur lors de l'ajout d'un index à une table avec des colonnes de type texte. Vous devez déclarer la taille que vous souhaitez utiliser pour chaque type de texte.
Mettez la taille entre les parenthèses ()
Si trop d'octets sont utilisés, vous pouvez déclarer une taille entre crochets pour varchar pour diminuer la quantité utilisée pour l'indexation. C'est même si vous avez déclaré une taille pour un type déjà comme varchar (1000). Vous n'avez pas besoin de créer une nouvelle table comme d'autres l'ont dit.
Ajout d'index
Ajout d'un index unique
la source
REMARQUE : 767 est le nombre de caractères limite dans lequel MySQL indexera les colonnes tout en traitant les index blob / texte
Réf: http://dev.mysql.com/doc/refman/5.7/en/innodb-restrictions.html
la source
Une autre excellente façon de gérer cela est de créer votre champ TEXT sans la contrainte unique et d'ajouter un champ VARCHAR frère unique qui contient un résumé (MD5, SHA1, etc.) du champ TEXT. Calculez et stockez le résumé sur l'intégralité du champ TEXT lorsque vous insérez ou mettez à jour le champ TEXT, puis vous avez une contrainte d'unicité sur l'ensemble du champ TEXT (plutôt que sur une partie principale) qui peut être recherchée rapidement.
la source
N'ont pas de valeurs longues comme clé primaire. Cela détruira vos performances. Voir le manuel mysql, section 13.6.13 «Réglage et dépannage des performances d'InnoDB».
Au lieu de cela, ayez une clé int de substitution comme primaire (avec auto_increment), et votre clé loong comme UNIQUE secondaire.
la source
Ajoutez une autre colonne varChar (255) (avec par défaut une chaîne vide non nulle) pour maintenir le débordement lorsque 255 caractères ne sont pas suffisants, et modifiez ce PK pour utiliser les deux colonnes. Cependant, cela ne ressemble pas à un schéma de base de données bien conçu, et je recommanderais à un modélisateur de données de regarder ce que vous avez en vue de le refactoriser pour plus de normalisation.
la source
La solution au problème est que dans votre
CREATE TABLE
instruction, vous pouvez ajouter la contrainteUNIQUE ( problemtextfield(300) )
après la colonne créer des définitions pour spécifier unekey
longueur de300
caractères pour unTEXT
champ, par exemple. Ensuite, les premiers300
caractères duproblemtextfield
TEXT
champ devraient être uniques, et toute différence après cela serait ignorée.la source
En outre, si vous souhaitez utiliser l'index dans ce champ, vous devez utiliser le moteur de stockage MyISAM et le type d'index FULLTEXT.
la source
Personne ne l'a mentionné jusqu'à présent ... avec utf8mb4 qui est de 4 octets et peut également stocker des émoticônes (nous ne devrions plus utiliser utf8 de 3 octets) et nous pouvons éviter les erreurs comme
Incorrect string value: \xF0\x9F\x98\...
nous ne devrions pas utiliser VARCHAR typique (255) mais plutôt VARCHAR ( 191) car dans le cas où utf8mb4 et VARCHAR (255), la même partie des données est stockée hors page et vous ne pouvez pas créer d'index pour la colonne VARCHAR (255) mais pour VARCHAR (191) vous pouvez. C'est parce que la taille de colonne indexée maximale est de 767 octets pour ROW_FORMAT = COMPACT ou ROW_FORMAT = REDUNDANT.Pour les nouveaux formats de ligne ROW_FORMAT = DYNAMIC ou ROW_FORMAT = COMPRESSED (qui nécessite un format de fichier plus récent innodb_file_format = Barracuda antilope pas plus ancien), la taille de colonne indexée maximale est de 3072. Elle est disponible depuis MySQL> = 5.6.3 lorsque innodb_large_prefix = 1 (désactivé par défaut pour MySQL <= 5.7.6 et activé par défaut pour MySQL> = 5.7.7). Donc, dans ce cas, nous pouvons utiliser VARCHAR (768) pour utf8mb4 (ou VARCHAR (1024) pour l'ancien utf8) pour la colonne indexée. L'option innodb_large_prefix est déconseillée depuis 5.7.7 car son comportement est intégré à MySQL 8 (dans cette version, l'option est supprimée).
la source
Vous devez changer le type de colonne en
varchar
ouinteger
pour l'indexation.la source
Allez dans mysql
edit table
-> changez le type de colonne envarchar(45)
.la source
Utilisez comme ça
la source