라 라벨 마이그레이션 : 고유 한 키가 너무 길다


166

Laravel에서 users 테이블을 마이그레이션하려고합니다. 마이그레이션을 실행할 때이 오류가 발생합니다.

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

인터넷 검색 후 테일러가 인덱스 키를의 두 번째 매개 변수로 지정할 수 있다고 말하는 이 버그 보고서 를 보았습니다 unique(). 여전히 오류가 발생합니다. 무슨 일이야?


전자 메일에 320자를 사용하는 이유는 무엇입니까? 이것은 당신의 문제 일 수 있습니다.
Antonio Carlos Ribeiro

1
그것은 실제로 문제였습니다. 왜 그런지 모르겠습니다. 그러나 네, 맞습니다. 왜 각 필드에 대해 문자 길이를 지정했는지 모르겠습니다. 이러한 제한을 제거했습니다
harryg

어떤 프레임 워크와 관계형 데이터베이스에 대해서도 영구적으로 해결되는 문제인 전자 메일의 해시와 voila를 포함하는 고정 길이 필드를 사용하도록 제안한 사람이 아무도 없습니다. 그것이 숫자 범위가 충분히 크다는 사실 (그리고 sha1 / sha256의 경우)을 고려할 때 가변 길이 입력의 고정 숫자 표현을 사용하여 독창성을 보장하는 방법입니다.
NB

1
laravel-news.com/laravel-5-4-key-too-long-error 는 도움을받을 수도 있습니다
matinict

답변:


280

이메일 길이를 더 짧게 지정하십시오.

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

실제로 기본값은 다음과 같습니다.

$table->string('email');

그리고 당신은 잘해야합니다.

Laravel 5.4의 경우이 Laravel 5.4 : 지정된 키가 너무 긴 오류입니다. 에서 해결책을 찾을 수 있습니다 .

마이그레이션 가이드에 설명 된대로이 문제를 해결하려면 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

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 bytes)-> 767/2 = 383. 여러 열 인덱스에 길이가 다른 다른 열도 고려하십시오.
Jackie Degl'Innocenti

2
모든 문자열 열에 대한 기본 길이를 지정하는 것보다 마이그레이션 파일에서 특정 열의 길이를 직접 편집 할 수도 있습니다. 모든 열이 인덱스에 없기 때문에이 제약 조건이 필요하지는 않기 때문입니다. $ table-> string ( '열 _ 이름', 191);
Jackie Degl'Innocenti

109

업데이트 1

현재 Laravel 5.4 이러한 변경은 필요 더 이상 없습니다.

Laravel 5.4는 기본적으로 utf8mb4 문자 세트를 사용하는데, 여기에는 데이터베이스에 "이모 지"를 저장하는 기능이 포함됩니다. Laravel 5.3에서 응용 프로그램을 업그레이드하는 경우이 문자 세트로 전환 할 필요가 없습니다.

업데이트 2

현재 프로덕션 MariaDB 버전 은 기본적으로이 설정을 전역 적으로 지원 하지 않습니다 . 기본적으로 MariaDB 10.2.2+ 에서 구현됩니다 .

해결책

당신이 의도적으로 올바른 미래 기본값을 사용하려는 경우와 UTF8 멀티 바이트 (5.4 Laravel부터) 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. 핫 RESTART가 작동하지 않을 수 있습니다.

sudo systemctl stop mysqld
sudo systemctl start mysqld

이제 UTF8을 지원하는 Laravel 5.x가 있습니다.


3
이것은 MySQL 5.5에서 제대로 작동했을 수 있습니다 (재구성을 시도하지 않았 음). 5.7 (아마도 5.6)도 재구성 할 필요없이 작동했습니다. 5.7은 바닐라 구성의 기본 커뮤니티 서버 배포판입니다.
Pjotr

