关于mysql:Laravel Migration Error:语法错误或访问冲突:1071指定密钥太长;

Laravel Migration Error: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes

使用php artisan make:auth的laravel 5.4上的迁移错误

[Illuminate\Database\QueryException] SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes (SQL: alter tabl e users add unique users_email_unique(email))

[PDOException] SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes


根据官方文件,你可以很容易地解决这个问题。

将以下代码添加到appserviceprovider.php(/app/providers/appserviceprovider.php)

1
2
3
4
5
6
use Illuminate\Support\Facades\Schema; //NEW: Import Schema

function boot()
{
    Schema::defaultStringLength(191); //NEW: Increase StringLength
}

MySQL reserves always the max amount for a UTF8 field which is 4 bytes so with 255 + 255 with your DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; you are over the 767 max key length limit. By @scaisedge


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

1
Schema::defaultStringLength(191);

在埃多克斯一〔8〕没有为我工作。有效的方法是编辑config文件夹中的database.php文件。只是编辑

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

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

它应该是有效的。希望它有帮助。


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

/config/database.php

1
2
3
4
5
'mysql' => [
    ...,
    ...,
    'engine' => 'InnoDB',
 ]

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


AppServiceProvider.php中,您将此代码包含在文件的顶部。

1
use Illuminate\Support\Facades\Schema;

然后在引导方法中添加这段代码。

1
 Schema::defaultStringLength(191);


此问题在Laravel 5.4中由数据库版本引起。

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

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.

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Import Schema
use Illuminate\Support\Facades\Schema;
// ...

class AppServiceProvider extends ServiceProvider
{

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

// ...

}

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

Be careful about this solution. If you index email fields for example,
stored emails can only have a max length of 191 chars. This is less
than the official RFC states.

因此,文档还提出了另一种解决方案:

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.


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

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

create_users_table.php

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

create_password_resets_table.php

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


如果在使用命令时处理laravel时遇到此错误:php artisan migrate。然后在文件中添加2行:app->providers->appserviceprovider.php

  • use Schema;
  • Schema::defaultStringLength(191);
  • 请检查这张图片。然后再次运行php artisan migrate命令。


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    '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,
        ],

    app/Providers/AppServiceProvider.php方法中添加以下代码:

    1
    2
    3
    4
    5
    6
    use Illuminate\Support\Facades\Schema;

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

    首先,您必须删除(如果有)用户表,password_从数据库中重置表并删除用户,password_从迁移表中重置条目,然后在删除旧表后运行php artisan migrate命令


    我不限制长度,而是提出以下建议,这对我很有效。

    里面

    config/database.php

    将此行替换为mysql

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

    在上面

    1
    'engine' => null,

    如已指定,我们将添加到app/providers中的appserviceprovider.php

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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/迁移

    但这不是我发表的全部内容!即使这样做,你也可能会得到另一个错误(当你运行EDCOX1,15)命令时,由于长度的问题,操作很可能卡在中间。解决方案如下,用户表可能是在没有其余部分的情况下创建的,或者创建的不完全正确)我们需要后退。默认的回滚将不起作用。因为迁移操作不喜欢完成。您需要手动删除数据库中新创建的表。

    我们可以使用Tinker,如下所示:

    1
    2
    3
    4
    5
    6
    7
    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


    我正在添加两个对我有用的解决方案。

    第一个解决方案是:

  • 打开database.php文件insde config dir/folder。
  • 编辑'engine' => null,'engine' => 'InnoDB',

    这对我很有用。

  • 第二个解决方案是:

  • 打开database.php文件insde config dir/folder。2.编辑'charset' => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    。到

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

  • 古德拉克


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

    创建用户表

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

    创建密码重置表

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

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


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

    1
    2
    3
    4
    5
    6
    use Illuminate\Support\Facades\Schema;

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

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

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

    1
    php artisan migrate

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


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

    只需定义数据库迁移类中任何特定列的长度。例如,我在CreateUsersTable类中定义了"name"、"username"和"email",如下所示:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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();
            });
        }


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

    1
    2
    3
    4
    5
    6
    7
    'mysql' => [
        ...,
        'charset' => 'utf8mb4',
        'collation' => 'utf8mb4_unicode_ci',
        ...,
        'engine' => null,
     ]

    并将其更改为:

    1
    2
    3
    4
    5
    6
    7
    'mysql' => [
        ...,
        'charset' => 'utf8',
        'collation' => 'utf8_unicode_ci',
        ...,
        'engine' => 'InnoDB',
     ]

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

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


    在AppServiceProvider.php文件中:

    1
    2
    3
    4
    5
    6
    use Illuminate\Support\Facades\Schema;

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

    更新&;在app/providers/appserviceprovider.php中插入这些行

    1
    2
    3
    4
    5
    use Illuminate\Support\Facades\Schema;  //insert this line
    public function boot()
    {
        Schema::defaultStringLength(191); //insert this line also
    }

    在"mysql"数组的config/database.php中设置数据库引擎

    1
    'engine' => 'InnoDB',

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

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

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

    哇!!


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

    1
    use Illuminate\Support\Facades\Schema;

    另外,将这个添加到"boot"函数中Schema::defaultStringLength(191);


    我认为把斯特林格特逼到191年真是个坏主意。所以我调查了解发生了什么。

    我注意到这个消息错误:

    SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key
    was too long; max key length is 767 bytes

    在我更新了我的MySQL版本之后,开始出现。所以我用phpmyadmin检查了这些表,我注意到创建的所有新表都使用排序规则utf8mb4-unicode-ci而不是旧表的utf8-unicode-ci。

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

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

    4交响曲

    change charset: utf8mb4 to charset: utf8 in config/packages/doctrine.yaml

    现在我的理论迁移又开始起作用了。


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

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


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

    打开my.inimysql配置文件,在[mysqld]行下添加以下行,如下所示。

    1
    2
    3
    4
    [mysqld]
    innodb_file_format = Barracuda
    innodb_large_prefix = 1
    innodb_file_per_table = ON

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

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

    如果问题仍然存在,请转到数据库配置文件并设置

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

    希望它有帮助!


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

  • 转到app/providers/appserviceprovide.php并添加
  • use Illuminate\Support\ServiceProvider;

    以及方法boot()的内部;

    Schema::defaultStringLength(191);

  • 现在删除数据库中的记录,例如用户表。

  • 运行以下内容

  • php artisan config:cache

    php artisan migrate


    尽管我已经犯了这个错误(实际上是因为我已经犯了)schema::defaultStringLength(191);在我的appServiceProvider.php文件中。

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

    1
    2
    3
    4
    5
    6
    7
    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解决了我的问题。


    对于任何可能遇到这种情况的人来说,我的问题是,我正在制作一个类型为string的列,并试图使它成为->unsigned(),而我的意思是它是一个整数。


    这里接近的工作是传递另一个带有键名的参数(一个短参数):

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

    对我来说,有效的方法是通过运行更新依赖项。

    1
    composer update

    您还应该安装最新的MySQL版本。