Laravel Taşıma Hatası: Sözdizimi hatası veya erişim ihlali: 1071 Belirtilen anahtar çok uzun; maksimum anahtar uzunluğu 767 bayttır


178

Laravel 5.4'te taşıma hatası php artisan make:auth

[Illuminate \ Database \ QueryException] SQLSTATE [42000]: Sözdizimi hatası veya erişim ihlali: 1071 Belirtilen anahtar çok uzun; maksimum anahtar uzunluğu 767 bayttır (SQL: değiştir tabl e usersadd unique users_email_unique( email))

[PDOException] SQLSTATE [42000]: Sözdizimi hatası veya erişim ihlali: 1071 Belirtilen anahtar çok uzun; maksimum anahtar uzunluğu 767 bayttır


3
Sorunuzu bir cevapta cevaplamalısınız. Söz konusu değil. stackoverflow.com/help/self-answer
Can Vural

@ Can-vural önerisi için teşekkürler, yaptım.
57'de canlı

Yanıtlar:


283

Göre resmi belgeler , oldukça kolay bunu çözebiliriz.

Aşağıdaki iki kod satırını AppServiceProvider.php'ye (/app/Providers/AppServiceProvider.php) ekleyin

use Illuminate\Database\Schema\Builder; // Import Builder where defaultStringLength method is defined

function boot()
{
    Builder::defaultStringLength(191); // Update defaultStringLength
}

MySQL, UTF8 alanı için her zaman 4 bayt olan maksimum tutarı saklar, böylece VARSAYILAN KARAKTER AYARINIZ ile 255 + 255 ile utf8mb4 COLLATE utf8mb4_unicode_ci; maksimum 767 anahtar uzunluğu sınırını aştınız. @Scaisedge tarafından


3
Bu çözüme dikkat edin. Örneğin, e-posta alanlarını endekslerseniz, saklanan e-postaların maksimum uzunluğu 191 karakter olabilir. Bu resmi RFC ülkelerinden daha azdır.
shock_gone_wild


Çalışıyor ve geçerli bir çözüm, ama sadece bu yaklaşımı kullanan olası tuzaklar olduğunu belirtmek istedim.
shock_gone_wild

Umarım bu çözüm gelecekte kıçımda beni ısırmaya gelmez, ancak şimdilik işe yarıyor. Yine de e-postaları nasıl endekslediğime dikkat etmeliyim.
deusofnull

4
neden tam olarak 191 karakter @absiddiqueLive
PseudoAj

121

Neden yukarıdaki çözümün ve resmi çözümün

Schema::defaultStringLength(191);

içinde AppServiceProviderbenim için çalışmadı. Ne işe yaradı database.phpdosyayı configklasörde düzenlemekti . Sadece düzenle

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

için

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

ve emoji gibi genişletilmiş çok baytlı karakterleri saklayamayacak olsanız da , çalışmalıdır .

Laravel 5.7 ile yaptım. Umarım yardımcı olur.


5
Bu karakter setini kullanmak, sadece Standart ASCII'yi kaydetmenize izin verir, Arapça, İbranice, çoğu Avrupa alfabesi ve elbette emoji gibi çok baytlı özel karakterleri kaydetmenize izin vermez. ayrıca bkz. stackoverflow.com/a/15128103/4233593
Jeff Puckett

7
Bence use Illuminate\Support\Facades\Schema;üstte bu kısmı kaçırdın .
sivilce

Laravel'in hangi sürümünü kullanıyorsunuz?
sivilce

Şimdi 6.0'dayım. Sanırım başlangıçta 5.7 veya 5.6 ile yaptım.
Koushik Das

2
utf8mb4Harmanlama bir nedeni vardır, yapabileceğini eğer kullanmak önerilir.
Alev

85

Bu yanıtı buraya ekliyorum çünkü bu benim için bir quickestçözüm. Sadece varsayılan veritabanı motorunu ayarlamak 'InnoDB'üzerinde

/config/database.php

'mysql' => [
    ...,
    ...,
    'engine' => 'InnoDB',
 ]

ardından php artisan config:cacheyapılandırma önbelleğini temizlemek ve yenilemek için çalıştırın


