Laravel-Migrationsfehler: Syntaxfehler oder Zugriffsverletzung: 1071 Der angegebene Schlüssel war zu lang. Die maximale Schlüssellänge beträgt 767 Byte

177

Migrationsfehler auf Laravel 5.4 mit php artisan make:auth

[Illuminate \ Database \ QueryException] SQLSTATE [42000]: Syntaxfehler oder Zugriffsverletzung: 1071 Der angegebene Schlüssel war zu lang. Die maximale Schlüssellänge beträgt 767 Byte (SQL: alter tabl e usersadd unique users_email_unique( email))

[PDOException] SQLSTATE [42000]: Syntaxfehler oder Zugriffsverletzung: 1071 Der angegebene Schlüssel war zu lang. Die maximale Schlüssellänge beträgt 767 Byte

absiddiqueLive
quelle
3
Sie sollten Ihre Frage in einer Antwort beantworten. Nicht in der Frage. stackoverflow.com/help/self-answer
Can Vural
Vielen Dank für den Vorschlag @ can-vural, den ich gemacht habe.
absiddiqueLive

Antworten:

283

Laut offizieller Dokumentation können Sie dies ganz einfach lösen.

Fügen Sie AppServiceProvider.php die folgenden zwei Codezeilen hinzu (/app/Providers/AppServiceProvider.php)

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

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

MySQL reserviert immer den maximalen Betrag für ein UTF8-Feld, das 4 Bytes beträgt, also mit 255 + 255 mit Ihrem DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; Sie haben die maximale Schlüssellänge von 767 überschritten. Von @scaisedge

absiddiqueLive
quelle
3
Seien Sie vorsichtig mit dieser Lösung. Wenn Sie beispielsweise E-Mail-Felder indizieren, können gespeicherte E-Mails nur eine maximale Länge von 191 Zeichen haben. Dies ist weniger als die offiziellen RFC-Staaten.
Schock_gone_wild
1
Diese Lösung vorschlagen durch Laravel github.com/laravel/framework/issues/17508 laracasts.com/discuss/channels/laravel/...
absiddiqueLive
Es funktioniert und ist eine gültige Lösung, aber ich wollte nur darauf hinweisen, dass es bei diesem Ansatz mögliche Fallstricke gibt.
Schock_gone_wild
Ich hoffe, diese Lösung wird mich in Zukunft nicht in den Arsch beißen, aber im Moment funktioniert das. Ich muss allerdings vorsichtig sein, wie ich E-Mails indiziere.
Deusofnull
4
warum genau 191 Zeichen @absiddiqueLive
PseudoAj
121

Ich weiß nicht, warum die obige Lösung und die offizielle Lösung, die hinzugefügt wird

Schema::defaultStringLength(191);

in AppServiceProviderhat bei mir nicht funktioniert. Was funktionierte, war das Bearbeiten der database.phpDatei im configOrdner. Einfach bearbeiten

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

zu

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

und es sollte funktionieren, obwohl Sie keine erweiterten Multibyte-Zeichen wie Emoji speichern können .

Ich habe es mit Laravel 5.7 gemacht. Ich hoffe es hilft.

Koushik Das
quelle
5
Mit diesem Zeichensatz können Sie nur Standard-ASCII speichern und keine Multibyte-Sonderzeichen wie Arabisch, Hebräisch, die meisten europäischen Skripte und natürlich Emoji. siehe auch stackoverflow.com/a/15128103/4233593
Jeff Puckett
7
Ich denke, Sie haben diesen Teil use Illuminate\Support\Facades\Schema;oben verpasst .
Zuhälter
@KoushikDas welche Version von Laravel benutzt du?
Zuhälter
Jetzt bin ich auf 6.0. Ich glaube, ich habe es anfangs vielleicht mit 5.7 oder 5.6 gemacht.
Koushik Das
2
Die utf8mb4Zusammenstellung ist aus einem bestimmten Grund vorhanden. Ich empfehle, sie zu verwenden, wenn Sie können.
Flamme
85

Ich füge hier nur diese Antwort hinzu, da dies die quickestLösung für mich ist. Setzen Sie einfach das Standard-Datenbankmodul 'InnoDB'auf Ein

/config/database.php

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

Führen Sie dann aus php artisan config:cache, um den Konfigurationscache zu löschen und zu aktualisieren

