#1071-La clave especificada era demasiado larga; la longitud máxima de la clave es de 767 bytes


Cuando ejecuté el siguiente comando:

ALTER TABLE `mytable` ADD UNIQUE (
`column1` ,
`column2`
);

Recibí este mensaje de error:

#1071 - Specified key was too long; max key length is 767 bytes

Información sobre column1 y column2:

column1 varchar(20) utf8_general_ci
column2  varchar(500) utf8_general_ci

Creo que varchar(20) solo requiere 21 bytes mientras que varchar(500) solo requiere 501 bytes. Así que el total de bytes son 522, menos de 767. Entonces, ¿por qué recibí el mensaje de error?

#1071 - Specified key was too long; max key length is 767 bytes
Author: OMG Ponies, 2009-11-29

27 answers

767 bytes es la limitación de prefijo indicada para las tablas InnoDB en MySQL versión 5.6 (y versiones anteriores). Es 1.000 bytes de largo para las tablas de MyISAM. En MySQL versión 5.7 y superior este límite se ha aumentado a 3072 bytes.

También debe tener en cuenta que si establece un índice en un campo char o varchar grande codificado en utf8mb4, debe dividir la longitud máxima del prefijo del índice de 767 bytes (o 3072 bytes) por 4, lo que resulta en 191. Esto se debe a la longitud máxima de un el carácter utf8mb4 es de cuatro bytes. Para un carácter utf8 sería de tres bytes dando como resultado una longitud máxima del prefijo del índice de 254.

Una opción que tiene es simplemente colocar un límite inferior en sus campos VARCHAR.

Otra opción (de acuerdo con la respuesta a este problema) es obtener el subconjunto de la columna en lugar de la cantidad completa, es decir:

ALTER TABLE `mytable` ADD UNIQUE ( column1(15), column2(200) );

Retoque ya que necesita obtener la clave para aplicar, pero me pregunto si valdría la pena revisar su modelo de datos con respecto a esto entidad para ver si hay mejoras que le permitan implementar las reglas de negocio previstas sin golpear la limitación de MySQL.

 312
Author: OMG Ponies,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-11 10:45:11

Si alguien tiene problemas con INNODB / Utf-8 tratando de poner un índice UNIQUE en un campo VARCHAR(256), cámbielo a VARCHAR(255). Parece que 255 es la limitación.

 356
Author: PinkTurtle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-29 17:19:13

Cuando llegas al límite. Establezca lo siguiente.

  • INNODB utf8 VARCHAR(255)
  • INNODB utf8mb4 VARCHAR(191)
 215
Author: Aley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-17 11:12:49

MySQL asume el peor caso para el número de bytes por carácter en la cadena. Para la codificación 'utf8' de MySQL, son 3 bytes por carácter ya que esa codificación no permite caracteres más allá de U+FFFF. Para la codificación MySQL 'utf8mb4', es de 4 bytes por carácter, ya que eso es lo que MySQL llama UTF-8 real.

Así que asumiendo que estás usando 'utf8', tu primera columna tomará 60 bytes del índice, y tu segunda otros 1500.

 143
Author: morganwahl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-22 18:15:40

Ejecute esta consulta antes de su consulta:

SET @@global.innodb_large_prefix = 1;

Esto aumentará el límite a 3072 bytes.

 38
Author: Raza Ahmed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-04 20:12:23

¿Qué codificación de caracteres está utilizando? Algunos conjuntos de caracteres (como UTF-16, etc.) usan más de un byte por carácter.

 37
Author: Amber,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-11-29 03:21:27

Solución Para Laravel Framework

Según Laravel 5.4.* documentación ; Debe establecer la longitud de cadena predeterminada dentro del

Boot

Método de

App / Providers / AppServiceProvider.php

Archive como sigue:

use Illuminate\Support\Facades\Schema;

public function boot() 
{
    Schema::defaultStringLength(191); 
}

Explicación de esta corrección, dada por Laravel 5.4.* documentación;

Laravel utiliza el conjunto de caracteres utf8mb4 de forma predeterminada, que incluye soporte para almacenar "emojis" en la base de datos. Si está ejecutando una versión de MySQL anterior a la versión 5.7.7 o MariaDB anterior a la versión 10.2.2, es posible que deba configurar manualmente la longitud de cadena predeterminada generada por las migraciones para que MySQL cree índices para ellas. Puede configurar esto llamando al método Schema:: defaultStringLength dentro de su AppServiceProvider

Alternativamente, puede habilitar la opción innodb_large_prefix para su base. Consulte la documentación de su base de datos para obtener instrucciones sobre cómo activar correctamente esta opción.

 23
Author: alishaukat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-11 15:06:47

