Laravelの移行:指定されていても、一意のキーが長すぎます


166

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');
});

いくつかグーグルした後、Taylorがインデックスキーをの2番目のパラメーターとして指定できると言ったこのバグレポートに遭遇しましunique()た。それでもエラーが発生します。ここで何が起こっているのですか?


電子メールに320文字を使用しているのはなぜですか?これはあなたの問題かもしれません。
アントニオカルロスリベイロ2014年

1
それは確かに問題でした、なぜかわかりません。しかし、はい、そうです。なぜ各フィールドの文字長を指定したのかはわかりません。これらの制限を取り除いた
ハリーグ

面白いことに、メールと出来上がりのハッシュを含む固定長フィールドの使用を誰も提案しなかった-どんなフレームワークでも、どんなリレーショナルデータベースでも、問題は永遠に解決されました。これが一意性を保証する方法です。可変長入力の固定数表現を使用すると、数値の範囲が十分に大きいという事実(およびsha1 / sha256の場合はそうです)が与えられます。
NB


回答:


280

電子メールの長さを短くしてください:

$table->string('email', 250);

これがデフォルトです、実際には:

$table->string('email');

そして、あなたは良いはずです。

Laravel 5.4の場合、このLaravel 5.4で解決策を見つけることができます:指定されたキーは長すぎるエラーでした、Laravelニュースポスト:

これを修正するための移行ガイドで概説されているように、あなたがしなければならないすべてはあなたのAppServiceProvider.phpファイルを編集し、ブートメソッド内でデフォルトの文字列長を設定します:

use Illuminate\Database\Schema\Builder;


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

6
可能な最大の電子メールの長さは254おそらくこれを覚えておく価値があるので、その場合はバリデーターを使用して一意性を検証するでしょう。
Sebastian Sulinski

12
Laravel 5.4、使用\Illuminate\Database\Schema\Builder::defaultStringLength(191);正しい関数基準パス
webcoder

5
AppServiceProvider.phpで設定を行った後も、この問題はまだ発生しています。私はただ混乱しています。どうして?サーバー、データベース、その他すべてを再起動しました。助けてください。
Koushik Das 2017

3
インデックス付き列の長さは、767バイトの制限に従って設定する必要があります。VARCHARには、長さの単位ごとに1、2、または4バイトがあることに注意してください。例:utf8_mb4(4バイト)-> 767/4 =191。それ以外の場合、X <85(1バイト)= O(85)のVARCHAR(X)の場合はutf8_general_ci、またはX> = 86(2)のVARCHAR(X)の場合はutf8_general_ciバイト)-> 767/2 =383。複数の列のインデックスにある他の列の長さも考慮してください。
Jackie Degl'Innocenti 2017

2
すべての列がどのインデックスにもないため、すべての列がこの制約を必要とするわけではないので、移行ファイルの特定の列の長さを直接編集して、すべての文字列列のデフォルトの長さを指定することもできます。$ table-> string( 'column_name'、191);
Jackie Degl'Innocenti 2017

109

アップデート1

以下のようLaravel 5.4これらの変更はもう必要ありません。

Laravel 5.4は、デフォルトでutf8mb4文字セットを使用します。これには、データベースに「絵文字」を格納するためのサポートが含まれます。アプリケーションをLaravel 5.3からアップグレードする場合、この文字セットに切り替える必要はありません。

アップデート2

現在の本番MariaDBバージョンは、デフォルトでこの設定をグローバルにサポートしていませんMariaDB 10.2.2以降ではデフォルトで実装されています

解決

そして、futureの正しいfuture-default(Laravel 5.4以降)UTF8マルチバイトutf8mb4サポートを意図的に使用したい場合は、データベース構成の修正を開始します。

Laravelでconfig/database.php定義します:

'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'engine' => 'InnoDB ROW_FORMAT=DYNAMIC',

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

クライアントの場合:

[mysql]
default-character-set=utf8mb4