Dexter Bengil
quelle
1
Dies sollte die offizielle Antwort / Lösung auf diese Frage sein ... Danke
Syamsoul Azrien
1
Dies ist die eigentliche Lösung, andere sind Problemumgehungen
Luís Cunha
3
aber was ist die Logik dahinter
Zulfiqar Tariq
1
Das ist die richtige Lösung. Aber warum nicht wurde es in die Standardinstallation aufgenommen.
Ankit Chauhan
38

In der AppServiceProvider.phpfügen Sie diesen Code oben in die Datei ein.

use Illuminate\Support\Facades\Schema;

public function boot()
{
Schema::defaultStringLength(191);
}
user7688086
quelle
Danke hat mir geholfen
The Dead Man
24

Dieses Problem wird in Laravel 5.4 durch die Datenbankversion verursacht.

Gemäß den Dokumenten (im Index Lengths & MySQL / MariaDBAbschnitt):

Laravel verwendet utf8mb4standardmäßig den Zeichensatz, der die Speicherung von "Emojis" in der Datenbank unterstützt. Wenn Sie eine Version von MySQL ausführen, die älter als die Version 5.7.7 oder MariaDB älter als die Version 10.2.2 ist, müssen Sie möglicherweise die durch Migrationen generierte Standardzeichenfolgenlänge manuell konfigurieren, damit MySQL Indizes für sie erstellt. Sie können dies konfigurieren, indem Sie die Schema::defaultStringLengthMethode in Ihrem aufrufen AppServiceProvider.

Mit anderen Worten, 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);
}

// ...

}

Aber wie der Kommentar zur anderen Antwort sagt:

Seien Sie vorsichtig mit dieser Lösung. Wenn Sie beispielsweise E-Mail-Felder indizieren, können gespeicherte E-Mails nur eine maximale Länge von 191 Zeichen haben. Dies ist weniger als die offiziellen RFC-Staaten.

Die Dokumentation schlägt also auch eine andere Lösung vor:

Alternativ können Sie die innodb_large_prefixOption für Ihre Datenbank aktivieren . Anweisungen zum ordnungsgemäßen Aktivieren dieser Option finden Sie in der Dokumentation Ihrer Datenbank.

Esteban Herrera
quelle
16

Für jemanden, der sich nicht ändern will AppServiceProvider.php. (Meiner Meinung nach ist es eine schlechte Idee, AppServiceProvider.phpnur für die Migration zu ändern )

Sie können die Datenlänge wie folgt zur Migrationsdatei hinzufügen database/migrations/:

create_users_table.php

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

create_password_resets_table.php

$table->string('email',128)->index();
Helloroy
quelle
Dies kann ein Problem sein, da E-Mails bis zu 255 (ish) Zeichen lang sein können
Half Crazed
Sie haben Recht @HalfCrazed, aber ich schlage diese Antwort stackoverflow.com/questions/1297272
helloroy
Mein Problem war durch diese Lösung genau lösbar. Meine Felder waren keine E-Mails.
Tharaka Devinda
11

Wenn dieser Fehler bei der Arbeit an Laravel während der Verwendung des Befehls auftritt, php artisan migrate fügen Sie der Datei einfach zwei Zeilen hinzu: app-> Providers-> AppServiceProvider.php

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

Bitte überprüfen Sie dieses Bild . Führen Sie dann den php artisan migrateBefehl erneut aus.

Abdul Rasheed
quelle
1
Es ist sehr wichtig, 'use Schema;' hinzuzufügen. Das ist also die beste Antwort
hxwtch
Sie können dies auch in einer Zeile tun, indem Sie vor der zweiten Zeile einen Schrägstrich '\' \Schema::defaultStringLength(191);
einfügen
10

Ich füge zwei Sollutionen hinzu , die für mich funktionieren.

1. sollution ist :

  1. Öffnen database.php Datei insde config - dir / Ordner.
  2. Bearbeiten 'engine' => null,zu'engine' => 'InnoDB',

    Das hat bei mir funktioniert.

2. sollution ist:

  1. Öffnen database.php Datei insde config - dir / Ordner.
    2. Bearbeiten
    'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci',
    auf

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


Viel Glück

Arslan Ahmad
quelle
10

