Errore di migrazione Laravel: errore di sintassi o violazione di accesso: 1071 La chiave specificata era troppo lunga; la lunghezza massima della chiave è 767 byte


178

Errore di migrazione su Laravel 5.4 con php artisan make:auth

[Illuminate \ Database \ QueryException] SQLSTATE [42000]: errore di sintassi o violazione di accesso: 1071 La chiave specificata era troppo lunga; la lunghezza massima della chiave è 767 byte (SQL: alter tabl e usersadd unique users_email_unique( email))

[PDOException] SQLSTATE [42000]: errore di sintassi o violazione di accesso: 1071 La chiave specificata era troppo lunga; la lunghezza massima della chiave è 767 byte


3
Dovresti rispondere alla tua domanda in una risposta. Non nella domanda. stackoverflow.com/help/self-answer
Can Vural

Grazie per il suggerimento @ can-vural, l'ho fatto.
absiddiqueVive il

Risposte:


283

Secondo la documentazione ufficiale , puoi risolverlo abbastanza facilmente.

Aggiungi le seguenti due righe di codice ad AppServiceProvider.php (/app/Providers/AppServiceProvider.php)

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

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

MySQL riserva sempre l'importo massimo per un campo UTF8 che è di 4 byte, quindi con 255 + 255 con il SET DI CARATTERI PREDEFINITO utf8mb4 COLLATE utf8mb4_unicode_ci; hai superato il limite di lunghezza massima della chiave 767. Di @scaisedge


3
Fai attenzione a questa soluzione. Ad esempio, se si indicizzano i campi e-mail, le e-mail memorizzate possono avere una lunghezza massima di 191 caratteri. Questo è inferiore agli stati RFC ufficiali.
shock_gone_wild


Funziona ed è una soluzione valida, ma volevo solo sottolineare che ci sono possibili insidie ​​usando questo approccio.
shock_gone_wild,

Spero che questa soluzione non mi morda nel culo in futuro, ma per ora funziona. Dovrò stare attento a come indicizzo le email però.
deusofnull,

4
perché esattamente 191 caratteri @absiddiqueLive
PseudoAj

121

Non so perché la soluzione di cui sopra e la soluzione ufficiale che sta aggiungendo

Schema::defaultStringLength(191);

in AppServiceProvidernon ha funzionato per me. Ciò che ha funzionato è stato la modifica del database.phpfile nella configcartella. Modifica

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

per

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

e dovrebbe funzionare, anche se non sarai in grado di memorizzare caratteri multibyte estesi come le emoji .

L'ho fatto con Laravel 5.7. Spero che sia d'aiuto.


5
L'uso di questo set di caratteri ti consentirà solo di salvare ASCII standard e non caratteri speciali multibyte come quelli di arabo, ebraico, la maggior parte degli script europei e, naturalmente, emoji. vedi anche stackoverflow.com/a/15128103/4233593
Jeff Puckett,

7
Penso che ti sia sfuggita questa parte use Illuminate\Support\Facades\Schema;in alto.
pimpace,

@KoushikDas quale versione di Laravel stai usando?
brufolo

Ora sono su 6.0. Penso di averlo fatto inizialmente con 5.7 o 5.6 forse.
Koushik Das,

2
La utf8mb4raccolta è lì per un motivo, ti consiglio di usarla se puoi.
Fiamma il

85

Sto solo aggiungendo questa risposta qui perché è la quickestsoluzione per me. Basta impostare il motore di database di default per 'InnoDB'il

/config/database.php

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

quindi eseguire php artisan config:cacheper cancellare e aggiornare la cache di configurazione


1
Questa dovrebbe essere la risposta / soluzione ufficiale a questa domanda ... Grazie
Syamsoul Azrien,

1
Questa è la soluzione reale, altri sono soluzioni alternative
Luís Cunha,

3
ma qual è la logica dietro questo
Zulfiqar Tariq,

1
Questa è la soluzione corretta. Ma perché non è stato incluso nell'installazione predefinita.
Ankit Chauhan,

38

Nel AppServiceProvider.php, includi questo codice all'inizio del file.

use Illuminate\Support\Facades\Schema;

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

Grazie, mi ha aiutato
The Dead Man il

24

Questo problema è causato in Laravel 5.4 dalla versione del database.

