ChatGPT解决这个技术问题 Extra ChatGPT

Laravel 迁移错误:语法错误或访问冲突:1071 指定的键太长;最大密钥长度为 767 字节

使用 php artisan make:auth 在 Laravel 5.4 上发生迁移错误

[Illuminate\Database\QueryException] SQLSTATE[42000]:语法错误或访问冲突:1071 指定的键太长;最大密钥长度为 767 字节(SQL:alter table e users add unique users_email_unique(email))[PDOException] SQLSTATE[42000]:语法错误或访问冲突:1071 指定的密钥太长;最大密钥长度为 767 字节

您应该在答案中回答您的问题。不在问题中。 stackoverflow.com/help/self-answer
感谢@can-vural 的建议,我做到了。

R
Ryan

根据official Laravel 7.x documentation,您可以很容易地解决这个问题。

更新您的 /app/Providers/AppServiceProvider.php 以包含:

use Illuminate\Support\Facades\Schema;

/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    Schema::defaultStringLength(191);
}

或者,您可以为您的数据库启用 innodb_large_prefix 选项。有关如何正确启用此选项的说明,请参阅数据库的文档。


小心这个解决方案。例如,如果您索引电子邮件字段,则存储的电子邮件最多只能有 191 个字符。这比官方 RFC 规定的要少。
它正在工作并且是一个有效的解决方案,但我只想指出,使用这种方法可能存在缺陷。
为什么正好是 191 个字符 @absiddiqueLive
这是一个丑陋的 hack,它阻碍了您的代码以适应不良/过时的数据库配置,并且它被呈现为好像它是一个实际的解决方案。
a
ankalagba

我不知道为什么上面的解决方案和正在添加的官方解决方案

Schema::defaultStringLength(191);

AppServiceProvider 中对我不起作用。有用的是编辑 config 文件夹中的 database.php 文件。只需编辑

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

'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',

它应该可以工作,尽管您将无法存储像表情符号这样的扩展多字节字符。

这是一个丑陋的黑客,如果你想用非英语语言存储字符串,请不要这样做,表情符号

我用 Laravel 5.7 做到了。希望能帮助到你。

不要忘记停止并再次启动服务器。


使用此字符集将只允许您保存标准 ASCII,而不是多字节特殊字符,如阿拉伯语、希伯来语、大多数欧洲脚本,当然还有表情符号。另见stackoverflow.com/a/15128103/4233593
我认为您错过了顶部的这部分use Illuminate\Support\Facades\Schema;
@KoushikDas 你使用的是什么版本的 Laravel?
现在我在6.0。我想我最初是用 5.7 或 5.6 做的。
utf8mb4 排序规则的存在是有原因的,如果可以的话,我建议使用它。
D
Dexter Bengil

我只是在这里添加这个答案,因为它是我的 quickest 解决方案。只需将默认数据库引擎设置为 'InnoDB'

/config/database.php

'mysql' => [
    ...,
    ...,
    'engine' => 'InnoDB',
 ]

然后运行 php artisan config:cache 以清除和刷新配置缓存

编辑:找到的答案 here 可能会解释这个问题的幕后情况


完美的解决方案。更好的一些文档以供将来解释
快速更新:我写了“InnoDB ROW_FORMAT=DYNAMIC”,只包含“InnoDB”,正如下面其他评论中提到的那样,它起作用了。但是我不知道这意味着什么以及它如何影响 Laravel 应用程序。如果有人知道,我将非常感谢您的提醒。
很好,谢谢。也适用于 Laravel 9
它对我不起作用!
p
perfectionist1

Laravel 7.X(也适用于 8X):简单的解决方案。

选项1:

php artisan db:wipe 

在 /config/database.php 中更新 mysql 数组的这些值(如下)

'charset' => 'utf8', 'collation' => 'utf8_general_ci',

接着

php artisan migrate

完成!迁移表将被成功创建。

选项 2:

使用 php artisan db:wipe 手动删除/删除数据库中的所有表。

更新您的 AppServiceProvider.php [位于 app/Providers/AppServiceProvider.php ]

use Illuminate\Support\Facades\Schema;
/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    Schema::defaultStringLength(191); 
}

接着

php artisan migrate

完成!

陷阱:我想提一下@shock_gone_wild 的评论

请注意此解决方案(选项 2)。例如,如果您索引电子邮件字段,则存储的电子邮件最多只能有 191 个字符。这比官方 RFC 规定的要少。

