Laravel迁移:即使指定,唯一键也太长

har*_*ryg 150 php mysql laravel

我正在尝试在Laravel中迁移用户表.当我运行迁移时,我收到此错误:

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

我的迁移如下:

Schema::create('users', function(Blueprint $table)
{
    $table->increments('id');
    $table->string('name', 32);
    $table->string('username', 32);
    $table->string('email', 320);
    $table->string('password', 64);
    $table->string('role', 32);
    $table->string('confirmation_code');
    $table->boolean('confirmed')->default(true);
    $table->timestamps();

    $table->unique('email', 'users_email_uniq');
});
Run Code Online (Sandbox Code Playgroud)

经过一些谷歌搜索我遇到了这个错误报告,泰勒说你可以指定索引键作为unique()我做的第二个参数.它仍然给出了错误.这里发生了什么?

Ant*_*iro 260

为电子邮件指定较小的长度:

$table->string('email', 250);
Run Code Online (Sandbox Code Playgroud)

这是默认值,实际上:

$table->string('email');
Run Code Online (Sandbox Code Playgroud)

你应该好.

对于Laravel 5.4,您可以在这个Laravel 5.4中找到解决方案:指定密钥太长错误,Laravel News帖子:

正如迁移指南中所述,为了解决这个问题,您只需编辑AppServiceProvider.php文件并在boot方法中设置默认字符串长度:

use Illuminate\Database\Schema\Builder;


public function boot()
{
    Builder::defaultStringLength(191);
}
Run Code Online (Sandbox Code Playgroud)

  • 对于_Laravel 5.4_,使用`\ Illuminate\Database\Schema\Builder :: defaultStringLength(191);`以获取正确的函数引用路径 (11认同)
  • 在AppServiceProvider.php中进行配置后,仍然会出现此问题.我很困惑.为什么?我重新启动了服务器,数据库以及其他所有内容.请帮忙. (5认同)
  • 最大可能的电子邮件长度为"254",因此可能值得记住这一点,因此我可能会在这种情况下使用验证器验证唯一性. (4认同)
  • 您必须根据767字节的限制设置索引列的长度.请注意,VARCHAR每个长度单位可能有1,2或4个字节.示例:utf8_mb4(4字节) - > 767/4 = 191.否则,对于VARCHAR(X),utf8_general_ci为X <85(1字节)= O(85),或者utf8_general_ci为VARCHAR(X),X> = 86(2) bytes) - > 767/2 = 383.还要考虑多列索引中的其他列. (3认同)
  • 您可能还想直接在迁移文件中编辑特定列的长度,而不是为所有字符串列指定默认长度,因为并非所有列都需要此约束,因为它们不在任何索引中。$ table-&gt; string('column_name',191); (2认同)

sco*_*rer 104

更新1

Laravel 5.4开始,不再需要这些变化.

Laravel 5.4默认使用utf8mb4字符集,其中包括支持在数据库中存储"emojis".如果要从Laravel 5.3升级应用程序,则无需切换到此字符集.

更新2

当前生产的MariaDB版本默认情况下支持此设置.默认情况下,它在MariaDB 10.2.2+中实现.

如果你有意想使用正确的future-default(从Laravel 5.4开始)UTF8多字节utf8mb4支持,那么就开始修复你的数据库配置.

在Laravel config/database.php定义:

'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'engine' => 'InnoDB ROW_FORMAT=DYNAMIC',
Run Code Online (Sandbox Code Playgroud)

DYNAMIC允许存储长键索引.

服务器设置(默认情况下包含在MySQL 5.7.7+/MariaDB 10.2.2+中):

[mysqld]
# default character set and collation
collation-server = utf8mb4_unicode_ci
character-set-server = utf8mb4

# utf8mb4 long key index
innodb_large_prefix = 1
innodb_file_format = barracuda
innodb_file_format_max = barracuda
innodb_file_per_table = 1
Run Code Online (Sandbox Code Playgroud)

对于客户:

[mysql]
default-character-set=utf8mb4
Run Code Online (Sandbox Code Playgroud)

然后停止 MySQL/MariaDB服务器.在那之后开始.热RESTART可能无法正常工作.

sudo systemctl stop mysqld
sudo systemctl start mysqld
Run Code Online (Sandbox Code Playgroud)

现在你有了支持UTF8的Laravel 5.x.

  • 这可能与MySQL 5.5相当不错(没有尝试重新配置).5.7(可能也是5.6)工作,无需任何重新配置​​.5.7是具有vanilla配置的默认社区服务器分发. (3认同)

小智 45

如果您正在使用或更新到Laravel 5.4这对我有用;

只需1改变.在AppServiceProvider.php中

use Illuminate\Support\Facades\Schema;

public function boot()
{
  Schema::defaultStringLength(191);
}
Run Code Online (Sandbox Code Playgroud)

如迁移指南https://laravel.com/docs/master/migrations#creating-indexes中所述

  • 这(推测)是因为每个字符恰好占用4个字节,最大密钥长度以字节为单位,而不是字符.因此密钥长度将为191*4 = 764字节,只是数据库将支持的最大767字节下的smidgen.解决方案需要解释IMO,如果他们要在这里贡献共享知识,而不仅仅是提供"程序".但仍然是一个方便的修复. (6认同)