Creo que varchar(20) solo requiere 21 bytes mientras que varchar(500) solo requiere 501 bytes. Así que el total de bytes son 522, menos de 767. Entonces por qué ¿recibí el mensaje de error?

UTF8 requiere de 3 bytes por carácter para almacenar la cadena, por lo que en su caso 20 + 500 caracteres = 20*3+500*3 = 1560 bytes que es más de permitido 767 bytes.

El límite para UTF8 es 767/3 = 255 caracteres , para UTF8mb4 que usa 4 bytes por carácter es 767/4 = 191 caracteres.


Hay dos soluciones a este problema si necesita usar una columna más larga que el límite:

  1. Use codificación" más barata " (la que requiere menos bytes por carácter)
    En mi caso, necesitaba agregar un índice único en la columna que contiene la cadena SEO del artículo, ya que solo uso [A-z0-9\-] caracteres para SEO, usé latin1_general_ci que usa solo un byte por carácter y por lo tanto la columna puede tener una longitud de 767 bytes.
  2. Crea hash a partir de tu columna y usa un índice único solo en ese
    La otra opción para mí era crear otra columna que almacenaría hash de SEO, esta columna tendría UNIQUE clave para garantizar que los valores de SEO sean únicos. También agregaría KEY index a la columna SEO original para acelerar la búsqueda.
 21
Author: Buksy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-23 09:19:59
Specified key was too long; max key length is 767 bytes

Recibiste ese mensaje porque 1 byte es igual a 1 carácter solo si usas el conjunto de caracteres latin-1. Si utiliza utf8, cada carácter se considerará 3 bytes al definir su columna clave. Si utiliza utf8mb4, cada carácter se considerará como 4 bytes al definir su columna clave. Por lo tanto, necesita multiplicar el límite de caracteres de su campo clave por, 1, 3 o 4 (en mi ejemplo) para determinar el número de bytes que el campo clave está tratando de permitir. Si está utilizando uft8mb4, solo puede defina 191 caracteres para un campo de clave primaria InnoDB nativo. Simplemente no infrinja 767 bytes.

 17
Author: Anthony Rutledge,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-21 15:42:53

Podría agregar una columna del md5 de columnas largas

 15
Author: diyism,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-25 04:18:34

La respuesta sobre por qué recibe el mensaje de error ya fue respondida por muchos usuarios aquí. Mi respuesta es sobre cómo arreglarlo y usarlo como sea.

Consulte desde este enlace.

  1. Abra el cliente MySQL (o el cliente MariaDB). Es una herramienta de línea de comandos.
  2. Le preguntará su contraseña, ingrese su contraseña correcta.
  3. Seleccione su base de datos usando este comando use my_database_name;

Base de datos cambiada

  1. set global innodb_large_prefix=on;

Consulta OK, 0 filas afectadas (0.00 seg)

  1. set global innodb_file_format=Barracuda;

Consulta OK, 0 filas afectadas (0.02 seg)

  1. Vaya a su base de datos en phpMyAdmin o algo así para una fácil administración. > Seleccionar base de datos > Ver tabla estructura > Vaya a la pestaña Operaciones. > Cambie ROW_FORMAT a DYNAMIC y guarde los cambios.
  2. Vaya a la pestaña estructura de la tabla > Haga clic en Único botón.
  3. Hecho. Ahora debería no tener errores.

El problema de esta solución es si exporta la base de datos a otro servidor (por ejemplo, de localhost a host real) y no puede usar la línea de comandos MySQL en ese servidor. No puedes hacer que funcione allí.

 13
Author: vee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-07 11:12:44

Encontramos este problema al intentar agregar un índice ÚNICO a un campo VARCHAR(255) usando utf8mb4. Si bien el problema ya se describe bien aquí, quería agregar algunos consejos prácticos sobre cómo lo resolvimos y resolvimos.

Cuando se usa utf8mb4, los caracteres cuentan como 4 bytes, mientras que bajo utf8, podrían como 3 bytes. Las bases de datos InnoDB tienen un límite que los índices solo pueden contener 767 bytes. Por lo tanto, al usar utf8, puede almacenar 255 caracteres (767/3 = 255), pero al usar utf8mb4, solo puede almacenar 191 caracteres (767/4 = 191).

Es absolutamente capaz de agregar índices regulares para los campos VARCHAR(255) usando utf8mb4, pero lo que sucede es que el tamaño del índice se trunca en 191 caracteres automáticamente, como unique_key aquí:

Sequel Pro captura de pantalla que muestra el índice truncado en 191 caracteres

Esto está bien, porque los índices regulares solo se utilizan para ayudar a MySQL a buscar sus datos más rápidamente. Todo el campo no necesita ser indexado.