可选地,我尝试了这些可能的方法(如下所示)但不起作用。

php artisan config:cache php artisan migrate:fresh

php artisan migrate:reset


E
Esteban Herrera

这个问题是在 Laravel 5.4 中由数据库版本引起的。

根据 docs(在 Index Lengths & MySQL / MariaDB 部分):

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

换句话说,在 <ROOT>/app/Providers/AppServiceProvider.php 中:

// Import Schema
use Illuminate\Support\Facades\Schema;
// ...

class AppServiceProvider extends ServiceProvider
{

public function boot()
{
    // Add the following line
    Schema::defaultStringLength(191);
}

// ...

}

但正如对另一个答案的评论所说:

小心这个解决方案。例如,如果您索引电子邮件字段,则存储的电子邮件最多只能有 191 个字符。这比官方 RFC 规定的要少。

所以文档还提出了另一种解决方案:

或者,您可以为您的数据库启用 innodb_large_prefix 选项。有关如何正确启用此选项的说明,请参阅数据库的文档。


D
Dexter Bengil

对于不想改变 AppServiceProvider.php 的人。 (在我看来,仅仅为了迁移而改变 AppServiceProvider.php 是个坏主意)

您可以将数据长度添加回 database/migrations/ 下的迁移文件,如下所示:

create_users_table.php

$table->string('name',64);
$table->string('email',128)->unique();

create_password_resets_table.php

$table->string('email',128)->index();

这可能是个问题,因为电子邮件最多可以包含 255(ish)个字符
你是对的@HalfCrazed,但我建议这个答案stackoverflow.com/questions/1297272
D
Dexter Bengil

我已经解决了这个问题并编辑了我的 config->database.php 文件以喜欢我的数据库 ('charset'=>'utf8')('collation'=>'utf8_general_ci'),所以我的问题是解决代码如下:

'mysql' => [
        'driver' => 'mysql',
        'host' => env('DB_HOST', '127.0.0.1'),
        'port' => env('DB_PORT', '3306'),
        'database' => env('DB_DATABASE', 'forge'),
        'username' => env('DB_USERNAME', 'forge'),
        'password' => env('DB_PASSWORD', ''),
        'unix_socket' => env('DB_SOCKET', ''),
        'charset' => 'utf8',
        'collation' => 'utf8_general_ci',
        'prefix' => '',
        'strict' => true,
        'engine' => null,
    ],

请注意,并非所有 Unicode 字符都受 utf8 支持。
A
Arslan Ahmad khan

我正在添加两个对我有用的 sollution

1st sollution is

打开 database.php 文件 insde 配置目录/文件夹。编辑 'engine' => null,到 'engine' => 'InnoDB',这对我有用。

第二个解决方案是:

打开 database.php 文件 insde 配置目录/文件夹。 2.Edit 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', to 'charset' => 'utf8', 'collation' => 'utf8_unicode_ci',

祝你好运


s
seyed mohammad asghari

1- 转到 /config/database.php 并找到这些行

'mysql' => [
    ...,
    'charset' => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    ...,
    'engine' => null,
 ]

并将它们更改为:

'mysql' => [
    ...,
    'charset' => 'utf8',
    'collation' => 'utf8_unicode_ci',
    ...,
    'engine' => 'InnoDB',
 ]

2- 运行 php artisan config:cache 重新配置 laravel

3- 删除数据库中的现有表,然后再次运行 php artisan migrate


但根据文档“utf8”将使用已弃用的 utf8 模式吗?
我刚刚将引擎部分从 null 更改为 InnoDB,问题就消失了。
U
Udhav Sarvaiya

我为这个错误找到了两种解决方案

选项1:

在数据库/迁移文件夹中打开您的用户和密码重置表

只需更改电子邮件的长度:

$table->string('email',191)->unique();

选项 2:

打开您的 app/Providers/AppServiceProvider.php 文件并在 boot() 方法中设置默认字符串长度:

use Illuminate\Support\Facades\Schema;

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

A
Alaa ElAlfi

对我来说就像魅力一样!

将此添加到 config/database.php

'engine' => 'InnoDB ROW_FORMAT=DYNAMIC',

代替

'engine' => 'null',

为我工作。谢谢!
A
Ali A. Dhillon

没有人告诉的解决方案是,在 Mysql v5.5 和更高版本中,InnoDB 是默认存储引擎,它没有这个问题,但在很多情况下,像我这样,有一些旧的 mysql ini 配置文件使用旧的 MISAM 存储引擎,如下所示。