Bre*_*dan 32

如果有其他人像我一样偶然发现了这个答案,但出于不同的原因,你可以查看你的Laravel DB字符集/校对.

我正在安装一个应用程序(Snipe-IT)并配置了Laravel数据库配置以使用以下内容:

'charset' => 'utf8mb4',
'collation' => 'utf8mb4_general_ci',
Run Code Online (Sandbox Code Playgroud)

mb4从两个字符串删除修复了问题,虽然我相信安东尼奥的答案是问题的真正解决方案.


use*_*647 20

这对我有用:

 $table->charset = 'utf8';
 $table->collation = 'utf8_unicode_ci';
Run Code Online (Sandbox Code Playgroud)


小智 15

从charset中删除mb4并从config/database.php中删除排序,然后它将成功执行.
'charset'=>'utf8',
'collat​​ion'=>'utf8_unicode_ci',


小智 13

对于laravel 5.6
此解决方案解决了我的问题
请转到config/database.php
下面的代码

'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' => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    'prefix' => '',
    'strict' => true,
    'engine' => null,
],
Run Code Online (Sandbox Code Playgroud)

改变这两个领域

'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci'
Run Code Online (Sandbox Code Playgroud)

有了这个

'charset' => 'utf8',
'collation' => 'utf8_unicode_ci'
Run Code Online (Sandbox Code Playgroud)


小智 12

对于laravel 5.4,只需编辑文件即可

软件\供应商\ AppServiceProvider.php

use Illuminate\Support\Facades\Schema;

public function boot()
{
    Schema::defaultStringLength(191);
}
Run Code Online (Sandbox Code Playgroud)


Mut*_*u17 11

我遇到了同样的问题,并通过在app/database.php中添加以下两行来修复它

'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
Run Code Online (Sandbox Code Playgroud)

我的文件如下所示:

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Default Database Connection Name
    |--------------------------------------------------------------------------
    |
    | Here you may specify which of the database connections below you wish
    | to use as your default connection for all database work. Of course
    | you may use many connections at once using the Database library.
    |
    */

    'default' => env('DB_CONNECTION', 'mysql'),

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

    ......
Run Code Online (Sandbox Code Playgroud)

  • 如果您在 Laravel 中安装了新版本。请从 utf8mb4 &amp; utf8mb4_unicode_ci &amp; config/database.php 中删除“mb4” (2认同)

小智 7

我有同样的问题,我正在使用 wamp

解决方案:打开文件:config/database.php

'engine' => null, => 'engine' => 'InnoDB',
Run Code Online (Sandbox Code Playgroud)

谢谢


Fai*_*oor 6

File: config/database.php
change the following
FROM ->
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',

TO ->
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
Run Code Online (Sandbox Code Playgroud)


小智 5

我添加到迁移本身

Schema::defaultStringLength(191);
Schema::create('users', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name');
    $table->string('email')->unique();
    $table->string('password');
    $table->rememberToken();
    $table->timestamps();
});
Run Code Online (Sandbox Code Playgroud)

是的,我知道我需要在每次迁移时考虑它,但我宁愿这样做,也不愿将其隐藏在一些完全不相关的服务提供商中


小智 5

在文件config/database.php中:

'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
Run Code Online (Sandbox Code Playgroud)

将此行更改为:

'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
Run Code Online (Sandbox Code Playgroud)


Wae*_*saf 5

对于Laravel >= 5.6用户

打开AppServiceProvider.php文件

使用以下类

use Illuminate\Support\Facades\Schema;
Run Code Online (Sandbox Code Playgroud)

然后在boot方法内部添加以下行

public function boot()
{
    Schema::defaultStringLength(191);
}
Run Code Online (Sandbox Code Playgroud)


dil*_*111 5

如果有人在这样做后仍然遇到此问题,则上述更改。例如,就我而言,我做了以下更改,

namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Schema;

class AppServiceProvider extends ServiceProvider
{
  /**
   * Register any application services.
   *
   * @return void
   */
   public function register()
   {
      //
   }

   public function boot()
   {
     Schema::defaultStringLength(191);
   }
}
Run Code Online (Sandbox Code Playgroud)

但由于两个原因,它不会立即起作用。一个是如果您使用 lumen 而不是 laravel,您可能需要先在 app.php 文件中取消注释这一行。

$app->register(App\Providers\AppServiceProvider::class);
Run Code Online (Sandbox Code Playgroud)

然后你必须再次使用 artisan 命令创建迁移脚本,

php artisan make:migration <your_table_name>
Run Code Online (Sandbox Code Playgroud)

因为现在只有您对 ServiceProvider 所做的更改才会起作用。


小智 5

转到您的config/database.php并将字符集和排序规则从 utf8mb4 更改为 utf8

'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
Run Code Online (Sandbox Code Playgroud)

我的问题用这个方法解决了,祝你好运!