Entonces, ¿por qué MySQL trunca el índice automáticamente para regular índices, pero lanzar un error explícito al intentar hacerlo para índices únicos? Bueno, para que MySQL pueda averiguar si el valor que se está insertando o actualizando ya existe, necesita indexar realmente el valor completo y no solo parte de él.

Al final del día, si usted quiere tener un índice único en un campo, todo el contenido del campo debe encajar en el índice. Para utf8mb4, esto significa reducir la longitud de los campos VARCHAR a 191 caracteres o menos. Si no necesita utf8mb4 para esa tabla o campo, puede devolverlo a utf8 y ser capaz de mantener sus campos de 255 longitudes.

 11
Author: maknz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-15 23:59:56

Aquí está mi respuesta original:

Acabo de soltar la base de datos y volver a crear de esta manera, y el error se ha ido:

drop database if exists rhodes; create database rhodes default CHARACTER set utf8 default COLLATE utf8_general_ci;

Sin embargo, no funciona para todos los casos.

En realidad es un problema usar índices en columnas VARCHAR con el conjunto de caracteres utf8 (o utf8mb4), con columnas VARCHAR que tienen más de una cierta longitud de caracteres. En el caso de utf8mb4, esa cierta longitud es 191.

Por favor, consulte la sección Índice largo en este artículo para obtener más información sobre cómo usar índices largos en la base de datos MySQL: http://hanoian.com/content/index.php/24-automate-the-converting-a-mysql-database-character-set-to-utf8mb4

 7
Author: Châu Hồng Lĩnh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-02 23:34:34

Hice algunas búsquedas sobre este tema finalmente conseguí algunos cambios personalizados

Para MySQL workbench 6.3.7 Versión interfase gráfica está disponible

  1. Inicie Workbench y seleccione la conexión.
  2. Vaya a administración o Instancia y seleccione Archivo de opciones.
  3. Si Workbench le pide permiso para leer el archivo de configuración y luego lo permite presionando OK dos veces.
  4. En la ventana de archivo de opciones del administrador del lugar central viene.
  5. Ir A InnoDB tab y compruebe el innodb_large_prefix si no está marcado en la sección General.
  6. establezca el valor de la opción innodb_default_row_format en DINÁMICO.

Para las versiones por debajo de 6.3.7 opciones directas no están disponibles por lo que necesita ir con símbolo del sistema

  1. Inicie CMD como administrador.
  2. Vaya al director donde se instala mysql server La mayoría de los casos es en "C:\Program Files \ MySQL \ MySQL Server 5.7 \ bin" así que el comando es "CD \" "archivos de programa de CD \ MySQL \ MySQL Servidor 5.7 \ bin".
  3. Ahora ejecute el comando mysql-u userName-p databasescheema Ahora pidió la contraseña del usuario respectivo. Proporcione la contraseña y entre en el prompt de mysql.
  4. Tenemos que establecer algunos ajustes globales introduzca los siguientes comandos uno por uno set global innodb_large_prefix = on; set global innodb_file_format=barracuda; set global innodb_file_per_table=true;
  5. Ahora en el último tenemos que alterar el ROW_FORMAT de la tabla requerida por defecto su COMPACTO tenemos que establecerlo a DINÁMICO.
  6. utilice el siguiente comando alter table table_name ROW_FORMAT=DYNAMIC;
  7. Hecho
 6
Author: Abhishek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-24 14:40:01

Cambie su intercalación. Puedes usar utf8_general_ci que soporta casi todo

 5
Author: Nids Barthwal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-29 09:15:20

Basado en la columna dada a continuación, esas 2 columnas de cadena variable están usando utf8_general_ci intercalación (utf8 charset está implícito).

En MySQL, utf8 charset utiliza un máximo de 3 bytes para cada carácter. Por lo tanto, tendría que asignar 500*3=1500 bytes, que es mucho mayor que los 767 bytes que permite MySQL. Es por eso que está recibiendo este error 1071.

En otras palabras, debe calcular el conteo de caracteres basado en la representación de bytes del conjunto de caracteres, ya que no todos charset es una representación de un solo byte (como usted presume.) Es decir, utf8 en MySQL se utiliza como máximo 3 bytes por carácter, 767/3≈255 caracteres, y para utf8mb4, una representación como máximo de 4 bytes, 767/4≈191 caracteres.

También se sabe que MySQL

column1 varchar(20) utf8_general_ci
column2  varchar(500) utf8_general_ci
 2
Author: Devy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-02 18:20:03

Solucioné este problema con :

varchar(200) 

Sustituido por

varchar(191)