Aktualisieren und fügen Sie diese Zeilen in app / Providers / AppServiceProvider.php ein

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

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

Ich habe dieses Problem gelöst und meine Datei config-> database.php so bearbeitet, dass sie meiner Datenbank ('charset' => 'utf8') und der ('collation' => 'utf8_general_ci') entspricht , sodass mein Problem mit dem Code als gelöst ist Folgen:

'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,
    ],
Ahmad Shakib
quelle
8

Ich habe zwei Lösungen für diesen Fehler gefunden

OPTION 1:

Öffnen Sie Ihre Tabelle user und password_reset im Ordner database / migrations

Und ändern Sie einfach die Länge der E-Mail:

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

OPTION 2:

Öffnen Sie Ihre app/Providers/AppServiceProvider.phpDatei und boot()legen Sie innerhalb der Methode eine Standardzeichenfolgenlänge fest:

use Illuminate\Support\Facades\Schema;

public function boot()
{
    Schema::defaultStringLength(191);
}
Udhav Sarvaiya
quelle
7

1- Gehen Sie zu /config/database.phpund finden Sie diese Zeilen

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

und ändern Sie sie zu:

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

2- Führen Sie php artisan config:cachediese Option aus, um die Laravel neu zu konfigurieren

3- Löschen Sie die vorhandenen Tabellen in Ihrer Datenbank und führen Sie sie php artisan migrateerneut aus

mohammad asghari
quelle
1
Dies ist die beste Antwort für Laravel 5.8. Aber löschen Sie bereits erstellte Tabellen
Magige Daniel
aber laut Dokumentation wird "utf8" den veralteten utf8-Modus verwenden?
NoBugs
5

In der Datei AppServiceProvider.php :

 use Illuminate\Support\Facades\Schema;

public function boot()
{
    Schema::defaultStringLength(191);
}
Uddyan Semwal
quelle
5

Anstatt eine Längenbeschränkung festzulegen, würde ich Folgendes vorschlagen, was für mich funktioniert hat.

Innerhalb:

config / database.php

Ersetzen Sie diese Zeile für MySQL:

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

mit:

'engine' => null,
Md. Noor-A-Alam Siddique
quelle
4

Wie in dem Migrations skizzierte führen , dies zu beheben, alles , was Sie tun müssen, ist Ihre bearbeiten app/Providers/AppServiceProvider.phpDatei und in der Boot - Methode eingestellte Länge einer Standardzeichenfolge:

use Illuminate\Support\Facades\Schema;

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

Hinweis: Zuerst müssen Sie die Benutzertabelle, die Tabelle password_resets aus der Datenbank löschen (falls vorhanden) und die Einträge user und password_resets aus der Migrationstabelle löschen .

Führen Sie den migrateBefehl Artisan aus , um alle ausstehenden Migrationen auszuführen :

php artisan migrate

Danach sollte alles wie gewohnt funktionieren.

Dexter Bengil
quelle
4

Wie bereits angegeben, fügen wir der AppServiceProvider.php in App / Providers hinzu

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

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

Weitere Details finden Sie im folgenden Link (Suche nach "Indexlängen & MySQL / MariaDB") https://laravel.com/docs/5.5/migrations

ABER GUT, darüber habe ich nicht alles veröffentlicht! Selbst wenn Sie die oben genannten Schritte ausführen, wird wahrscheinlich ein weiterer Fehler angezeigt (wenn Sie den php artisan migrateBefehl ausführen und aufgrund des Problems der Länge der Vorgang wahrscheinlich in der Mitte hängen bleibt. Die Lösung befindet sich unten und die Benutzertabelle wird wahrscheinlich erstellt ohne den Rest oder nicht ganz richtig) müssen wir zurückrollen . Das Standard-Rollback funktioniert nicht. weil der Vorgang der Migration nicht gerne beendet wurde. Sie müssen die neu erstellten Tabellen in der Datenbank manuell löschen.

wir können es mit basteln wie unten machen:

L:\todos> php artisan tinker

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

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

=> null

Ich selbst hatte ein Problem mit der Benutzertabelle.

Danach können Sie loslegen

php artisan migrate:rollback

php artisan migrate

Mohamed Allal
quelle
4

