执行以下命令时:

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

当前回答

5解决方法:

在5.7.7中提高了限制(MariaDB 10.2.2?)。并且可以通过5.6(10.1)中的一些工作来增加它。

如果你因为试图使用字符集utf8mb4而达到极限。然后做以下其中一种(每一种都有缺点)来避免错误:

⚈  Upgrade to 5.7.7 for 3072 byte limit -- your cloud may not provide this;
⚈  Change 255 to 191 on the VARCHAR -- you lose any values longer than 191 characters (unlikely?);
⚈  ALTER .. CONVERT TO utf8 -- you lose Emoji and some of Chinese;
⚈  Use a "prefix" index -- you lose some of the performance benefits.
⚈  Or... Stay with older version but perform 4 steps to raise the limit to 3072 bytes:

SET GLOBAL innodb_file_format=Barracuda;
SET GLOBAL innodb_file_per_table=1;
SET GLOBAL innodb_large_prefix=1;
logout & login (to get the global values);
ALTER TABLE tbl ROW_FORMAT=DYNAMIC;  -- (or COMPRESSED)

——http://mysql.rjweb.org/doc.php/limits 767 _limit_in_innodb_indexes

其他回答

laravel 5.7到9.0

应遵循的步骤

进入App\Providers\AppServiceProvider.php。 将此添加到提供商使用Illuminate\Support\Facades\Schema;在顶部。 在Boot函数中添加这个Schema::defaultStringLength(191);

就这些,好好享受吧。

我们在尝试使用utf8mb4向VARCHAR(255)字段添加UNIQUE索引时遇到了这个问题。虽然在这里已经很好地概述了这个问题,但我想为我们如何发现并解决它添加一些实际的建议。

当使用utf8mb4时,字符计数为4个字节,而在utf8下,字符计数为3个字节。InnoDB数据库有一个限制,索引只能包含767字节。因此,当使用utf8时,您可以存储255个字符(767/3 = 255),但使用utf8mb4时,您只能存储191个字符(767/4 = 191)。

你完全可以使用utf8mb4为VARCHAR(255)字段添加常规索引,但发生的事情是索引大小自动被截断为191个字符-就像这里的unique_key:

这很好,因为常规索引只是用来帮助MySQL更快地搜索数据。整个字段不需要被索引。

那么,为什么MySQL为常规索引自动截断索引,但抛出一个显式错误时,试图这样做的唯一索引?好吧,为了让MySQL能够判断插入或更新的值是否已经存在,它需要索引整个值,而不仅仅是它的一部分。

最后,如果您想在一个字段上拥有唯一的索引,那么该字段的整个内容必须适合该索引。对于utf8mb4,这意味着将VARCHAR字段长度减少到191个字符或更少。如果这个表或字段不需要utf8mb4,那么可以将其删除回utf8,并能够保留255长度的字段。

我对这个相同问题的修复是添加一个选项作为第三个参数:charset

queryInterface.createTable(
  tableName,
  { /*... columns*/ },
  { charset: 'utf8' } 
)

否则sequelize将创建utf8mb4表。

这个问题

MySQL中有最大键长度限制。

InnoDB -最大密钥长度为1536字节(8kb页面大小)和768字节(4kb页面大小)(来源:Dev.MySQL.com) MyISAM -最大密钥长度是1000字节(来源Dev.MySQL.com)。

这些都是以字节为单位计算的!因此,一个UTF-8字符可能需要一个以上的字节才能存储到密钥中。

因此,你只有两个直接的解决方案:

只索引文本类型的前n个字符。 创建一个全文搜索-所有内容都可以在文本中搜索,以一种类似ElasticSearch的方式

索引文本类型的前N个字符

如果您正在创建一个表,请使用以下语法来索引某些字段的前255个字符:KEY sometextkey (SomeText(255))。像这样:

CREATE TABLE `MyTable` (
    `id` int(11) NOT NULL auto_increment,
    `SomeText` TEXT NOT NULL,
    PRIMARY KEY  (`id`),
    KEY `sometextkey` (`SomeText`(255))
);

如果你已经有了这个表,那么你可以用add unique (ConfigValue(20));为一个字段添加一个唯一键。像这样:

ALTER TABLE
MyTable
ADD UNIQUE(`ConfigValue`(20));

如果字段名不是保留的MySQL关键字,则在字段名周围不需要反引号(' ' ')。

创建全文搜索

全文搜索将允许您搜索文本字段的全部值。如果你使用自然语言模式,它会进行全词匹配,如果你使用其他模式之一,它会进行部分词匹配。查看更多关于全文本的选项:Dev.MySQL.com

创建您的文本表,并添加全文索引…

ALTER TABLE
        MyTable
ADD FULLTEXT INDEX
        `SomeTextKey` (`SomeTextField` DESC);

然后像这样搜索你的桌子……

SELECT
        MyTable.id, MyTable.Title,
MATCH
        (MyTable.Text)
AGAINST
        ('foobar' IN NATURAL LANGUAGE MODE) AS score
FROM
        MyTable
HAVING
        score > 0
ORDER BY
        score DESC;

关于为什么你会得到错误消息的答案已经被很多用户回答了。我的答案是如何修复和使用它。

从这个链接中查阅。

打开MySQL客户端(或MariaDB客户端)。它是一个命令行工具。 它会问你的密码,输入正确的密码。 使用以下命令选择您的数据库:

数据库修改

设置全局innodb_large_prefix=on;

查询OK, 0行受影响(0.00秒)

set global innodb_file_format=Barracuda;

查询OK, 0行受影响(0.02秒)

去phpMyAdmin或类似的数据库,以便于管理。>选择数据库>查看表结构>进入“操作”页签。>将ROW_FORMAT更改为DYNAMIC并保存更改。 进入表的结构选项卡>单击唯一按钮。 完成了。现在应该没有错误了。

这个修复的问题是,如果你导出数据库到另一个服务器(例如从本地主机到真实主机),你不能在该服务器上使用MySQL命令行。你不能让它在那里工作。