Todos los varchar que tienen más de 200 reemplazarlos con 191 o ponerlos texto.

 2
Author: flik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-09 06:48:43

Encontré esta consulta útil para detectar qué columnas tenían un índice que violaba la longitud máxima:

SELECT
  c.TABLE_NAME As TableName,
  c.COLUMN_NAME AS ColumnName,
  c.DATA_TYPE AS DataType,
  c.CHARACTER_MAXIMUM_LENGTH AS ColumnLength,
  s.INDEX_NAME AS IndexName
FROM information_schema.COLUMNS AS c
INNER JOIN information_schema.statistics AS s
  ON s.table_name = c.TABLE_NAME
 AND s.COLUMN_NAME = c.COLUMN_NAME 
WHERE c.TABLE_SCHEMA = DATABASE()
  AND c.CHARACTER_MAXIMUM_LENGTH > 191 
  AND c.DATA_TYPE IN ('char', 'varchar', 'text')
 1
Author: Andrew,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-16 10:21:38

Por favor, compruebe si sql_mode es como

sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

Si lo es, cambie a

sql_mode=NO_ENGINE_SUBSTITUTION

O

Reinicie su servidor cambiando su my.archivo cnf (poniendo siguiente)

innodb_large_prefix=on
 1
Author: neel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-06 17:06:35

Cambiando utf8mb4 a utf8 al crear tablas resolví mi problema. Por ejemplo: CREATE TABLE ... DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; a CREATE TABLE ... DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;.

 1
Author: MajidJafari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-21 15:31:14

Cambie el CONJUNTO de caracteres del campo índice de quejas a"latin1"
es decir, ALTERAR LA TABLA tbl CAMBIAR myfield myfield varchar (600) JUEGO DE CARACTERES latin1 DEFAULT NULL;
latin1 toma un byte para un carácter en lugar de cuatro

 0
Author: Stan Holodnak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-27 13:14:25

Si estás creando algo como:

CREATE TABLE IF NOT EXISTS your_table (
  id int(7) UNSIGNED NOT NULL AUTO_INCREMENT,
  name varchar(256) COLLATE utf8mb4_bin NOT NULL,
  PRIMARY KEY (id),
  UNIQUE KEY name (name)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1 ROW_FORMAT=FIXED;

Debería ser algo como

CREATE TABLE IF NOT EXISTS your_table (
      id int(7) UNSIGNED NOT NULL AUTO_INCREMENT,
      name varchar(256) COLLATE utf8mb4_bin NOT NULL,
      PRIMARY KEY (id)
    ) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1 ROW_FORMAT=FIXED;

Pero debe verificar la unicidad de esa columna desde el código o agregar una nueva columna como MD5 o SHA1 de la columna varchar

 0
Author: 10undertiber,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-20 12:06:58

Si ha cambiado innodb_log_file_size recientemente, intente restaurar el valor anterior que funcionaba.

 0
Author: AnkitK,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-05 11:30:57

En mi caso, tuve este problema cuando estaba haciendo una copia de seguridad de una base de datos utilizando los caracteres de salida/entrada de redirección de Linux. Por lo tanto, cambio la sintaxis como se describe a continuación. PD: usando un terminal linux o mac.

Copia de seguridad (sin la > redirección)

# mysqldump -u root -p databasename -r bkp.sql

Restaurar (sin la

# mysql -u root -p --default-character-set=utf8 databasename
mysql> SET names 'utf8'
mysql> SOURCE bkp.sql

El error "La clave especificada era demasiado larga; la longitud máxima de la clave es de 767 bytes" simplemente desapareció.

 0
Author: Cassio Seffrin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-15 03:18:43

Para laravel 5.6

Pasos a seguir

  1. Vaya a app\Providers\AppServiceProvider.php
  2. Agregue esto al proveedor / / (No incluya canalización) use Illuminate\Support \ Facades \ Schema;
  3. Dentro de la función de arranque Agregue este Esquema:: defaultStringLength(191);

Que todo, Disfrutar.

 0
Author: Manojkiran.A,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-26 13:03:07

Para mí, el problema de "#1071 - La clave especificada era demasiado larga; la longitud máxima de la clave es de 767 bytes" se resolvió después de cambiar la combinación primarykey / uniquekey al limitar el tamaño de la columna en 200.

ALTER TABLE `mytable` ADD UNIQUE (
`column1` (200) ,
`column2` (200)
);
 -1
Author: Abdul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-18 16:36:48

En caso de que ejecute Laravel (laravel ahora tiene por defecto 4 bytes Unicode que causa esto) puede resolver esto cambiando las siguientes líneas en configuración / base de datos.php desde

'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',

 a

'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
 -2
Author: despotbg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-03 21:42:25