【问题标题】:Laravel "Specified key was too long" when creating notifications table创建通知表时Laravel“指定的键太长”
【发布时间】:2017-01-11 21:10:59
【问题描述】:

我正在使用 Laravel 的默认迁移来创建通知表。

public function up()
{
    Schema::create('notifications', function (Blueprint $table) {
        $table->uuid('id')->primary();
        $table->string('type');
        $table->morphs('notifiable');
        $table->text('data');
        $table->timestamp('read_at')->nullable();
        $table->timestamps();
    });
}

但我在尝试使用时遇到错误:

[Illuminate\Database\QueryException]
  SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes (SQL: alter table `notifications` add index `n
  otifications_notifiable_id_notifiable_type_index`(`notifiable_id`, `notifiable_type`))



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



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

更新

我将索引列的名称更改为notifiable_index,但它仍然抱怨索引键的长度。

  [Illuminate\Database\QueryException]
  SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes (SQL: alter table `notifications` add index `n
  otifiable_index`(`notifiable_id`, `notifiable_type`))



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



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

【问题讨论】:

  • notifiable 列的排序规则是什么?
  • 你解决了吗?
  • @PhilippSander 不得不使用另一种方法来创建更短的密钥。

标签: mysql laravel laravel-5


【解决方案1】:

我最终做的是我刚刚为通知 ID 创建了一个手动索引。这是迁移:

    Schema::create('notifications', function (Blueprint $table) {
        $table->uuid('id')->primary();
        $table->string('type');
        $table->text('data');
        $table->timestamp('read_at')->nullable();
        $table->timestamps();

        $table->unsignedInteger("notifiable_id");
        $table->string("notifiable_type");
        $table->index('notifiable_id');
    });

而不是命令:

 $table->morphs('notifiable');

我有 3 行:

    $table->unsignedInteger("notifiable_id");
    $table->string("notifiable_type");
    $table->index('notifiable_id');

缺点是索引不是基于type+id组合的,它只是基于id。但是因为我只有可以通知的用户模型,所以这对我来说没问题。

【讨论】:

  • 这是一个更好的答案
【解决方案2】:

如果您使用 Laravel 5.4 并运行低于 5.7.7 版本的 MySQL 版本。您可以通过在 AppServiceProvider 类的 boot 方法中调用 Schema::defaultStringLength 方法来解决此问题。

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

【讨论】:

  • 我有 Laravel 5.3
  • @naneri 你试过了吗?
  • @PhilippSander Yah。我尝试了 mariadb 10.1 并且工作正常。
  • @naneri 请与我们分享!
  • 它在 Laravel 5.4.21 中不起作用。你应该改用Illuminate\Database\Schema\Builder::$defaultStringLength = 191
【解决方案3】:

Laravel 根据您的表和名称使用外键约定。但是您可以为密钥提供自己的名称:

$table->morphs('notifiable', 'mykeyname');

这样,您可以确保键名足够短。

来源:https://github.com/laravel/framework/blob/5.3/src/Illuminate/Database/Schema/Blueprint.php#L963

【讨论】:

  • 我更新了列名,但它仍然抱怨密钥长度:(。您可以在第一篇文章中看到更新。
猜你喜欢
  • 2014-01-30
  • 2016-06-19
  • 2014-07-10
  • 2018-11-19
  • 1970-01-01
  • 1970-01-01
  • 2020-01-02
  • 2017-07-23
  • 2020-11-11
相关资源
最近更新 更多