1
Bu, bu sorunun resmi cevabı / çözümü olmalı ... Teşekkürler
Syamsoul Azrien

1
Bu gerçek çözümdür, diğerleri geçici çözümlerdir
Luís Cunha

3
ama bunun arkasındaki mantık nedir
Zülfikar Tarikatı

1
Doğru çözüm bu. Ama neden varsayılan yüklemeye dahil edilmedi.
Ankit Chauhan

38

Olarak AppServiceProvider.php, dosyanın bu kod üst içerir.

use Illuminate\Support\Facades\Schema;

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

Teşekkür bana yardım etti
Ölü Adam

24

Bu sorun, veritabanı sürümü Laravel 5.4 neden olur.

Dokümanlara göre ( Index Lengths & MySQL / MariaDBbölümde):

Laravel, utf8mb4varsayılan olarak "emojileri" veritabanında saklamak için destek içeren karakter kümesini kullanır . 5.7.7 sürümünden daha eski bir MySQL sürümü veya 10.2.2 sürümünden daha eski bir MariaDB sürümü kullanıyorsanız, MySQL'in kendileri için dizin oluşturması için geçişler tarafından oluşturulan varsayılan dize uzunluğunu el ile yapılandırmanız gerekebilir. Bunu, Schema::defaultStringLengthiçindeki yöntemi çağırarak yapılandırabilirsiniz AppServiceProvider.

Başka bir deyişle, içinde <ROOT>/app/Providers/AppServiceProvider.php:

// Import Schema
use Illuminate\Support\Facades\Schema;
// ...

class AppServiceProvider extends ServiceProvider
{

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

// ...

}

Ancak diğer cevaba yapılan yorumun söylediği gibi:

Bu çözüme dikkat edin. Örneğin, e-posta alanlarını endekslerseniz, saklanan e-postaların maksimum uzunluğu 191 karakter olabilir. Bu resmi RFC ülkelerinden daha azdır.

Böylece dokümantasyon başka bir çözüm de önermektedir:

Alternatif olarak, innodb_large_prefixveritabanınız için seçeneği etkinleştirebilirsiniz . Bu seçeneğin uygun şekilde etkinleştirilmesine ilişkin talimatlar için veritabanınızın belgelerine bakın.


16

Değişmek istemeyen biri için AppServiceProvider.php. (Bence AppServiceProvider.phpsadece göç için değiştirmek kötü bir fikir )

Veri uzunluğunu taşıma dosyasına database/migrations/aşağıdaki gibi geri ekleyebilirsiniz :

create_users_table.php

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

create_password_resets_table.php

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

E-postalar 255 (ish) karaktere kadar olabileceğinden bu bir sorun olabilir
Half Crazed

Haklısın @HalfCrazed, ama bu cevabı öneriyorum stackoverflow.com/questions/1297272
helloroy

benim sorunum tam olarak bu çözümle çözülebilirdi. Alanlarım e-posta değildi.
Tharaka Devinda

11

Komutu kullanırken laravel üzerinde çalışırken bu hatayla karşılaşırsanız: php artisan migrate dosyaya sadece 2 satır eklersiniz: app-> Providers-> AppServiceProvider.php

  1. use Schema;
  2. Schema::defaultStringLength(191);

lütfen bu resmi kontrol edin . sonra php artisan migratekomutu tekrar çalıştırın .


1
'Şema kullan;' eklemek çok önemlidir. Yani bu en iyi cevap
hxwtch

Bunu, bu şekilde 2. çizgiden önce ters eğik çizgi '\' ekleyerek de yapabilirsiniz\Schema::defaultStringLength(191);
Tahir Afridi

10

Benim için çalışan iki sollution ekliyorum .

1. çözüm :

  1. Database.php dosyasını açın insde config dir / folder.
  2. Düzenleme 'engine' => null,için'engine' => 'InnoDB',

    Bu benim için çalıştı.

2. çözüm:

  1. Database.php dosyasını açın insde config dir / folder.
    2. Şununla düzenle
    'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci',
    :

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


İyi şanslar


10

