执行以下命令时:

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

我得到了这个错误信息:

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

columnn1和column2的信息:

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

我认为varchar(20)只需要21个字节,而varchar(500)只需要501个字节。所以总字节数是522,小于767。为什么我得到了错误消息?

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

当前回答

在我的例子中,我在使用linux重定向输出/输入字符备份数据库时遇到了这个问题。因此,我按照下面的描述更改语法。PS:使用linux或mac终端。

备份(没有>重定向)

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

恢复(不带< redirect)

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

错误“指定的键太长;最大密钥长度是767字节。

其他回答

为了解决这个问题,这个方法对我很有效。

ALTER DATABASE dbname CHARACTER SET utf8 COLLATE utf8_general_ci;

索引长度& MySQL / MariaDB


Laravel默认使用utf8mb4字符集,其中包括在数据库中存储“表情符号”的支持。如果您运行的MySQL版本比5.7.7版本更老,或者MariaDB版本比10.2.2版本更老,您可能需要手动配置由迁移生成的默认字符串长度,以便MySQL为它们创建索引。你可以在AppServiceProvider中调用Schema::defaultStringLength方法来配置:

use Illuminate\Support\Facades\Schema; /** * Bootstrap any application services. * * @return void */ public function boot() { Schema::defaultStringLength(191); } Alternatively, you may enable the innodb_large_prefix option for your database. Refer to your database's documentation for instructions on how to properly enable this option. Reference from blog : https://www.scratchcode.io/specified-key-too-long-error-in-laravel/ Reference from Official laravel documentation : https://laravel.com/docs/5.7/migrations

如果您最近修改了innodb_log_file_size,请尝试恢复之前的值。

我认为varchar(20)只需要21个字节,而varchar(500)只需要 需要501字节。所以总字节数是522,小于767。那么,为什么 我收到错误信息了吗?

UTF8每个字符需要3个字节来存储字符串,因此在您的情况下,20 +500字符= 20*3+500*3 = 1560字节,这超过了允许的767字节。

UTF8的限制是767/3 = 255个字符,对于每个字符使用4个字节的UTF8mb4,它是767/4 = 191个字符。


如果您需要使用比限制更长的列,有两种解决方案:

Use "cheaper" encoding (the one that requires less bytes per character) In my case, I needed to add Unique index on column containing SEO string of article, as I use only [A-z0-9\-] characters for SEO, I used latin1_general_ci which uses only one byte per character and so column can have 767 bytes length. Create hash from your column and use unique index only on that The other option for me was to create another column which would store hash of SEO, this column would have UNIQUE key to ensure SEO values are unique. I would also add KEY index to original SEO column to speed up look up.

Laravel框架解决方案

根据Laravel 5.4。*文档;你必须在app/Providers/AppServiceProvider.php文件的引导方法中设置默认字符串长度,如下所示:

use Illuminate\Support\Facades\Schema;

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

Laravel 5.4对这个修复的解释。*文档:

Laravel uses the utf8mb4 character set by default, which includes support for storing "emojis" in the database. If you are running a version of MySQL older than the 5.7.7 release or MariaDB older than the 10.2.2 release, you may need to manually configure the default string length generated by migrations in order for MySQL to create indexes for them. You may configure this by calling the Schema::defaultStringLength method within your AppServiceProvider. Alternatively, you may enable the innodb_large_prefix option for your database. Refer to your database's documentation for instructions on how to properly enable this option.