次に、MySQL / MariaDBサーバーを停止します。その後START。ホットリスタートが機能しない可能性があります。

sudo systemctl stop mysqld
sudo systemctl start mysqld

これで、UTF8をサポートするLaravel 5.xができました。


3
これは、MySQL 5.5で十分機能する可能性があります(再構成を試みなかった)。5.7(おそらく5.6も)は、再構成する必要なく機能しました。5.7は、バニラ構成のデフォルトのCommunity Serverディストリビューションでした。
Pjotr​​ 2016年

あなたが言及したように、私のdatabase.phpのエンジンを変更しましたが、それでも問題を引き起こしているrow = compactでテーブルを作成しています。私は完全に理解していませんでした、database.phpにこの変更を加えるだけでは不十分で、my.cnfファイルにも変更を加える必要があると言っていますか?
vesperknight 2017年

database.php設定ファイルを変更するだけで十分であり、ローカルのLaravelプロジェクトに影響を与えます。delete変更を加える前に必ずデータベースを作成し、新しい設定で作成してください。my.cnfグローバルなサーバー側の変更の場合のみ、構成ファイルを変更する必要があります(現在、すべての新しいインストールでが使用されますutf8mb4)。
スコアラー

または-別のフィールドを追加し、電子メールのハッシュを計算し、フィールドを一意にし、問題を永久に解決し、データベース初期化変数をいじるのを避けます。
NB

誰かがDoctrine 2を使用している場合options={"row_format"="DYNAMIC"}@Tableアノテーションに渡すことでROW_FORMATを設定できます。
Albert221 2017

50

Laravel 5.4をお使いの場合、または更新した場合、これでうまくいきました。

変更は1つだけです。AppServiceProvider.php

use Illuminate\Support\Facades\Schema;

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

移行ガイドhttps://laravel.com/docs/master/migrations#creating-indexesで述べたように


これは移行自体で行いました。
Amirmasoud 2017年

7
これは(おそらく)各文字が正確に4バイトを占め、最大キー長は文字ではなくバイト単位で測定されるためです。したがって、キーの長さは191 * 4 = 764バイトになります。データベースがサポートする最大767バイトを下回るsmidgenです。ここで共有される知識に貢献するのであれば、ソリューションはIMOの説明を必要とし、「手順」を提供するだけではありません。しかし、それでも便利な修正です。
Jason

33

他の誰かが私と同じようにこの答えに出くわしたが、別の理由で、Laravel DBの文字セット/照合順序を確認できます。

私はアプリケーション(Snipe-IT)をインストールしていて、次のものを使用するようにLaravelデータベース構成を構成していました。

'charset' => 'utf8mb4',
'collation' => 'utf8mb4_general_ci',

mb4両方の文字列から削除することで問題が解決しましたが、Antonioの答えが問題の真の解決策であると思います。


21

これは私のために働きました:

 $table->charset = 'utf8';
 $table->collation = 'utf8_unicode_ci';


これでうまくいきました。私はサーバーバージョンを使用しています:10.1.22-MariaDB-ソースディストリビューション
、プネーのWeb開発者

16

charsetからmb4を削除し、config / database.phpから照合を削除すると、正常に実行されます。
'charset' => 'utf8'、
'collat​​ion' => 'utf8_unicode_ci'、


15

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,
],

この2つのフィールドを変更する

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

これとともに

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

14

私は同じ問題に直面しており、私のapp / database.phpに以下の2行を追加することで修正しました

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

私のファイルは以下のようになります:

<?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',

    ......

2
Laravelに新しいバージョンをインストールした場合。utf8mb4&utf8mb4_unicode_ci&config / database.php
Muthu17

13

laravel 5.4の場合、ファイルを編集するだけです

App \ Providers \ AppServiceProvider.php

use Illuminate\Support\Facades\Schema;

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


6

同じ問題があり、湿地を使用しています

解決策:ファイルを開く:config / database.php

'engine' => null, => 'engine' => 'InnoDB',