default-storage-engine=MYISAM

这造成了所有这些问题,解决方案是一劳永逸地在 Mysql 的 ini 配置文件中将 default-storage-engine 更改为 InnoDB,而不是进行临时修改。

default-storage-engine=InnoDB

如果您使用的是 MySql v5.5 或更高版本,则 InnoDB 是默认引擎,因此您不需要像上面那样显式设置它,只需删除 default-storage-engine=MYISAM if它存在于您的 ini 文件中,您可以开始了。


谢谢!我必须将此建议与字符串长度、字符集和排序规则更改结合使用,以使其与 laravel 6 和 mysql 5.6 一起使用。希望这对将来的其他人有所帮助。
@CasperWilkes 你不必做任何字符串长度,字符集的东西。检查您的 Mysql 系统变量,像这样 show global variables like 'innodb_large_prefix'; 它应该是 ON。如果它是关闭,那么您可以查看this答案以了解如何打开它。 here 是关于 dev.mysql.com 上的 innodb_large_prefix 的更多信息。
谢谢,我不想对 laravel 配置进行任何更改,所以您的解决方案解决了 laravel 9.9 的问题
G
GuruBob

我不会设置长度限制,而是提出以下建议,这对我有用。

里面:

配置/数据库.php

将此行替换为 mysql:

'engine' => 'InnoDB ROW_FORMAT=DYNAMIC',

和:

'engine' => null,

A
Amranur Rahman

在此处打开此文件:/app/Providers/AppServiceProvider.php

并将此代码更新为我的图像:

use Illuminate\Support\Facades\Schema;

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

https://i.stack.imgur.com/naeBO.jpg


不客气安东尼·菲利普斯
D
Dexter Bengil

如迁移 guide 中所述,要解决此问题,您只需编辑 app/Providers/AppServiceProvider.php 文件并在引导方法中设置默认字符串长度:

use Illuminate\Support\Facades\Schema;

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

注意:首先您必须从数据库中删除(如果有)用户表、密码重置表,并从迁移表中删除用户和密码重置条目。

要运行所有未完成的迁移,请执行 migrate Artisan 命令:

php artisan migrate

之后,一切都应该正常工作。


D
Dexter Bengil

如前所述,我们添加到 App/Providers 中的 AppServiceProvider.php

use Illuminate\Support\Facades\Schema;  // add this

/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    Schema::defaultStringLength(191); // also this line
}

您可以在下面的链接中查看更多详细信息(搜索“索引长度和 MySQL / MariaDB”)https://laravel.com/docs/5.5/migrations

但这不是我发布的全部内容!问题是即使执行上述操作您也可能会遇到另一个错误(那是在您运行 php artisan migrate 命令时,因为长度的问题,操作很可能会卡在中间。解决办法在下面,用户表很可能是创建没有其余部分或不完全正确)我们需要回滚。默认回滚将不起作用。因为迁移的操作不喜欢完成。您需要手动删除数据库中新创建的表。

我们可以使用 tinker 来做到这一点,如下所示:

L:\todos> php artisan tinker

Psy Shell v0.8.15 (PHP 7.1.10 — cli) by Justin Hileman

>>> Schema::drop('users')

=> null

我自己对用户表有问题。

之后你就可以走了

php artisan migrate:rollback

php artisan migrate


C
Chintan Kotadiya

如果要更改 AppServiceProvider,则需要在迁移中定义电子邮件字段的长度。只需将第一行代码替换为第二行。

创建用户表

$table->string('email')->unique();
$table->string('email', 50)->unique();

create_password_resets_table

$table->string('email')->index();
$table->string('email', 50)->index();

成功更改后,您可以运行迁移。注意:首先您必须从数据库中删除(如果有)用户表、密码重置表,并从迁移表中删除用户和密码重置条目。


F
Fatema Tuz Zuhora

Schema::defaultStringLength(191); 将默认定义所有字符串的长度 191,这可能会破坏您的数据库。你不能走这条路。

只需定义数据库迁移类中任何特定列的长度即可。例如,我在 CreateUsersTable 类中定义“名称”、“用户名”和“电子邮件”,如下所示:

public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name', 191);
            $table->string('username', 30)->unique();
            $table->string('email', 191)->unique();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });
    }

S
Sammie

推荐的解决方案是启用 MySQL 的 innodb_large_prefix 选项,这样您就不会遇到后续问题。以下是如何做到这一点:

打开 my.ini MySQL 配置文件并像这样在 [mysqld] 行下添加以下行。