Die Lösung, die niemand sagt, ist, dass InnoDB in MySQL v5.5 und höher die Standard-Speicher-Engine ist, die dieses Problem nicht hat, aber in vielen Fällen wie meinen gibt es einige alte MySQL-INI- Konfigurationsdateien, die die alte MYISAM- Speicher-Engine wie unten verwenden.

default-storage-engine=MYISAM

die all diese Probleme schafft und die Lösung zu ändern default-storage-Engine InnoDB in der der Mysql ini - Konfigurationsdatei ein für alle Mal statt temporäre Hacks zu tun.

default-storage-engine=InnoDB

Und wenn Sie mit MySql v5.5 oder höher arbeiten, ist InnoDB die Standard-Engine, sodass Sie es nicht explizit wie oben festlegen müssen. Entfernen default-storage-engine=MYISAMSie einfach das, wenn es in Ihrer iniDatei vorhanden ist, und Sie können loslegen.

Ali A. Dhillon
quelle
Vielen Dank! Ich musste diesen Vorschlag in Verbindung mit den Änderungen der Zeichenfolgenlänge, des Zeichensatzes und der Sortierung verwenden, damit dies mit Laravel 6 und MySQL 5.6 funktioniert. Hoffentlich hilft dies anderen in der Zukunft.
Casper Wilkes
@CasperWilkes Sie müssen nichts von dieser Zeichenkettenlänge, Zeichensatz-Sachen machen. Überprüfen Sie Ihre Mysql Systemvariable wie dies show global variables like 'innodb_large_prefix';sollte es sein , ON . Wenn es OFF dann können Sie überprüfen , diese Antwort, wie man es einschalten. Und hier ist mehr Informationen über innodb_large_prefix auf dev.mysql.com.
Ali A. Dhillon
3

Wenn Sie in AppServiceProvider ändern möchten, müssen Sie die Länge des E-Mail-Felds bei der Migration definieren. Ersetzen Sie einfach die erste Codezeile durch die zweite.

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

Nach erfolgreichen Änderungen können Sie die Migration ausführen.
Hinweis: Zuerst müssen Sie löschen (wenn Sie haben) Benutzer - Tabelle , password_resets Tabelle aus der Datenbank und löschen Benutzer und password_resets Einträge aus Migrationstabelle.

Chintan Kotadiya
quelle
3

Schema::defaultStringLength(191);definiert standardmäßig die Länge aller Zeichenfolgen 191, die Ihre Datenbank ruinieren können. Du darfst diesen Weg nicht gehen.

Definieren Sie einfach die Länge einer bestimmten Spalte in der Datenbankmigrationsklasse. Zum Beispiel definiere ich den "Namen", "Benutzernamen" und "E-Mail" in der CreateUsersTableKlasse wie folgt:

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();
        });
    }
Fatema T. Zuhora
quelle
1
Dies ist für mich am besten vorzuziehen, da ich lieber keine Laravel-Kerncodes optimieren möchte.
Okiemute Omuta
2

Dies ist häufig der Fall, da Laravel 5.4 den Standard-Datenbankcharater auf utf8mb4 geändert hat. Was Sie tun müssen, ist: Bearbeiten Sie Ihre App \ Providers.php, indem Sie diesen Code vor die Klassendeklaration setzen

use Illuminate\Support\Facades\Schema;

Fügen Sie dies auch der Boot-Funktion hinzu Schema::defaultStringLength(191);

Schatz
quelle
2

Wenn Ihrer Datenbank noch keine Daten zugewiesen sind, gehen Sie wie folgt vor:

  1. Gehen Sie zu app / Providers / AppServiceProvide.php und fügen Sie hinzu

Verwenden Sie Illuminate \ Support \ ServiceProvider.

und innerhalb der Methode boot ();

Schema :: defaultStringLength (191);

  1. Löschen Sie nun die Datensätze in Ihrer Datenbank, z. B. Benutzertabelle.

  2. Führen Sie Folgendes aus

PHP Artisan Config: Cache

PHP Handwerker migrieren

Levinski Polnisch
quelle
Es hat funktioniert, aber muss hinzugefügt werden, use Illuminate\Support\Facades\Schema; use Illuminate\Support\ServiceProvider;ist bereits da.
Ich
2