bu satırları güncelle ve app / Providers / AppServiceProvider.php dosyasına ekle

use Illuminate\Support\Facades\Schema;  // add this line at top of file

public function boot()
{
    Schema::defaultStringLength(191); // add this line in boot method
}

8

Bu sorunu çözdüm ve benim veritabanı ('charset' => 'utf8') ve ('harmanlama' => 'utf8_general_ci') gibi config-> database.php dosyamı düzenledim , bu yüzden sorunum kodu çözdü takip et:

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

8

Bu hata için iki çözüm buldum

SEÇENEK 1:

Senin aç kullanıcı ve password_reset tablo veritabanı / göçler klasörüne

Ve sadece e-postanın uzunluğunu değiştirin:

$table->string('email',191)->unique();

SEÇENEK 2:

app/Providers/AppServiceProvider.phpDosyanızı açın ve boot()yöntem içinde varsayılan bir dize uzunluğu ayarlayın:

use Illuminate\Support\Facades\Schema;

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

7

1-/config/database.php Bu satırlara gidin ve bulun

'mysql' => [
    ...,
    'charset' => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    ...,
    'engine' => null,
 ]

ve bunları şu şekilde değiştirin:

'mysql' => [
    ...,
    'charset' => 'utf8',
    'collation' => 'utf8_unicode_ci',
    ...,
    'engine' => 'InnoDB',
 ]

2- çalıştırın php artisan config:cacheyeniden yapılandırmak laravel için

3- Veritabanınızdaki mevcut tabloları silin ve php artisan migratetekrar çalıştırın.


1
laravel 5.8 için en iyi cevap budur. Ancak önceden oluşturulmuş tabloları silin
Magige Daniel

ama belgelere göre "utf8" artık kullanım dışı utf8 modunu kullanır?
NoBugs

5

In AppServiceProvider.php dosyası:

 use Illuminate\Support\Facades\Schema;

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

5

Uzunluk için bir sınır belirlemek yerine, benim için çalışan aşağıdakileri öneririm.

İçinde:

config / DatabaseFunctions.php

mysql için bu satırı değiştirin:

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

ile:

'engine' => null,

4

Bunu düzeltmek için Taşıma kılavuzunda belirtildiği gibi , tek yapmanız gereken app/Providers/AppServiceProvider.phpdosyanızı düzenlemek ve önyükleme yönteminin içinde varsayılan bir dize uzunluğu ayarlamaktır:

use Illuminate\Support\Facades\Schema;

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

Not: önce (varsa) kullanıcı tablosunu, password_resets tablosunu veritabanından, kullanıcıları ve password_resets girdilerini taşıma tablosundan silmeniz gerekir .

Tüm olağanüstü taşıma işlemlerinizi gerçekleştirmek için migrateArtisan komutunu yürütün :

php artisan migrate

Bundan sonra her şey normal olarak çalışmalıdır.


4

Daha önce belirtildiği gibi, Uygulama / Sağlayıcılar'daki AppServiceProvider.php dosyasına ekliyoruz

use Illuminate\Support\Facades\Schema;  // add this

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

aşağıdaki bağlantıda daha fazla ayrıntı görebilirsiniz ("Dizin Uzunlukları ve MySQL / MariaDB" için arama yapın ) https://laravel.com/docs/5.5/migrations

AMA İYİ hakkında yayınladığım şey bu değil! yukarıdakileri yaparken bile başka bir hata alırsınız ( php artisan migratekomutu çalıştırdığınızda ve uzunluk problemi nedeniyle işlem muhtemelen ortada sıkışır. çözüm aşağıdadır ve kullanıcı tablosu muhtemelen oluşturulur geri kalanı olmadan veya tamamen doğru değil) geri almamız gerekir . varsayılan geri alma çalışmaz. çünkü göç operasyonu bitirmek istemiyordu. veritabanında yeni oluşturulan tabloları el ile silmeniz gerekir.

Aşağıdaki gibi tamircilik kullanarak yapabiliriz:

L:\todos> php artisan tinker

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

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

=> null

Kullanıcılar tablosunda kendimle ilgili bir sorun yaşadım.

