Tengo una tabla con una clave primaria que es un varchar (255). Han surgido algunos casos en los que 255 caracteres no son suficientes. Intenté cambiar el campo a un texto, pero aparece el siguiente error:
BLOB/TEXT column 'message_id' used in key specification without a key length
¿Cómo puedo arreglar esto?
editar: también debo señalar que esta tabla tiene una clave primaria compuesta con múltiples columnas.
mysql
sql
mysql-error-1170
GSto
fuente
fuente
UNIQUE
claves?Respuestas:
El error ocurre porque MySQL puede indexar solo los primeros N caracteres de un BLOB o
TEXT
columna. Por lo que el error se produce principalmente cuando hay un tipo de campo / columna deTEXT
o BLOB o los que pertenecen aTEXT
, oBLOB
tipos, tales comoTINYBLOB
,MEDIUMBLOB
,LONGBLOB
,TINYTEXT
,MEDIUMTEXT
, yLONGTEXT
que trate de hacer que una clave principal o un índice. Con el valor de longitud completoBLOB
oTEXT
sin él, MySQL no puede garantizar la unicidad de la columna, ya que tiene un tamaño variable y dinámico. Por lo tanto, cuando se utilizanBLOB
o losTEXT
tipos como índice, se debe proporcionar el valor de N para que MySQL pueda determinar la longitud de la clave. Sin embargo, MySQL no admite un límite de longitud de clave enTEXT
oBLOB
.TEXT(88)
Simplemente no funcionará.El error también aparecerá cuando intente convertir una columna de la tabla
non-TEXT
ynon-BLOB
escribir, comoVARCHAR
yENUM
enTEXT
oBLOB
escribir, con la columna ya definida como restricciones o índice únicos. El comando Alter Table SQL fallará.La solución al problema es eliminar la columna
TEXT
oBLOB
del índice o la restricción única o establecer otro campo como clave principal. Si no puede hacer eso y desea colocar un límite en la columnaTEXT
oBLOB
, intente usarVARCHAR
type y coloque un límite de longitud en él. Por defecto,VARCHAR
está limitado a un máximo de 255 caracteres y su límite debe especificarse implícitamente dentro de un paréntesis justo después de su declaración, es decir,VARCHAR(200)
lo limitará a 200 caracteres solamente.A veces, a pesar de que no se utilicen
TEXT
oBLOB
tipo relacionado en la tabla, el error 1170 puede también aparecer. Ocurre en una situación como cuando especifica unaVARCHAR
columna como clave principal, pero establece incorrectamente su longitud o tamaño de caracteres.VARCHAR
solo puede aceptar hasta 256 caracteres, por lo que cualquier cosa comoVARCHAR(512)
forzará a MySQL a convertir automáticamenteVARCHAR(512)
a unSMALLTEXT
tipo de datos, que posteriormente falla con el error 1170 en la longitud de la clave si la columna se usa como clave primaria o índice único o no único. Para resolver este problema, especifique una cifra menor que 256 como el tamaño delVARCHAR
campo.Referencia: MySQL Error 1170 (42000): columna BLOB / TEXT utilizada en la especificación de clave sin una longitud de clave
fuente
Debe definir qué parte inicial de una
TEXT
columna desea indexar.InnoDB
tiene una limitación de768
bytes por clave de índice y no podrá crear un índice por más tiempo.Esto funcionará bien:
Tenga en cuenta que el valor máximo del tamaño de la clave depende del conjunto de caracteres de la columna. Son
767
caracteres para un conjunto de caracteres de un solo byteLATIN1
y solo255
caracteres paraUTF8
(MySQL
solo usosBMP
que requieren como máximo3
bytes por carácter)Si necesita que toda su columna sea
PRIMARY KEY
, calculeSHA1
oMD5
haga hash y úsela como aPRIMARY KEY
.fuente
REDUNDANT
oCOMPACT
. Por ejemplo, puede alcanzar este límite con un índice de prefijo de columna de más de 255 caracteres en una columnaTEXT
oVARCHAR
, suponiendo un conjunto de caracteres utf8mb3 y el máximo de 3 bytes para cada carácter.REDUNDANT
yCOMPACT
eran los únicos formatos disponibles en el momento en que se dio esta respuesta.Puede especificar la longitud de la clave en la solicitud de alterar tabla, algo así como:
fuente
Deshabilita MySQL indexación de un valor total de
BLOB
,TEXT
y las largasVARCHAR
columnas porque los datos que contienen pueden ser enormes, e implícitamente índice DB serán grandes, es decir, ningún beneficio de índice.MySQL requiere que defina los primeros N caracteres a indexar, y el truco consiste en elegir un número N que sea lo suficientemente largo como para proporcionar una buena selectividad, pero lo suficientemente corto como para ahorrar espacio. El prefijo debe ser lo suficientemente largo como para que el índice sea casi tan útil como lo sería si indexara toda la columna.
Antes de continuar, definamos algunos términos importantes. La selectividad del índice es la relación del total de valores indexados distintos y el número total de filas . Aquí hay un ejemplo para la tabla de prueba:
Si indexamos solo el primer carácter (N = 1), la tabla de índice se verá como la siguiente tabla:
En este caso, la selectividad del índice es igual a IS = 1/3 = 0.33.
Veamos ahora qué sucederá si aumentamos el número de caracteres indexados a dos (N = 2).
En este escenario IS = 2/3 = 0.66, lo que significa que aumentamos la selectividad del índice, pero también hemos aumentado el tamaño del índice. El truco consiste en encontrar el número mínimo N que dará como resultado una selectividad de índice máxima .
Hay dos enfoques que puede hacer cálculos para su tabla de base de datos. Haré una demostración en el volcado de esta base de datos .
Supongamos que queremos agregar la columna last_name en los empleados de la tabla al índice, y queremos definir el número N más pequeño que produzca la mejor selectividad del índice.
Primero identifiquemos los apellidos más frecuentes:
Como puede ver, el apellido Baba es el más frecuente. Ahora vamos a encontrar los prefijos de apellido más frecuentes , comenzando con los prefijos de cinco letras.
Hay muchos más casos de cada prefijo, lo que significa que tenemos que aumentar el número N hasta que los valores sean casi los mismos que en el ejemplo anterior.
Aquí están los resultados para N = 9
Aquí están los resultados para N = 10.
Estos son muy buenos resultados. Esto significa que podemos hacer que el índice en la columna indexe
last_name
solo los primeros 10 caracteres. En la tabla, la columna de definiciónlast_name
se define comoVARCHAR(16)
, y esto significa que hemos guardado 6 bytes (o más si hay caracteres UTF8 en el apellido) por entrada. En esta tabla hay 1637 valores distintos multiplicados por 6 bytes que son aproximadamente 9 KB, e imagine cómo crecería este número si nuestra tabla contiene millones de filas.Puede leer otras formas de calcular el número de N en mis índices indexados en MySQL .
fuente
Recibí este error al agregar un índice a una tabla con columnas de tipo de texto. Debe declarar la cantidad de tamaño que desea usar para cada tipo de texto.
Ponga la cantidad del tamaño dentro del paréntesis ()
Si se usan demasiados bytes, puede declarar un tamaño entre paréntesis para varchar para disminuir la cantidad utilizada para la indexación. Esto es incluso si declaró un tamaño para un tipo que ya es varchar (1000). No necesita crear una nueva tabla como han dicho otros.
Agregando índice
Agregar índice único
fuente
NOTA : 767 es el límite de número de caracteres hasta el cual MySQL indexará columnas mientras se trata de índices de blob / texto
Ref: http://dev.mysql.com/doc/refman/5.7/en/innodb-restrictions.html
fuente
Otra excelente manera de lidiar con esto es crear su campo TEXT sin la restricción única y agregar un campo hermano VARCHAR que sea único y contenga un resumen (MD5, SHA1, etc.) del campo TEXT. Calcule y almacene el resumen sobre todo el campo TEXTO cuando inserte o actualice el campo TEXTO, entonces tiene una restricción de unicidad sobre todo el campo TEXTO (en lugar de una parte inicial) que se puede buscar rápidamente.
fuente
No tiene valores largos como clave principal. Eso destruirá tu desempeño. Consulte el manual de mysql, sección 13.6.13 'Ajuste y resolución de problemas de InnoDB'.
En su lugar, tenga una clave int sustituta como primaria (con auto_increment) y su clave loong como UNIQUE secundaria.
fuente
Agregue otra columna varChar (255) (con el valor predeterminado como cadena vacía no nula) para contener el desbordamiento cuando 255 caracteres no son suficientes, y cambie esta PK para usar ambas columnas. Sin embargo, esto no parece un esquema de base de datos bien diseñado, y recomendaría obtener un modelador de datos para ver lo que tiene con el objetivo de refactorizarlo para una mayor Normalización.
fuente
La solución al problema es que en su
CREATE TABLE
declaración, puede agregar la restricciónUNIQUE ( problemtextfield(300) )
después de que la columna cree definiciones para especificar unakey
longitud de300
caracteres para unTEXT
campo, por ejemplo. Entonces, los primeros300
caracteres delproblemtextfield
TEXT
campo tendrían que ser únicos y no se tendrían en cuenta las diferencias posteriores.fuente
Además, si desea usar el índice en este campo, debe usar el motor de almacenamiento MyISAM y el tipo de índice FULLTEXT.
fuente
Nadie lo mencionó hasta ahora ... con utf8mb4, que es de 4 bytes y también puede almacenar emoticones (nunca más deberíamos usar utf8 de 3 bytes) y podemos evitar errores como
Incorrect string value: \xF0\x9F\x98\...
no deberíamos usar VARCHAR típico (255) sino VARCHAR ( 191) porque en caso de que utf8mb4 y VARCHAR (255) la misma parte de los datos se almacene fuera de la página y no puede crear el índice para la columna VARCHAR (255), pero sí para VARCHAR (191). Esto se debe a que el tamaño máximo de la columna indexada es de 767 bytes para ROW_FORMAT = COMPACT o ROW_FORMAT = REDUNDANT.Para los formatos de fila más nuevos ROW_FORMAT = DYNAMIC o ROW_FORMAT = COMPRESSED (que requiere un formato de archivo más nuevo innodb_file_format = Barracuda no es un antílope más antiguo) el tamaño máximo de la columna indexada es 3072. Está disponible desde MySQL> = 5.6.3 cuando innodb_large_prefix = 1 (deshabilitado por defecto para MySQL <= 5.7.6 y habilitado por defecto para MySQL> = 5.7.7). Entonces, en este caso, podemos usar VARCHAR (768) para utf8mb4 (o VARCHAR (1024) para el antiguo utf8) para la columna indexada. La opción innodb_large_prefix está en desuso desde 5.7.7 porque su comportamiento está incorporado en MySQL 8 (en esta versión se elimina la opción).
fuente
Usted tiene que cambiar el tipo de columna para
varchar
ointeger
para la indexación.fuente
Vaya a mysql
edit table
-> cambie el tipo de columna avarchar(45)
.fuente
Usar así
fuente