Wie im Migrationshandbuch beschrieben, müssen Sie lediglich Ihre AppServiceProvider.php-Datei bearbeiten und innerhalb der Startmethode eine Standardzeichenfolgenlänge festlegen:

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

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

Hoffe das wird dir helfen..cheers ..

Rohit Saini
quelle
2

Ich habe gerade die folgende Zeile in usersund password_resetsMigrationsdatei geändert .

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

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

Mahesh Gaikwad
quelle
1

Ich denke, StringLenght auf 191 zu zwingen, ist eine wirklich schlechte Idee. Also untersuche ich, um zu verstehen, was los ist.

Ich habe festgestellt, dass diese Meldung Fehler:

SQLSTATE [42000]: Syntaxfehler oder Zugriffsverletzung: 1071 Der angegebene Schlüssel war zu lang. Die maximale Schlüssellänge beträgt 767 Byte

Wurde angezeigt, nachdem ich meine MySQL-Version aktualisiert habe. Also habe ich die Tabellen mit PHPMyAdmin überprüft und festgestellt, dass alle neu erstellten Tabellen mit der Sortierung utf8mb4_unicode_ci anstelle von utf8_unicode_ci für die alten Tabellen erstellt wurden .

In meiner Doctrine-Konfigurationsdatei habe ich festgestellt, dass der Zeichensatz auf utf8mb4 festgelegt wurde, aber alle meine vorherigen Tabellen in utf8 erstellt wurden. Ich denke, dies ist eine Update-Magie, die auf utf8mb4 funktioniert.

Die einfache Lösung besteht nun darin, den Zeilenzeichensatz in Ihrer ORM-Konfigurationsdatei zu ändern. Löschen Sie dann die Tabellen mit utf8mb4_unicode_ci, wenn Sie sich im Entwicklungsmodus befinden, oder korrigieren Sie den Zeichensatz, wenn Sie sie nicht löschen können.

Für Symfony 4

Ändern Sie charset: utf8mb4 in charset: utf8 in config / packages / doct ..yaml

Jetzt funktionieren meine Doktrinenmigrationen wieder einwandfrei.

Kaizoku Gambare
quelle
1

Die empfohlene Lösung besteht darin, die innodb_large_prefixOption von MySQL zu aktivieren, damit Sie nicht auf nachfolgende Probleme stoßen. Und so geht's:

Öffnen Sie die my.iniMySQL-Konfigurationsdatei und fügen Sie die folgenden Zeilen unter der folgenden [mysqld]Zeile hinzu.

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

Speichern Sie danach Ihre Änderungen und starten Sie Ihren MySQL-Dienst neu.

Führen Sie bei Bedarf ein Rollback durch und führen Sie die Migration erneut aus.


Nur für den Fall, dass Ihr Problem weiterhin besteht, gehen Sie zu Ihrer Datenbankkonfigurationsdatei und legen Sie fest

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

Ich hoffe es hilft!

Sammie
quelle
1

Löschen Sie zuerst alle Tabellen der Datenbank im localhost

Ändern Sie die Eigenschaften der Laravel-Standarddatenbank (utf8mb4) in der Datei config / database.php in:

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

danach Ändern meiner lokalen Datenbankeigenschaften utf8_unicode_ci. PHP Handwerker migrieren es ist in Ordnung.

Goldman.Vahdettin
quelle
0

Für alle anderen, die darauf stoßen könnten, bestand mein Problem darin, dass ich eine Spalte vom Typ erstellte stringund versuchte, ->unsigned()sie zu erstellen , wenn ich beabsichtigte, dass es sich um eine Ganzzahl handelt.

Brynn Bateman
quelle
0

Die hier angesprochene Arbeit bestand darin, einen zweiten Parameter mit dem Schlüsselnamen (einen kurzen) zu übergeben:

$table->string('my_field_name')->unique(null,'key_name');
Tiago Gouvêa
quelle
0

Ich habe diesen Fehler erhalten, obwohl ich bereits Schema :: defaultStringLength (191) hatte (eigentlich, weil ich es bereits hatte); in meiner AppServiceProvider.php-Datei.

Der Grund dafür ist, dass ich versucht habe, bei einer meiner Migrationen einen Zeichenfolgenwert auf einen Wert über 191 festzulegen:

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

Das Entfernen des 1000 oder das Setzen auf 191 löste mein Problem.

Jacey
quelle