ondan sonra gitmekte iyisin

php artisan migrate:rollback

php artisan migrate


4

Kimsenin söylemediği çözüm, Mysql v5.5 ve daha sonra InnoDB'de bu sorunu olmayan varsayılan depolama motoru olduğu, ancak benimki gibi birçok durumda, aşağıdaki gibi eski MYISAM depolama motorunu kullanan bazı eski mysql ini yapılandırma dosyalarının olduğu .

default-storage-engine=MYISAM

tüm bu sorunları yaratıyor ve çözüm Mysql ini yapılandırma dosyasındaki InnoDB'yi bir kez ve geçici hack yapmak yerine InnoDB olarak değiştirmektir .

default-storage-engine=InnoDB

Ve MySql v5.5 veya sonraki bir sürümdeyseniz , InnoDB varsayılan motordur, bu yüzden yukarıdaki gibi açıkça ayarlamanıza gerek yoktur, sadece dosyanızdan default-storage-engine=MYISAMvarsa ve kaldırmaya hazırsanız kaldırın ini.


Teşekkürler! Ben laravel 6 ve mysql 5.6 ile çalışmak için bu öneri dize uzunluğu, karakter kümesi ve harmanlama değişiklikleri ile birlikte kullanmak zorunda kaldı. Umarım bu gelecekte başkalarına yardımcı olur.
Casper Wilkes

@CasperWilkes, o dize uzunluğundan, karakter kümesinden herhangi bir şey yapmanız gerekmiyor. Mysql sistem değişkeninizi AÇIKshow global variables like 'innodb_large_prefix'; olması gerektiği gibi kontrol edin . E? Er KAPALI o zaman kontrol edebilirsiniz bu açmak nasıl cevap. Ve burada dev.mysql.com üzerinde innodb_large_prefix hakkında daha fazla bilgi.
Ali A. Dhillon

3

AppServiceProvider'da değiştirmek istiyorsanız taşıma sırasında e-posta alanının uzunluğunu tanımlamanız gerekir. sadece kodun ilk satırını ikinci satıra değiştirin.

create_users_table

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

create_password_resets_table

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

Başarılı bir şekilde değiştirildikten sonra taşımayı çalıştırabilirsiniz.
Not: önce (varsa) kullanıcı tablosunu , password_resets tablosunu silmeniz gerekir veritabanından ve kullanıcıları ve password_resets girdilerini taşıma tablosundan silmeniz gerekir.


3

Schema::defaultStringLength(191);varsayılan olarak tüm dizelerin (191) uzunluğunu tanımlar ve bu da veritabanınızı bozabilir. Bu şekilde gitmemelisin.

Veritabanı geçiş sınıfındaki herhangi bir sütunun uzunluğunu tanımlamanız yeterlidir. Örneğin, CreateUsersTablesınıfta "name", "username" ve "email" tanımlarını aşağıdaki gibi yapıyorum :

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
Laravel'in çekirdek kodlarını değiştirmek istemediğim için bu benim için en çok tercih edilen.
Okiemute Omuta

2

Laravel 5.4, varsayılan veritabanı karakter setini utf8mb4 olarak değiştirdiğinden bu durum yaygındır. Yapmanız gereken şudur: Bu kodu sınıf bildiriminden önce koyarak App \ Providers.php dosyanızı düzenlemek

use Illuminate\Support\Facades\Schema;

Ayrıca, bunu 'boot' işlevine ekleyin Schema::defaultStringLength(191);


2

Veritabanınıza atanmış herhangi bir veriniz yoksa aşağıdakileri yapın:

  1. App / Providers / AppServiceProvide.php adresine gidin ve ekleyin

Illuminate \ Support \ ServiceProvider kullanın;

ve boot () yönteminin içi;

Şema :: defaultStringLength (191);

  1. Şimdi veritabanınızdaki kayıtları silin.

  2. aşağıdakileri çalıştır

php artisan yapılandırma: önbellek

php esnaf göç


Çalıştı ama eklemeniz gerekiyor use Illuminate\Support\Facades\Schema; use Illuminate\Support\ServiceProvider;zaten. Umarım düzeltirsiniz
Jimish Gamit