언급 한대로 database.php에서 엔진을 변경했지만 여전히 row = compact로 테이블을 생성하여 문제를 일으 킵니다. 완전히 이해하지 못했습니다. database.php 에서이 변경으로는 충분하지 않으며 my.cnf 파일에서 변경해야한다고 말하는가?
vesperknight

database.php구성 파일 에서만 변경하면 충분하며 로컬 Laravel 프로젝트에 영향을 미칩니다. 로 반드시 delete변경하기 전에 데이터베이스와 새로운 설정을 만들 수 있습니다. my.cnf전역 서버 측 변경에 대해서만 구성 파일 을 변경해야합니다 (현재 모든 새 설치에서 사용 utf8mb4).
득점

또는-다른 필드를 추가하고, 전자 메일의 해시를 계산하고, 필드를 고유하게 만들고, 문제를 영원히 해결하고, 데이터베이스 초기화 변수를 사용하지 마십시오.
NB

누구든지 Doctrine 2를 사용하는 경우 주석 에 전달 options={"row_format"="DYNAMIC"}하여 ROW_FORMAT을 설정할 수 있습니다 @Table.
Albert221

50

Laravel 5.4를 사용 중이거나 업데이트 한 경우 이것은 저에게 효과적이었습니다.

한 번만 변경하십시오. AppServiceProvider.php에서

use Illuminate\Support\Facades\Schema;

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

마이그레이션 가이드 https://laravel.com/docs/master/migrations#creating-indexes에 언급 된대로


마이그레이션 자체에서이 작업을 수행했습니다.
Amirmasoud

7
이것은 아마도 각 문자가 정확히 4 바이트를 차지하고 최대 키 길이는 문자가 아닌 바이트 단위로 측정되기 때문입니다. 따라서 키 길이는 191 * 4 = 764 바이트이며 데이터베이스가 지원하는 최대 767 바이트 미만의 smidgen입니다. 솔루션은 "프로 시저"를 제공하는 것이 아니라 여기에서 공유 된 지식에 기여하려면 IMO에 대한 설명이 필요합니다. 그럼에도 불구하고 편리한 수정.
Jason

33

다른 사람이 내가 한 것처럼이 답변을 우연히 발견 한 경우 다른 이유로 Laravel DB 문자 집합 / 데이터 정렬을 확인할 수 있습니다.

응용 프로그램 (Snipe-IT)을 설치하고 다음을 사용하도록 Laravel 데이터베이스 구성을 구성했습니다.

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

mb4Antonio의 답변이 문제의 진정한 해결책이라고 생각하지만 두 문자열을 모두 제거 하면 문제가 해결되었습니다.


21

이것은 나를 위해 일했다 :

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


이것은 나를 위해 일했습니다. 나는 서버 버전을 사용한다 : 10.1.22-MariaDB-소스 배포
Pune의 웹 개발자

16

config / database.php에서 charset 및 collation에서 mb4를 제거하면 성공적으로 실행됩니다.
'charset'=> 'utf8',
'collation'=> '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,
],

이 두 필드를 변경

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

이것으로

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

14

나는 같은 문제에 직면하여 내 app / database.php에 아래 두 줄을 추가하여 수정했습니다.

'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에서 'mb4'를 제거하십시오
Muthu17

13

laravel 5.4의 경우 간단히 파일을 편집하십시오.

App \ Providers \ AppServiceProvider.php

use Illuminate\Support\Facades\Schema;

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

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

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

1
이것이 질문에 대한 답변이 될 수 있지만이 답변이 문제를 해결하는 데 어떻게 도움이 될 수 있는지에 대한 설명을 추가하는 것이 좋습니다. 자세한 내용 을 알아 보려면 좋은 답변작성하려면 어떻게합니까? 를 참조하십시오.
Roshana Pitigala 님이

6

나는 같은 문제가 있었고 늪을 사용하고있다.

해결책 : 파일 열기 : config / database.php

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

감사