[mysqld]
innodb_file_format = Barracuda
innodb_large_prefix = 1
innodb_file_per_table = ON

之后,保存更改并重新启动 MySQL 服务。

如果需要,回滚,然后重新运行迁移。

万一您的问题仍然存在,请转到您的数据库配置文件并设置

'engine' => null,'engine' => 'innodb row_format=dynamic'

希望能帮助到你!


U
Uddyan Semwal

我刚刚在 userspassword_resets 迁移文件中修改了以下行。

旧:$table->string('email')->unique();

新:$table->string('email', 128)->unique();


F
Fenn-CS

为了避免更改代码中的任何内容,只需将 MySQL 服务器更新到至少 5.7.7

参考此以获得更多信息:https://laravel-news.com/laravel-5-4-key-too-long-error


不,18.04中的Mariadb 10.1.41也有这个错误。
T
Treasure

这很常见,因为 Laravel 5.4 将默认数据库字符集更改为 utf8mb4。您需要做的是:编辑您的 App\Providers.php 通过将此代码放在类声明之前

use Illuminate\Support\Facades\Schema;

此外,将此添加到“启动”功能 Schema::defaultStringLength(191);


C
Community

如果您还没有为数据库分配任何数据,请执行以下操作:

转到 app/Providers/AppServiceProvide.php 并添加

使用 Illuminate\Support\ServiceProvider;

在方法 boot() 内部;

架构::defaultStringLength(191);

现在删除数据库中的记录,例如用户表。运行以下

php artisan 配置:缓存 php artisan 迁移


它工作但需要添加 use Illuminate\Support\Facades\Schema; use Illuminate\Support\ServiceProvider; 已经存在。希望你改正
A
Ajay

尝试使用默认字符串长度 125(对于 MySQL 8.0)。

defaultStringLength(125)


M
Mizael Clistion

在 database.php 中

添加这一行:

'引擎' => 'InnoDB ROW_FORMAT=DYNAMIC',

https://i.stack.imgur.com/9GFCx.png


K
Kaizoku Gambare

我认为将 StringLenght 强制为 191 是一个非常糟糕的主意。所以我调查以了解发生了什么。

我注意到此消息错误:

SQLSTATE[42000]:语法错误或访问冲突:1071 指定的键太长;最大密钥长度为 767 字节

在我更新我的 MySQL 版本后开始出现。所以我用 PHPMyAdmin 检查了表,我注意到创建的所有新表都使用排序规则 utf8mb4_unicode_ci 而不是旧表的 utf8_unicode_ci。

在我的学说配置文件中,我注意到 charset 设置为 utf8mb4,但我之前的所有表都是在 utf8 中创建的,所以我想这是一些更新魔法,它开始在 utf8mb4 上工作。

现在简单的解决方法是更改 ORM 配置文件中的行字符集。如果您处于开发模式,则使用 utf8mb4_unicode_ci 删除表,如果无法删除它们,请修复字符集。

对于 Symfony 4

在 config/packages/doctrine.yaml 中将 charset: utf8mb4 更改为 charset: utf8

现在我的学说迁移再次正常工作。


G
Goldman.Vahdettin

首先删除localhost中数据库的所有表

将文件 config/database.php 中的 Laravel 默认数据库(utf8mb4)属性更改为:

'charset' => 'utf8', 'collation' => 'utf8_unicode_ci',

然后更改我的本地数据库属性 utf8_unicode_ci。 php artisan migrate 没问题。


B
Brynn Bateman

对于可能遇到此问题的任何其他人,我的问题是我正在创建一个类型为 string 的列,并试图使其成为 ->unsigned(),而我的意思是它是一个整数。


T
Tiago Gouvêa

在这里工作的方法是传递带有键名的第二个参数(一个短的):

$table->string('my_field_name')->unique(null,'key_name');

J
Jacey

即使我已经有了(实际上是因为我已经有了)Schema::defaultStringLength(191); 我也收到了这个错误。在我的 AppServiceProvider.php 文件中。

原因是因为我试图在我的一次迁移中将字符串值设置为高于 191 的值:

Schema::create('order_items', function (Blueprint $table) {
    $table->primary(['order_id', 'product_id', 'attributes']);
    $table->unsignedBigInteger('order_id');
    $table->unsignedBigInteger('product_id');
    $table->string('attributes', 1000); // This line right here
    $table->timestamps();
});

删除 1000 或将其设置为 191 解决了我的问题。