2

Bunu düzeltmek için Geçişler kılavuzunda belirtildiği gibi, yapmanız gereken tek şey AppServiceProvider.php dosyanızı düzenlemek ve önyükleme yönteminin içinde varsayılan bir dize uzunluğu ayarlamaktır:

//edit your AppServiceProvider.php file contains in providers folder
use Illuminate\Support\Facades\Schema;

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

Umarım bu size yardımcı olacaktır ..


2

Aşağıdaki satırı değiştirdim usersvepassword_resets taşıma dosyasını değiştirdik.

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

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



1

StringLenght'i 191'e zorlamak gerçekten kötü bir fikir. Neler olup bittiğini anlamak için araştırıyorum.

Bu mesaj hatası fark ettim:

SQLSTATE [42000]: Sözdizimi hatası veya erişim ihlali: 1071 Belirtilen anahtar çok uzun; maksimum anahtar uzunluğu 767 bayttır

MySQL sürümümü güncelledikten sonra görünmeye başladı. Bu yüzden PHPMyAdmin ile tabloları kontrol ettim ve oluşturulan tüm yeni tabloların utf8_unicode_ci yerine utf8mb4_unicode_ci harmanlamasıyla olduğunu fark ettim. eskileri için .

Doktrin yapılandırma dosyamda, charset'in utf8mb4 olarak ayarlandığını fark ettim, ancak önceki tüm tablolarım utf8'de oluşturuldu, bu yüzden bu utf8mb4 üzerinde çalışmaya başlayan bazı güncelleme büyüsü olduğunu tahmin ediyorum.

Şimdi kolay düzeltme ORM yapılandırma dosyanızdaki çizgi karakter kümesini değiştirmektir. Sonra devf modunda iseniz tabloları utf8mb4_unicode_ci kullanarak bırakmak veya bırakamıyorsanız karakter kümesini düzeltmek.

Symfony 4 için

değişim charset: utf8mb4 için charset: utf8 içinde config / paketler / doctrine.yaml

Şimdi doktrin göçlerim yine iyi çalışıyor.


1

Önerilen çözüm, innodb_large_prefix sonraki sorunlara girmemeniz için MySQL seçeneğini . İşte bunu nasıl yapacağınız:

my.iniMySQL yapılandırma dosyasını açın ve aşağıdaki satırları aşağıdaki [mysqld]gibi ekleyin .

[mysqld]
innodb_file_format = Barracuda
innodb_large_prefix = 1
innodb_file_per_table = ON

Bundan sonra değişikliklerinizi kaydedin ve MySQL hizmetinizi yeniden başlatın.

Taşıma işleminizi yapmanız ve ardından yeniden çalıştırmanız gerekiyorsa geri alma.


Sorununuzun devam etmesi durumunda, veritabanı yapılandırma dosyanıza gidin ve

'engine' => null, için 'engine' => 'innodb row_format=dynamic'

Umarım yardımcı olur!


1

önce localhost'ta veritabanının tüm tablolarını sil

Config / database.php dosyasındaki Laravel varsayılan veritabanı (utf8mb4) özelliklerini şu şekilde değiştirin:

'charset' => 'utf8', 'harmanlama' => 'utf8_unicode_ci',

daha sonra utf8_unicode_ci yerel veritabanı özelliklerimi değiştirme. php esnaf göç ok.


0

Bunun içine girebilecek herkes için, benim sorunum bir tür sütun stringyapmak ve ->unsigned()bir tamsayı demek istedim bunu yapmaya çalışıyordu oldu .


0

Buradaki çalışmanın, anahtar adıyla (kısa bir tane) ikinci bir parametre geçmesi oldu:

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

0

Zaten vardı bile bu hatayı alıyordum (aslında çünkü zaten vardı ) alıyordum Schema :: defaultStringLength (191); AppServiceProvider.php dosyamda.

Çünkü 191'den daha yüksek bir değere geçişlerimden birinde dize değeri ayarlamaya çalışıyordum:

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'i kaldırmak veya 191 olarak ayarlamak sorunumu çözdü.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.