ありがとう


以前の答えはどれもうまくいきませんでしたが、これは魅力のように働きました!そして、それは完全に理にかなっています。以前のバージョンのLaravel DBエンジンはデフォルトでInnoDBに設定されていたため、以前はこれらのエラーに遭遇しなかったと思います。
Sasa Blagojevic 2017

はい、他のいくつかの答えとこれも行う必要がありました。
Andrew

6

ファイルconfig / database.phpで:

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

この行を次のように変更します。

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

5

Laravel> = 5.6のユーザー

AppServiceProvider.phpファイルを開く

次のクラスを使用します

use Illuminate\Support\Facades\Schema;

次に、bootメソッド内に次の行を追加します

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

4

移行自体に追加しました

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();
});

はい、私はすべての移行でそれを考慮する必要があることを知っていますが、完全に無関係のサービスプロバイダーに隠しておくよりはむしろ


4

実行後もこの問題が発生する場合は、上記の変更。例として、私の場合、以下の変更を行いました、

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);
   }
}

しかし、2つの理由ですぐには機能しません。1つは、laravelの代わりにルーメンを使用している場合、最初にapp.phpファイルのこの行のコメントを解除する必要がある場合があります。

$app->register(App\Providers\AppServiceProvider::class);

次に、artisanコマンドを使用して移行スクリプトを再度作成する必要があります。

php artisan make:migration <your_table_name>

以降、ServiceProviderに加えた変更のみが機能します。


4

laravel 5.7の場合、これらのコードをappserviceprovider.phpに記述します

  use Illuminate\Support\Facades\Schema;

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

2

文字セットを「utf8mb4」から「utf8」に変更し、

「utf8mb4_unicode_ci」から「utf8_unicode_ci」への照合

config / database.phpファイル内

それは私のために働いた。


2

Laravelはutf8mb4デフォルトで文字セットを使用します。これには、データベースに「絵文字」を格納するためのサポートが含まれます。5.7.7リリースより前のバージョンのMySQLまたは10.2.2リリースより前のMariaDBを実行している場合、MySQLがインデックスを作成するために、移行によって生成されるデフォルトの文字列長を手動で構成する必要がある場合があります。あなたはあなたの中でSchema::defaultStringLengthメソッドを呼び出すことによってこれを設定することができ ますAppServiceProvider

use Illuminate\Support\Facades\Schema;

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

チェックアウトできます

https://laravel-news.com/laravel-5-4-key-too-long-error https://laravel.com/docs/5.5/migrations#indexes


ありがとう、私のために働きます。laravel 5.6.23とMAMPのMySQLの
ブルースカイ

2

Laravel 5.4utf8mb4を使用しているためです保存をサポートするutf8mb4をです。

これをapp \ Providers \ AppServiceProvider.phpに追加します

use Illuminate\Support\Facades\Schema;

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

そして、あなたは行ってもいいはずです。


2

Laravel 5.4を使用しているか、最新バージョンにアップデートしている場合は機能します。
AppServiceProvider.phpの1つの変更

use Illuminate\Support\Facades\Schema;

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

1

私が見逃したことを指摘したいと思います...

私はLaravelの初心者です。 "use Illuminate ....."はコピーしませんでした。なぜなら、本当に機能ブーツの真上に既に使用しているからです。。ステートメント。

誰かを助けることを願っています

**use Illuminate\Support\Facades\Schema;**

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

また、任意のファサードにプレフィックスを付けることもできます\
Ohgodwhy

1

問題が発生しました。「config / database」の構成を変更してください

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

データベースで同じパターンを維持します。

その後、私はコマンドを与えました

php artisan migrate

1

2016年10月24日にテイラー・オトウェルで発表されたLaravelの作者はTwitterです

「utf8mb4」は、Laravel 5.4のデフォルトのMySQL文字セットになり、絵文字のサポートが向上します。🙌 テイラー・オトウェルのTwitter投稿

バージョン5.4以前では、文字セットは utf8