Secondo i documenti (nella Index Lengths & MySQL / MariaDBsezione):

Laravel utilizza il utf8mb4set di caratteri per impostazione predefinita, che include il supporto per la memorizzazione di "emoji" nel database. Se si esegue una versione di MySQL precedente alla versione 5.7.7 o MariaDB precedente alla versione 10.2.2, potrebbe essere necessario configurare manualmente la lunghezza della stringa predefinita generata dalle migrazioni per consentire a MySQL di creare gli indici per esse. Puoi configurarlo chiamando il Schema::defaultStringLengthmetodo nel tuo AppServiceProvider.

In altre parole, in <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);
}

// ...

}

Ma come dice il commento sull'altra risposta:

Fai attenzione a questa soluzione. Ad esempio, se si indicizzano i campi e-mail, le e-mail memorizzate possono avere una lunghezza massima di 191 caratteri. Questo è inferiore agli stati RFC ufficiali.

Quindi la documentazione propone anche un'altra soluzione:

In alternativa, è possibile abilitare l' innodb_large_prefixopzione per il database. Fare riferimento alla documentazione del database per istruzioni su come abilitare correttamente questa opzione.


16

Per qualcuno che non vuole cambiare AppServiceProvider.php. (Secondo me, è una cattiva idea cambiare AppServiceProvider.phpsolo per la migrazione)

È possibile aggiungere nuovamente la lunghezza dei dati al file di migrazione database/migrations/come di seguito:

create_users_table.php

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

create_password_resets_table.php

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

Questo può essere un problema poiché le e-mail possono avere un massimo di 255 caratteri (ish)
Half Crazed,

Hai ragione @HalfCrazed, ma vi suggerisco questa risposta stackoverflow.com/questions/1297272
helloroy

il mio problema era esattamente risolvibile con questa soluzione. I miei campi non erano e-mail.
Tharaka Devinda,

11

Se riscontri questo errore mentre lavori su laravel mentre usi il comando: php artisan migrate allora aggiungi solo 2 righe nel file: app-> Provider-> AppServiceProvider.php

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

per favore controlla questa immagine . quindi eseguire php artisan migratenuovamente il comando.


1
è molto importante aggiungere "usa Schema;". Quindi questa è la risposta migliore
hxwtch,

Puoi anche farlo in una riga aggiungendo una barra rovesciata "\" prima della seconda riga in questo modo\Schema::defaultStringLength(191);
Tahir Afridi,

10

Sto aggiungendo due sollution che funzionano per me.

Il primo sollution è :

  1. Apri il file database.php nella cartella / directory di configurazione .
  2. Modifica 'engine' => null,in'engine' => 'InnoDB',

    Questo ha funzionato per me.

2 ° sollution è:

  1. Apri il file database.php nella cartella / directory di configurazione .
    2. Modifica
    'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci',
    in

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


In bocca al lupo


10

aggiorna e inserisci queste righe in app / Provider / AppServiceProvider.php

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

Ho risolto questo problema e modificato il mio file config-> database.php in modo che mi piacesse il mio database ('charset' => 'utf8') e il ('collation' => 'utf8_general_ci') , quindi il mio problema è stato risolto come Seguire:

'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

Ho trovato due soluzioni per questo errore

OPZIONE 1:

Aprire la tabella utente e password_reset nella cartella database / migrations

E basta cambiare la lunghezza dell'email:

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

OPZIONE 2:

Apri il tuo app/Providers/AppServiceProvider.phpfile e all'interno del boot()metodo imposta una lunghezza di stringa predefinita:

use Illuminate\Support\Facades\Schema;

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

7

1- Vai a /config/database.phpe trova queste righe

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

e cambiali in:

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

2- Esegui php artisan config:cacheper riconfigurare laravel

3- Eliminare le tabelle esistenti nel database e quindi eseguirle php artisan migratenuovamente


1
questa è la risposta migliore per laravel 5.8. Ma elimina le tabelle già create
Magige Daniel,

ma secondo la documentazione "utf8" utilizzerà la modalità deprecata utf8 però?
NoBugs,

5

Nel file AppServiceProvider.php :

 use Illuminate\Support\Facades\Schema;

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

5

Invece di fissare un limite di lunghezza, proporrei quanto segue, che ha funzionato per me.

Dentro:

config / database.php

sostituire questa riga per mysql:

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

con:

'engine' => null,

4

Come indicato nella Guida alle migrazioni per risolvere questo problema, tutto ciò che devi fare è modificare il tuo app/Providers/AppServiceProvider.phpfile e all'interno del metodo di avvio impostare una lunghezza di stringa predefinita:

use Illuminate\Support\Facades\Schema;

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

Nota: per prima cosa è necessario eliminare la tabella degli utenti (se presente) , la tabella password_resets dal database ed eliminare le voci utenti e password_resets dalla tabella delle migrazioni .

Per eseguire tutte le migrazioni in sospeso, esegui il migratecomando Artisan:

php artisan migrate

Dopodiché tutto dovrebbe funzionare normalmente.


4

Come già specificato, aggiungiamo a AppServiceProvider.php in App / Provider

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

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

puoi vedere maggiori dettagli nel link qui sotto (cerca "Index Lengths & MySQL / MariaDB") https://laravel.com/docs/5.5/migrations

MA BENE NON è quello di cui ho pubblicato tutto! il fatto è che anche quando si esegue quanto sopra è probabile che si verifichi un altro errore (quando si esegue il php artisan migratecomando e a causa del problema della lunghezza, l'operazione sarà probabilmente bloccata nel mezzo. La soluzione è sotto e la tabella utente viene probabilmente creata senza il resto o non del tutto correttamente) dobbiamo tornare indietro . il rollback predefinito non funzionerà. perché l'operazione di migrazione non ha gradito il completamento. è necessario eliminare manualmente le nuove tabelle create nel database.

possiamo farlo usando armeggiare come di seguito:

L:\todos> php artisan tinker

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

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

=> null

Io stesso ho avuto un problema con la tabella degli utenti.

dopodiché sei a posto

php artisan migrate:rollback

php artisan migrate


4

La soluzione che nessuno dice è che in Mysql v5.5 e successive InnoDB è il motore di archiviazione predefinito che non presenta questo problema ma in molti casi come il mio ci sono alcuni vecchi file di configurazione di mysql ini che utilizzano il vecchio motore di archiviazione MYISAM come di seguito.

default-storage-engine=MYISAM

che sta creando tutti questi problemi e la soluzione è cambiare il motore di archiviazione predefinito in InnoDB nel file di configurazione ini di Mysql una volta per tutte invece di fare hack temporanei.

default-storage-engine=InnoDB

E se sei su MySql v5.5 o versioni successive, InnoDB è il motore predefinito, quindi non è necessario impostarlo in modo esplicito come sopra, rimuovi semplicemente default-storage-engine=MYISAMse esiste dal tuo inifile e sei a posto.


Grazie! Ho dovuto usare questo suggerimento insieme alle modifiche di lunghezza della stringa, set di caratteri e regole di confronto per farlo funzionare con laravel 6 e mysql 5.6. Spero che questo aiuti gli altri in futuro.
Casper Wilkes,

@CasperWilkes non devi fare niente di quella lunghezza di stringa, roba charset. Controlla la tua variabile di sistema Mysql in questo show global variables like 'innodb_large_prefix';modo dovrebbe essere ON . Se è OFF , puoi controllare questa risposta su come attivarla. Ed ecco ulteriori informazioni su innodb_large_prefix su dev.mysql.com.
Ali A. Dhillon,

3

Se si desidera modificare AppServiceProvider, è necessario definire la lunghezza del campo e-mail durante la migrazione. basta sostituire la prima riga di codice nella seconda riga.

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

Dopo aver modificato correttamente è possibile eseguire la migrazione.
Nota: per prima cosa è necessario eliminare la tabella degli utenti (se presente) , la tabella password_resets dal database ed eliminare le voci utenti e password_resets dalla tabella di migrazione.


3

Schema::defaultStringLength(191);definirà la lunghezza di tutte le stringhe 191 per impostazione predefinita che potrebbe rovinare il database. Non devi andare così.

Basta definire la lunghezza di qualsiasi colonna specifica nella classe di migrazione del database. Ad esempio, sto definendo "nome", "nome utente" ed "e-mail" nella CreateUsersTableclasse come di seguito:

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
Questo è preferibile per me poiché preferirei non modificare alcun codice core Laravel.
Okiemute Omuta,

2

Ciò è comune poiché Laravel 5.4 ha modificato il carattere predefinito del database impostato su utf8mb4. Quello che devi fare è: modificare la tua App \ Providers.php inserendo questo codice prima della dichiarazione di classe

use Illuminate\Support\Facades\Schema;

Inoltre, aggiungi questo alla funzione 'avvio' Schema::defaultStringLength(191);


2

Se non hai già assegnato dati al tuo database, procedi come segue:

  1. Vai su app / Provider / AppServiceProvide.php e aggiungi

usa Illuminate \ Support \ ServiceProvider;

e all'interno del metodo boot ();

Schema :: defaultStringLength (191);

  1. Ora elimina i record nel tuo database, tabella utente per es.

  2. eseguire il seguente

php artisan config: cache

php artigiano migrare


Ha funzionato ma è necessario aggiungere use Illuminate\Support\Facades\Schema; use Illuminate\Support\ServiceProvider;è già lì. Spero che tu l'abbia corretto
Jimish Gamit,

2

Come indicato nella Guida alle migrazioni per risolvere questo problema, tutto ciò che devi fare è modificare il tuo file AppServiceProvider.php e all'interno del metodo di avvio impostare una lunghezza di stringa predefinita:

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

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

Spero che questo ti possa aiutare ...


2

Ho appena modificato seguente riga in userse password_resetsfile di migrazione.

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

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



1

Penso che forzare StringLenght a 191 sia una pessima idea. Quindi indago per capire cosa sta succedendo.

Ho notato che questo messaggio di errore:

SQLSTATE [42000]: errore di sintassi o violazione di accesso: 1071 La chiave specificata era troppo lunga; la lunghezza massima della chiave è 767 byte

Ho iniziato a mostrarmi dopo aver aggiornato la mia versione di MySQL. Quindi ho controllato le tabelle con PHPMyAdmin e ho notato che tutte le nuove tabelle create erano con le regole di confronto utf8mb4_unicode_ci anziché utf8_unicode_ci per quelle vecchie.

Nel mio file di configurazione dottrina, ho notato che charset era impostato su utf8mb4, ma tutte le mie tabelle precedenti sono state create in utf8, quindi immagino che questo sia un aggiornamento magico che inizia a funzionare su utf8mb4.

Ora la soluzione semplice è cambiare il set di righe nel tuo file di configurazione ORM. Quindi rilasciare le tabelle usando utf8mb4_unicode_ci se si è in modalità dev o correggere il set di caratteri se non è possibile rilasciarle.

Per Symfony 4

cambia charset: utf8mb4 in charset: utf8 in config / pacchetti / doctrine.yaml

Ora le migrazioni della mia dottrina stanno funzionando di nuovo bene.


1

La soluzione consigliata è abilitare l' innodb_large_prefixopzione di MySQL in modo da non incorrere in problemi successivi. Ed ecco come farlo:

Apri il my.inifile di configurazione di MySQL e aggiungi le righe sottostanti sotto la [mysqld]riga in questo modo.

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

Successivamente, salva le modifiche e riavvia il servizio MySQL.

Eseguire il rollback se è necessario e rieseguire la migrazione.


Nel caso in cui il problema persista, andare al file di configurazione del database e impostare

'engine' => null, per 'engine' => 'innodb row_format=dynamic'

Spero che sia d'aiuto!


1

eliminare innanzitutto tutte le tabelle del database nell'host locale

Cambia le proprietà del database predefinito Laravel (utf8mb4) nel file config / database.php in:

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

dopo aver modificato le proprietà del mio database locale utf8_unicode_ci. php artigiano migrare è ok.


0

Per chiunque potesse imbattersi in questo, il mio problema era che stavo creando una colonna di tipo stringe provavo a farcela ->unsigned()quando volevo che fosse un numero intero.


0

Si avvicinò che il lavoro qui era passare un secondo parametro con il nome della chiave (uno breve):

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

0

Stavo ottenendo questo errore anche se avevo già (in realtà perché avevo già) Schema :: defaultStringLength (191); nel mio file AppServiceProvider.php.

Il motivo è perché stavo cercando di impostare un valore di stringa in una delle mie migrazioni su un valore superiore a 191:

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

Rimuovere il 1000 o impostarlo su 191 ha risolto il mio problema.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.