이전 답변 중 어느 것도 나를 위해 일한 것은 아니지만이 답변은 매력처럼 작동했습니다! 그리고 이전 버전의 Laravel DB 엔진이 기본적으로 InnoDB로 설정되어 있으므로 이러한 오류가 발생하지 않았다고 생각합니다.
사사 블라고 예비치

예, 몇 가지 다른 답변 과이 작업을 수행해야했습니다.
Andrew

6

config / database.php 파일에서 :

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

이 줄을 다음과 같이 변경하십시오.

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

5

라벨의 경우> = 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);
   }
}

그러나 두 가지 이유로 즉시 작동하지 않습니다. 하나는 laravel 대신 lumen을 사용하는 경우 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

라 라벨은 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
bluesky

2

라벨 5.4 는 이모티콘 저장을 지원하는 utf8mb4 를 사용 하기 때문 입니다.

이것을 app \ Providers \ AppServiceProvider.php 에 추가하십시오.

use Illuminate\Support\Facades\Schema;

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

그리고 당신은 잘 가야합니다.


2

Laravel 5.4 및 최신 버전으로 업데이트되었거나 최신 버전 인 경우 작동합니다.
AppServiceProvider.php에서 한 번만 변경

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

또한 Facade를 접두어로 붙일 수도 있습니다\
Ohgodwhy

1

문제가 있습니다. 'config / database'의 구성을 변경하십시오.

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

데이터베이스에서 동일한 패턴을 유지합니다.

그런 다음 명령을 내 렸습니다.

php artisan migrate

1

2016 년 10 월 24 일 에 Laravel의 저자 인 Taylor Otwell 은 트위터입니다.

"utf8mb4"는 더 나은 이모티콘 지원을 위해 Laravel 5.4의 기본 MySQL 문자 세트입니다. 🙌 Taylor Otwell 트위터 게시물

버전 5.4 이전에 문자 세트는 utf8

이 세기 동안 많은 웹 앱에는 채팅이나 일종의 플랫폼이 포함되어있어 사용자가 대화 할 수 있으며 많은 사람들이 이모티콘이나 스마일리를 좋아합니다. 이것은 저장하기 위해 더 많은 공간이 필요 utf8mb4하고 문자셋 으로 만 사용할 수있는 일종의 슈퍼 문자입니다 . 그것이 utf8mb4공간 목적 으로 만 마이그레이션하는 이유 입니다.

Illuminate\Database\Schema\Builder클래스 를 조회 하면가 255$defaultStringLength 로 설정되어 있고 Facade를 통해 진행 하고 메소드를 호출 하고 새 길이를 전달할 수 있음을 수정할 수 있습니다 .SchemadefaultStringLength

해당 변경을 수행하려면 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 유니 코드 인코딩) 테이블 열 수와 행 크기의 제한


이것은 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다음brew install mariadb --devel

설치가 완료되면 실행중인 서비스를 중지 / 시작하십시오. brew services stop mariadb brew services start mariadb

현재 개발 버전은 10.2.3입니다. 설치가 끝나면 더 이상 걱정할 필요가 없으며 Laravel 문서에서 제안한대로 utf8로 다시 전환하거나 AppServiceProvider를 편집하지 않고도 utf8mb4 (이제 Laravel 5.4의 기본값)를 사용할 수 있습니다 : https : // laravel .com / docs / master / releases # laravel-5.4 (아래로 스크롤 : 마이그레이션 기본 문자열 길이 )


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명령 을 좋아할 때 길이 문제로 인해 중간 에 멈춤 과 같은 작업이 발생합니다. 솔루션이 울림 ) 나머지 여부를 완전히 정확하게) 우리가 롤의 혈중 알코올 농도 필요 K. 기본 롤백은 수행되지 않습니다. 마이그레이션 작업이 완료를 좋아하지 않았기 때문입니다. 데이터베이스에서 새로 작성된 테이블을 수동으로 삭제해야합니다.

우리는 다음과 같이 땜장이를 사용하여 할 수 있습니다.

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.