今世紀の間、多くのWebアプリには、チャットや、ユーザーが会話できる何らかのプラットフォームが含まれており、多くの人は絵文字やスマイリーを使用することを好みます。これは、格納するためにより多くのスペースを必要とするスーパーキャラクターの一種でありutf8mb4charsetとしてのみ使用できます。それが彼らが移住する理由ですutf8mb4が宇宙目的のためだけです。

Illuminate\Database\Schema\Builderクラスを検索すると、$defaultStringLength255に設定されていることがわかります。これを変更するには、SchemaFacadeを続行して、defaultStringLength方法をして、新しい長さを渡します。

その変更を実行するにAppServiceProviderは、このようなapp \ providersサブディレクトリの下にあるクラス内でそのメソッドを呼び出します

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        // all other code ...

        Schema::defaultStringLength(191); 
    }
    // and all other code goes here
}

MySQLが767バイトをサポートしていること、およびこれが取得する各マルチバイト文字のバイト数であるため、値として191を使用することをお勧めします767 / 4191

詳しくは、こちらをご覧ください テーブルの列数と行サイズのutf8mb4文字セット(4バイトUTF-8 Unicodeエンコーディング)の制限


これが191マジックナンバーを説明する唯一の答えです。
Illya Moskvin


1

あなたのところに行きconfig/database.php、文字セットと照合をutf8mb4からutf8に変更します

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

私の問題はこの方法を使用して解決されました。


0

MySQL 5.7.7以降またはMariaDB 10.2.2以降を使用している場合は、この問題は発生しません。

Brewを使用してMacでMariaDBを更新するには、まず現在のものをリンク解除してから、次 brew unlink mariadbを使用してdevをインストールします。brew install mariadb --devel

インストールが完了したら、サービスの実行を停止/開始します。 brew services stop mariadb brew services start mariadb

現在の開発バージョンは10.2.3です。インストールが完了したら、これを心配する必要はなくなり、utf8に切り替えたり、Laravelのドキュメントで提案されているようにAppServiceProviderを編集したりせずに、utf8mb4(これはLaravel 5.4のデフォルトです)を使用できます: https:// laravel .com / docs / master / releases#laravel-5.4(下にスクロール:Migration Default String Length


0

MariaDB 10.2.4 RCをインストールし、新しい空のLaravel 5.4プロジェクトを起動し、デフォルトの移行(varchar(255)列)が機能します。

DB confとLaravaelを変更する必要はありませんconfig/database.php。したがって、@ scorerが10.2.2以降のデフォルトの動作について述べたのと同じです。


0

すべては他のAnwserで詳しく説明されています。詳細は以下のリンクで確認できます(キー 'Index Lengths&MySQL / MariaDB'で検索) https://laravel.com/docs/5.5/migrations

しかし、それはこの答えが何であるかではありません!上記のことを行っても、別のエラーが発生します(起動php artisan migrateコマンドが好きで、長さの問題が原因で、途中でスタックするような操作が発生します。解決策は次のとおりです。ユーザーテーブルは、残りまたは完全に正しくない) 私たちはバクを転がす必要がありますます。デフォルトのロールバックは行いません。移行の操作が終了を好まなかったためです。データベースに新しく作成されたテーブルを手動で削除する必要があります。

以下のようにティンカーを使用して実行できます。

L:\todos> php artisan tinker

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

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

=> null

私自身もusersテーブルに問題がありました。

その後、あなたが行ってもいい

php artisan migrate:rollback

php artisan migrate

0

データベースエンジンInnoDBを設定します。

  Schema::create('users', function (Blueprint $table) {
            $table->engine = 'InnoDB';
            $table->increments('id');
            $table->string('name');
            $table->string('email')->unique();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });

0

他のすべての回答を試してもうまくいかない場合は、データベースからすべてのテーブルを削除してから、次のコマンドを使用して、migrateコマンドを一度に実行できます。

php artisan migrate:fresh
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.