Migration: Fremdschlüsseleinschränkung kann nicht hinzugefügt werden

206

Ich versuche, Fremdschlüssel in Laravel zu erstellen, aber wenn ich meine Tabelle mit migriere artisan, wird der folgende Fehler ausgegeben:

[Illuminate\Database\QueryException]
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL
: alter table `priorities` add constraint priorities_user_id_foreign foreign 
key (`user_id`) references `users` (`id`))     

Mein Migrationscode lautet wie folgt:

Migrationsdatei für Prioritäten

public function up()
{
    //
    Schema::create('priorities', function($table) {
        $table->increments('id', true);
        $table->integer('user_id');
        $table->foreign('user_id')->references('id')->on('users');
        $table->string('priority_name');
        $table->smallInteger('rank');
        $table->text('class');
        $table->timestamps('timecreated');
    });
}

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    //
    Schema::drop('priorities');
}

Benutzer-Migrationsdatei

public function up()
{
    //
    Schema::table('users', function($table)
    {
    $table->create();
    $table->increments('id');
    $table->string('email');
    $table->string('first_name');
    $table->string('password');
    $table->string('email_code');
    $table->string('time_created');
    $table->string('ip');
    $table->string('confirmed');
    $table->string('user_role');
    $table->string('salt');
    $table->string('last_login');

    $table->timestamps();
    });
}

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    //
        Schemea::drop('users');
}

Irgendwelche Ideen, was ich falsch gemacht habe, möchte ich sofort machen, da ich viele Tabellen habe, die ich erstellen muss, z. B. Benutzer, Kunden, Projekte, Aufgaben, Status, Prioritäten, Typen, Teams. Im Idealfall möchte ich Tabellen erstellen , die diese Daten mit dem Fremdschlüssel, i..e halten clients_projectund project_tasksusw.

Hoffe, jemand kann mir helfen, loszulegen.

001221
quelle

Antworten:

356

Fügen Sie es in zwei Schritten hinzu, und es ist gut, es auch ohne Vorzeichen zu machen:

public function up()
{
    Schema::create('priorities', function($table) {
        $table->increments('id', true);
        $table->integer('user_id')->unsigned();
        $table->string('priority_name');
        $table->smallInteger('rank');
        $table->text('class');
        $table->timestamps('timecreated');
    });

   Schema::table('priorities', function($table) {
       $table->foreign('user_id')->references('id')->on('users');
   });

}
Antonio Carlos Ribeiro
quelle
117
Danke, Antonio! Für mich bestand das Problem nicht darin, der Spalte user_id unsigned () hinzuzufügen, damit es mit dem Datentyp der Spalte id in der Tabelle users übereinstimmt. Die Inkrementfunktion ('id') von Laravel erstellt eine Ganzzahl ohne Vorzeichen, daher muss auch die Fremdschlüsselspalte ohne Vorzeichen sein.
Brad Griffith
7
Das Hinzufügen von nicht signierten, abgesehen von der Trennung zur Schema::tableMethode hat geholfen! Vielen Dank!
Patrickjason91
4
Für mich war es nicht so, dass der Ausweis auch nicht signiert war. Danke für den Tipp.
Carl Weis
6
Die Lösung finden Sie in @BradGriffiths Kommentar. Wie oben erwähnt, besteht überhaupt keine Notwendigkeit, sich zu trennen. Vielleicht ist es besser, die Antwort entsprechend zu aktualisieren.
Matanya
11
Verwenden Sie, $table->unsignedBigInteger('user_id')wenn Ihre user.id istbigIncrements
Maksim Ivanov
114

Die Frage wurde bereits beantwortet, aber ich hoffe, dies könnte jemand anderem helfen.

Dieser Fehler trat bei mir auf, weil ich zuerst die Migrationstabelle mit dem Fremdschlüssel erstellt habe, bevor der Schlüssel als Primärschlüssel in der ursprünglichen Tabelle vorhanden war. Migrationen werden in der Reihenfolge ausgeführt, in der sie erstellt wurden, wie durch den nach der Ausführung generierten Dateinamen angegeben migrate:make. ZB 2014_05_10_165709_create_student_table.php.

Die Lösung bestand darin, die Datei mit dem Fremdschlüssel zu einem früheren Zeitpunkt als die Datei mit dem Primärschlüssel umzubenennen, wie hier empfohlen: http://forumsarchive.laravel.io/viewtopic.php?id=10246

Ich denke, ich musste auch hinzufügen $table->engine = 'InnoDB';

haakym
quelle
4
Nachdem Sie die Migrationsdatei umbenannt haben und einige Fehler erhalten haben wie: Fehler beim Öffnen des Streams: Keine solche Datei oder kein solches Verzeichnis (und der alte Migrationsname wird angezeigt) müssen Sie ausführen: Composer Dump-Autoload
Stelian
14
$ table-> engine = 'InnoDB'; ist erforderlich, um Fremdschlüssel auf MySQL-Ebene zu erzwingen. Die Standard-Laravel-Engine ist MyIsam, die keine Fremdschlüssel unterstützt!
François Breton
2
Das hat auch bei mir funktioniert, danke. Aber es scheint mir ein bisschen seltsam, dass es so funktioniert. Ich meine, es ist sinnvoll, aber es sollte eine andere Möglichkeit geben, die Reihenfolge der Migrationsausführung festzulegen, als die Dateien manuell
umzubenennen
2
Ich bin nicht hierher gekommen, weil ich Fehler bekommen habe, aber ich konnte der Spalte, die ein Fremdschlüssel war, falsche Werte hinzufügen. Dann habe ich den Kommentar und die Antwort zu InnoDB gesehen. Das war gut zu wissen. Danke Jungs :)
SuperNOVA
2
Die Reihenfolge, in der Sie Ihre Migrationen erstellt haben, bleibt bei der Migration weiterhin wichtig. Ich bin auf dieses Problem gestoßen, aber das hat es behoben.
Mugabits
60

Laravel ^ 5.8

Ab Laravel 5.8 verwenden Migrationsstubs standardmäßig die bigIncrements-Methode für ID-Spalten. Bisher wurden ID-Spalten mit der Inkrementmethode erstellt.

Dies wirkt sich nicht auf vorhandenen Code in Ihrem Projekt aus. Beachten Sie jedoch, dass Fremdschlüsselspalten vom gleichen Typ sein müssen . Daher kann eine mit der Methode increments erstellte Spalte nicht auf eine mit der Methode bigIncrements erstellte Spalte verweisen.

Quelle: Migrations & bigIncrements


Beispiel

Stellen Sie sich vor, Sie erstellen eine einfache rollenbasierte Anwendung und müssen in der PIVOT- Tabelle "role_user" auf user_id verweisen .

2019_05_05_112458_create_users_table.php

// ...

public function up()
{
    Schema::create('users', function (Blueprint $table) {

        $table->bigIncrements('id');

        $table->string('full_name');
        $table->string('email');
        $table->timestamps();
    });
}

2019_05_05_120634_create_role_user_pivot_table.php

// ...

public function up()
{
    Schema::create('role_user', function (Blueprint $table) {

        // this line throw QueryException "SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint..."
        // $table->integer('user_id')->unsigned()->index();

        $table->bigInteger('user_id')->unsigned()->index(); // this is working
        $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
    });
}

Wie Sie sehen können, löst die kommentierte Zeile eine Abfrageausnahme aus, da Fremdschlüsselspalten , wie in den Upgrade-Hinweisen erwähnt, vom gleichen Typ sein müssen. Daher müssen Sie entweder den Vorschlüssel (in diesem Beispiel user_id ) in ändern bigInteger in der Tabelle role_user oder ändern Sie die bigIncrements- Methode in die Inkrementierungsmethode in der Benutzertabelle und verwenden Sie die kommentierte Zeile in der Pivot-Tabelle. Es liegt an Ihnen.


Ich hoffe, ich konnte Ihnen dieses Problem klären.

Chebaby
quelle
1
Danke dir. du hast mein Leben gerettet. Nach Ihrer Erklärung habe ich meinen Fremdschlüssel wie von Ihnen vorgeschlagen in bigInteger geändert. Schema::table('goal_objective', function (Blueprint $table) { $table->bigInteger('job_title_id')->after('target')->unsigned()->nullable(); $table->foreign('job_title_id')->references('id')->on('job_titles')->onDelete('set null'); } Es funktionierte. Danke dir.
Bruce Tong
1
@ BruceTong, ich bin froh, dass ich helfen konnte.
Chebaby
1
Ja, das ist die relevanteste Antwort.
Mohd Abdul Mujib
1
Diese Antwort ist sehr hilfreich.
Karim Pazoki
1
Beste Antwort. Vielen Dank
VishalParkash
49

In meinem Fall bestand das Problem darin, dass die Haupttabelle bereits Datensätze enthielt und ich die neue Spalte zwang, nicht NULL zu sein. Das Hinzufügen von -> nullable () zur neuen Spalte hat also den Trick getan. Im Beispiel der Frage wäre so etwas:

$table->integer('user_id')->unsigned()->nullable();

oder:

$table->unsignedInteger('user_id')->nullable();

Hoffe das hilft jemandem!

AdrianCR
quelle
Beachten Sie, dass die Spalte 'id' in Ihrer übergeordneten Tabelle ebenfalls ohne Vorzeichen sein muss! Verwenden einer Zeile wie $ table-> increments ('id'); wird automatisch standardmäßig nicht signiert.
Colin Stadig
Das hat bei mir funktioniert. Ich habe den Datentyp der übergeordneten Tabellen-ID von BigIncrements in Inkremente geändert.
Emmanuel Benson
22

In meinem Fall bestand das Problem darin, dass die automatisch generierte Migration für die usersTabelle festgelegt wurde

...
$table->bigIncrements('id');
...

Also musste ich den Spaltentyp ändern


$table->bigInteger('id');

damit meine Migration mit dem Fremdschlüssel funktioniert.

Dies mit Laravel 5.8.2

Daniele
quelle
Da die Fremdschlüsselspalte denselben Spaltentyp haben muss, auf den sie sich bezieht
Daniele
9
Das hat bei mir funktioniert $ table-> unsignedBigInteger ('user_id'); in Laravel 5.8. *
Adam Winnipass
Ich hatte auch dieses Problem mit 5.8, das hat es für mich behoben! Vielen Dank!
Mike Sheward
Rettete mich vor einer langen Nacht!
chq
19

In meinem Fall bestand das Problem darin, dass das Migrations-Timing beim Erstellen von Migrationen vorsichtig sein sollte. Erstellen Sie zuerst die untergeordnete Migration als die Basismigration. Denn wenn Sie zuerst eine Basismigration erstellen, bei der Ihr Fremdschlüssel nach einer untergeordneten Tabelle sucht, gibt es keine Tabelle, die dann eine Ausnahme auslöst.

Außerdem:

Wenn Sie eine Migration erstellen, wird am Anfang ein Zeitstempel angezeigt. können sagen , dass Sie eine Migration erstellt haben , Katze , so dass es aussehen wird 2015_08_19_075954_the_cats_time.phpund es diesen Code hat

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class TheCatsTime extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('cat', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');  
            $table->date('date_of_birth');
            $table->integer('breed_id')->unsigned()->nullable(); 
        });

        Schema::table('cat', function($table) {
        $table->foreign('breed_id')->references('id')->on('breed');
      });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('cat');
    }
}

Und nachdem Sie die Basistabelle erstellt haben, erstellen Sie eine andere Migrationsrasse , die untergeordnete Tabelle, die einen eigenen Erstellungszeit- und Datumsstempel hat. Der Code sieht folgendermaßen aus:

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class BreedTime extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('breed', function (Blueprint $table) {
             $table->increments('id');    
             $table->string('name');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('breed');
    }
}

es scheint, dass diese beiden Tabellen korrekt sind, aber wenn Sie PHP Artisan Migrate ausführen . Es wird eine Ausnahme ausgelöst, da durch die Migration zuerst die Basistabelle in Ihrer Datenbank erstellt wird, da Sie diese Migration zuerst erstellt haben und unsere Basistabelle eine Fremdschlüsseleinschränkung enthält, die nach einer untergeordneten Tabelle sucht und die untergeordnete Tabelle wahrscheinlich nicht vorhanden ist eine Ausnahme..

So:

Erstellen Sie zuerst eine untergeordnete Tabellenmigration.

Erstellen Sie eine Basistabellenmigration, nachdem eine untergeordnete Migration erstellt wurde.

PHP Handwerker migrieren.

fertig wird es funktionieren

Vicky
quelle
13

In meinem Fall ändere ich nur die Reihenfolge, in der Migrationen manuell ausgeführt werden, sodass zuerst Tabellenbenutzer erstellt werden.

In der Ordnerdatenbank / migrations / Ihr Migrationsdateiname haben Sie das folgende Format: year_month_day_hhmmss_create_XXXX_table.php

Benennen Sie einfach die Benutzerdatei erstellen um, damit das Erstellungsdatum Ihrer Tabellenprioritätstabelle später als das Benutzerdatum festgelegt wird (sogar eine Sekunde später ist ausreichend).

ldt
quelle
13

In Laravel 5.8 verwendet die users_table den bigIncrements('id')Datentyp für den Primärschlüssel. Wenn Sie also auf eine Fremdschlüsseleinschränkung verweisen möchten, muss Ihre user_idSpalte vom unsignedBigInteger('user_id')Typ sein.

Dhara Talaviya
quelle
Vielen Dank, ich habe eine Stunde lang versucht herauszufinden, warum der Fremdschlüssel die Ausnahme verursacht
Ya Basha
10

Ich hatte das gleiche Problem mit Laravel 5.8. Nachdem Sie sich die Laravel-Dokumente genauer angesehen haben, finden Sie hier auch Migrations & bigIncrements . Ich habe es gelöst, indem ich jeder einzelnen Tabelle, die sich auf die Tabelle "Benutzer" und ihre Zuordnungen bezieht, Primärschlüssel "$ table-> bigIncrements ('id')" hinzugefügt habe , in meinem Fall die Tabelle "Rolle" . Zuletzt hatte ich "$ table-> unsignedBigInteger" zum Zuordnen von Rollen zu Benutzern (Many-to-Many), dh Tabelle "role_user" .

1. Users table

    Schema::create('users', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });

2. Roles Table
    Schema::create('roles', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->string('name')->unique();
        $table->string('display_name')->nullable();
        $table->string('description')->nullable();
        $table->timestamps();
    });

3. Table role_user
Schema::create('role_user', function (Blueprint $table) {
            $table->unsignedBigInteger('user_id');
            $table->unsignedBigInteger('role_id');
            $table->foreign('user_id')->references('id')->on('users')
                ->onUpdate('cascade')->onDelete('cascade');
            $table->foreign('role_id')->references('id')->on('roles')
                ->onUpdate('cascade')->onDelete('cascade');
            $table->primary(['user_id', 'role_id']);
        });
Capfer
quelle
9

Ich hatte dieses Problem mit Laravel 5.8 und habe diesen Code, wie hier in der Laravel-Dokumentation gezeigt , an der Stelle behoben , an der ich einen Fremdschlüssel hinzufüge.

$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');

dann rannte ich $ php artisan migrate:refresh

Da diese Syntax ziemlich ausführlich ist, bietet Laravel zusätzliche, kürzere Methoden, die Konventionen verwenden, um eine bessere Entwicklererfahrung zu erzielen. Das obige Beispiel könnte folgendermaßen geschrieben werden:

Schema::table('posts', function (Blueprint $table) {
    $table->foreignId('user_id')->constrained()->onDelete('cascade');
});
Slycreator
quelle
7

Die Verwendung von Laravel 5.3 hatte das gleiche Problem.

Die Lösung bestand darin, unsignedInteger anstelle von integer ('name') -> unsigned () zu verwenden .

Das hat also funktioniert

$table->unsignedInt('column_name');
$table->foreign('column_name')->references('id')->on('table_name');

Der Grund, warum dies funktioniert hat, ist die Tatsache, dass bei Verwendung von Integer ('Name') -> unsigned die in der Tabelle erstellte Spalte die Länge 11 hatte, bei Verwendung von unsigedInteger ('Name') die Spalte jedoch die Länge 10 hatte.

Länge 10 ist die Länge für Primärschlüssel, wenn Laravel verwendet wird, sodass die Spaltenlänge übereinstimmt.

Radu Diță
quelle
Mann, danke dafür, dass ich aufgeben und die rohe SQL ausführen wollte, als ich gerade Ihren Beitrag gefunden habe. Ich werde mehr darüber lesen müssen, warum der Laravel-Primärschlüssel eine Länge von 10 haben muss und ob es einen Grund gibt, warum die Ausführung von Integer ('column') -> unsigned () von unsigedInteger ('column')
Arnaud
6

Dieser Fehler trat bei mir auf, weil - während die Tabelle, die ich erstellen wollte, InnoDB war - die fremde Tabelle, auf die ich sie beziehen wollte, eine MyISAM-Tabelle war!

Bagnap
quelle
MyISAM unterstützt keine Fremdschlüsseleinschränkungen. Es hat wahrscheinlich funktioniert, weil der Wechsel zu MyISAM dazu führte, dass der Fremdschlüssel, der wahrscheinlich aus einem bestimmten Grund vorhanden war, vollständig ignoriert wurde. Achtung.
Greggle138
5

Wir können keine Beziehungen hinzufügen, es sei denn, verwandte Tabellen werden erstellt. Laravel führt die Migrationsreihenfolge nach Datum der Migrationsdateien aus. Wenn Sie also eine Beziehung zu einer Tabelle erstellen möchten, die in der zweiten Migrationsdatei vorhanden ist, schlägt dies fehl.

Ich hatte das gleiche Problem, also habe ich endlich eine weitere Migrationsdatei erstellt, um alle Beziehungen anzugeben.

Schema::table('properties', function(Blueprint $table) {
        $table->foreign('user')->references('id')->on('users')->onDelete('cascade');
        $table->foreign('area')->references('id')->on('areas')->onDelete('cascade');
        $table->foreign('city')->references('id')->on('cities')->onDelete('cascade');
        $table->foreign('type')->references('id')->on('property_types')->onDelete('cascade');
    });

    Schema::table('areas', function(Blueprint $table) {
        $table->foreign('city_id')->references('id')->on('cities')->onDelete('cascade');
    });
Pavan Kumar
quelle
1
Wie haben Sie die Datei benannt? 9999_99_99_999999_create_foreign_keys.php?
Iannazzi
Das Hinzufügen von 9999_99_99_99999 zum Migrationsdateinamen ist eine schlechte Idee, da dadurch die Rollback-Funktion beeinträchtigt wird.
Maulik Gangani
5

Beachten Sie: Wenn Laravel mit einen Tisch aufstellt

$table->increments('id');

Dies ist bei den meisten Migrationen Standard und richtet ein vorzeichenloses Ganzzahlfeld ein. Stellen Sie daher beim Erstellen einer Fremdreferenz von einer anderen Tabelle zu diesem Feld sicher, dass Sie in der Referenzierungstabelle das Feld auf UnsignedInteger und nicht auf das Feld UnsignedBigInteger (was ich angenommen hatte) setzen.

Beispiel: In der Migrationsdatei 2018_12_12_123456_create_users_table.php:

Schema::create('users', function (Blueprint $table){
    $table->increments('id');
    $table->string('name');
    $table->timestamps();

Dann in der Migrationsdatei 2018_12_12_18000000_create_permissions_table.php, die die Fremdreferenz für Benutzer zurückstellt:

Schema::create('permissions', function (Blueprint $table){
    $table->increments('id');
    $table->UnsignedInteger('user_id'); // UnsignedInteger = "increments" in users table
    $table->boolean('admin');
    $table->boolean('enabled');
    $table->timestamps();

    // set up relationship
    $table->foreign('user_id')->reference('id')->on('users')->onDelete('cascade');
}
bnoeafk
quelle
5

Sie sollten auf diese Weise schreiben

public function up()
{
    Schema::create('transactions', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->float('amount', 11, 2);
        $table->enum('transaction type', ['debit', 'credit']);
        $table->bigInteger('customer_id')->unsigned();      
        $table->timestamps();                 
    });

    Schema::table('transactions', function($table) {
        $table->foreign('customer_id')
              ->references('id')->on('customers')
              ->onDelete('cascade');
    });     
}

Das Fremdschlüsselfeld sollte nicht signiert sein , hoffe es hilft !!

Mahesh Yadav
quelle
Nicht nur ohne Vorzeichen, sondern wenn es auf eine bigIncrements-Spalte verweist, sollte es unsigedBigInteger
gondwe
4

Für das Hinzufügen von Fremdschlüsseleinschränkungen in Laravel hat Folgendes für mich funktioniert:

  1. Erstellen Sie die Spalte als Fremdschlüssel wie folgt:

    $ table-> integer ('column_name') -> unsigned ();
  2. Hinzufügen der Beschränkungslinie unmittelbar nach (1) dh

    $ table-> integer ('column_name') -> unsigned ();
    $ table-> fremd ('Spaltenname') -> Referenzen ('pk_of_other_table') -> on ('other_table');
bmnepali
quelle
3

Ich weiß, dass dies eine alte Frage ist, aber stellen Sie sicher, dass die richtige unterstützende Engine definiert ist, wenn Sie mit Referenzen arbeiten. Stellen Sie die innodb-Engine für beide Tabellen und den gleichen Datentyp für die Referenzspalten ein

$table->engine = 'InnoDB';
di3
quelle
2

Als ich einige Jahre nach der ursprünglichen Frage mit Laravel 5.1 hierher kam, hatte ich den gleichen Fehler, da meine Migrationen computergeneriert mit demselben Datumscode waren. Ich ging alle vorgeschlagenen Lösungen durch und überarbeitete sie dann, um die Fehlerquelle zu finden.

Beim Verfolgen von Laracasts und beim Lesen dieser Beiträge glaube ich, dass die richtige Antwort der von Vickies ähnelt, mit der Ausnahme, dass Sie keinen separaten Schemaaufruf hinzufügen müssen. Sie müssen den Tisch nicht auf Innodb decken, ich gehe davon aus, dass Laravel das jetzt tut.

Die Migrationen müssen lediglich korrekt zeitgesteuert sein. Dies bedeutet, dass Sie den Datumscode (später) im Dateinamen für Tabellen ändern, für die Sie Fremdschlüssel benötigen. Alternativ oder zusätzlich verringern Sie den Datumscode für Tabellen, die keine Fremdschlüssel benötigen.

Der Vorteil beim Ändern des Datumscodes besteht darin, dass Ihr Migrationscode einfacher zu lesen und zu warten ist.

Bisher funktioniert mein Code, indem der Zeitcode angepasst wird, um Migrationen, die Fremdschlüssel benötigen, zurückzuschieben.

Allerdings habe ich Hunderte von Tabellen, so dass ich ganz am Ende eine letzte Tabelle nur für Fremdschlüssel habe. Nur um die Dinge zum Fließen zu bringen. Ich gehe davon aus, dass ich diese in die richtige Datei ziehen und den Datumscode ändern werde, während ich sie teste.

Ein Beispiel: Datei 2016_01_18_999999_create_product_options_table. Hier muss die Produkttabelle erstellt werden. Schauen Sie sich die Dateinamen an.

 public function up()
{
    Schema::create('product_options', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('product_attribute_id')->unsigned()->index();
        $table->integer('product_id')->unsigned()->index();
        $table->string('value', 40)->default('');
        $table->timestamps();
        //$table->foreign('product_id')->references('id')->on('products');
        $table->foreign('product_attribute_id')->references('id')->on('product_attributes');
        $table->foreign('product_id')->references('id')->on('products');


    });
}

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    Schema::drop('product_options');
}

Die Produkttabelle: Diese muss zuerst migriert werden. 2015_01_18_000000_create_products_table

public function up()
{
    Schema::create('products', function (Blueprint $table) {
        $table->increments('id');

        $table->string('style_number', 64)->default('');
        $table->string('title')->default('');
        $table->text('overview')->nullable();
        $table->text('description')->nullable();


        $table->timestamps();
    });
}

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    Schema::drop('products');
}

Und schließlich ganz am Ende die Datei, die ich vorübergehend zur Behebung von Problemen verwende, die ich überarbeiten werde, wenn ich Tests für die Modelle schreibe, die ich 9999_99_99_999999_create_foreign_keys.php genannt habe. Diese Schlüssel werden kommentiert, als ich sie herausgezogen habe, aber Sie verstehen es.

    public function up()
    {
//        Schema::table('product_skus', function ($table) {
//            $table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
//    });

    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
//        Schema::table('product_skus', function ($table)
//        {
//            $table->dropForeign('product_skus_product_id_foreign');
//        });
Iannazzi
quelle
2

So einfach !!!

Wenn Sie zum ersten Mal eine 'priorities'Migrationsdatei erstellen, wird Laravel zuerst ausgeführt, 'priorities'solange 'users'keine Tabelle vorhanden ist.

wie es eine Beziehung zu einer Tabelle hinzufügen kann, die nicht existiert!.

Lösung: Ziehen Sie Fremdschlüsselcodes aus der 'priorities'Tabelle heraus. Ihre Migrationsdatei sollte folgendermaßen aussehen:

Geben Sie hier die Bildbeschreibung ein

und fügen Sie zu einer neuen Migrationsdatei hinzu, hier ist ihr Name create_prioritiesForeignKey_tableund fügen Sie diese Codes hinzu:

public function up()
{        
    Schema::table('priorities', function (Blueprint $table) {          
        $table->foreign('user_id')
              ->references('id')
              ->on('users');                        
    });
}
josef
quelle
2

Stellen Sie sicher, dass Ihre vordere Säule über die Wut der vorderen Schlüsselkolonne hinausgeht

Ich meine, Ihr Vorschlüssel (in der zweiten Tabelle) muss der gleiche Typ Ihres Ponter-Schlüssel sein (in der ersten Tabelle).

Ihr Zeiger-Hauptschlüssel muss eine vorzeichenlose Methode sein. Lassen Sie mich zeigen:

in Ihrer ERSTEN Migrationstabelle:

$table->increments('column_name'); //is INTEGER and UNSIGNED

in Ihrer ZWEITEN Migrationstabelle:

$table->integer('column_forein_name')->unsigned(); //this must be INTEGER and UNSIGNED
$table->foreign('column_forein_name')->references('column_name')->on('first_table_name');

EIN ANDERES BEISPIEL, UM UNTERSCHIEDE ZU SEHEN

in Ihrer ERSTEN Migrationstabelle:

$table->mediumIncrements('column_name'); //is MEDIUM-INTEGER and UNSIGNED

in Ihrer ZWEITEN Migrationstabelle:

$table->mediumInteger('column_forein_name')->unsigned(); //this must be MEDIUM-INTEGER and UNSIGNED
$table->foreign('column_forein_name')->references('column_name')->on('first_table_name');

SIEHE MYSQL NUMERIC TYPES TABLE RANGES

Rubén Ruíz
quelle
2

Eine Sache, die mir aufgefallen ist, ist, dass wenn die Tabellen eine andere Engine als die Fremdschlüsseleinschränkung verwenden, dies nicht funktioniert.

Zum Beispiel, wenn eine Tabelle verwendet:

$table->engine = 'InnoDB';

Und die anderen Verwendungen

$table->engine = 'MyISAM';

würde einen Fehler erzeugen:

SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint

Sie können dies beheben, indem Sie InnoDB am Ende Ihrer Tabellenerstellung wie folgt hinzufügen:

public function up()
{
    Schema::create('users', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->unsignedInteger('business_unit_id')->nullable();

        $table->string('name', 100);

        $table->foreign('business_unit_id')
                ->references('id')
                ->on('business_units')
                ->onDelete('cascade');

        $table->timestamps();
        $table->softDeletes();
        $table->engine = 'InnoDB'; # <=== see this line
    });
}
erlandmuchasaj
quelle
1

In meinem Fall habe ich auf eine Ganzzahlspalte id in einer Zeichenfolgenspalte verwiesen user_id. Ich habe mich verändert:

$table->string('user_id')

zu:

$table->integer('user_id')->unsigned();

Hoffe es hilft jemandem!

Raphael Rafatpanah
quelle
1

Das Wesentliche ist, dass die Fremdmethode verwendet wird ALTER_TABLE, um ein bereits vorhandenes Feld in einen Fremdschlüssel zu verwandeln . Sie müssen also den Tabellentyp definieren, bevor Sie den Fremdschlüssel anwenden. Es muss jedoch nicht in einem separaten Schema::Anruf sein. Sie können beides innerhalb von create wie folgt tun:

public function up()
{
    Schema::create('priorities', function($table) {
        $table->increments('id', true);
        $table->integer('user_id')->unsigned();
        $table->foreign('user_id')->references('id')->on('users');
        $table->string('priority_name');
        $table->smallInteger('rank');
        $table->text('class');
        $table->timestamps('timecreated');
    });
}

Beachten Sie auch, dass der Typ von user_idso eingestellt ist, dass er nicht mit dem Fremdschlüssel übereinstimmt.

Menasheh
quelle
1

Sie können den booleschen Parameter direkt in der Ganzzahlspalte übergeben und angeben, dass er ohne Vorzeichen sein soll oder nicht. In Laravel 5.4 löste der folgende Code mein Problem.

        $table->integer('user_id', false, true);

Hier bedeutet der zweite Parameter false , dass er nicht automatisch inkrementiert werden soll, und der dritte Parameter true bedeutet , dass er ohne Vorzeichen sein soll. Sie können die Fremdschlüsseleinschränkung in derselben Migration beibehalten oder trennen. Es funktioniert bei beiden.

Mohit Satish Pawar
quelle
1

Wenn keine der oben genannten Lösungen für Neulinge funktioniert, überprüfen Sie, ob beide IDs denselben Typ haben: beide sind integeroder beide sind bigInteger, ... Sie können so etwas haben:

Haupttabelle (Benutzer zum Beispiel)

$table->bigIncrements('id');

Untergeordnete Tabelle (Prioritäten zum Beispiel)

$table->unsignedInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');

Diese Abfrage ist fehlgeschlagen, da users.ides sich um eine BIG INTEGERwährend priorities.user_ideiner Abfrage handelt INTEGER.

Die richtige Abfrage in diesem Fall wäre die folgende:

$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
Waiyl Karim
quelle
1

In meinem Fall hat es nicht funktioniert, bis ich den Befehl ausgeführt habe

composer dump-autoload

Auf diese Weise können Sie die Fremdschlüssel im Erstellungsschema belassen

public function up()
{
    //
     Schema::create('priorities', function($table) {
        $table->increments('id', true);
        $table->integer('user_id');
        $table->foreign('user_id')->references('id')->on('users');
        $table->string('priority_name');
        $table->smallInteger('rank');
        $table->text('class');
        $table->timestamps('timecreated');
    });
 }

 /**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    //
    Schema::drop('priorities');
}
Vladimir Salguero
quelle
1

Es kann auch Ihre Reihenfolge der Erstellungsmigration sein. Wenn Sie zuerst eine Prioritäts-Tabelle und nach der Benutzertabelle erstellen, ist dies falsch. Wegen der ersten Migration nach Benutzertabelle suchen. Sie müssen also die Reihenfolge der Migration ändern

app/database/migrations

Verzeichnis

Turan Zamanlı
quelle
1

Für mich wurde die Tabellenspalte, auf die meine untergeordnete Tabelle verwiesen hat, nicht indiziert.

Schema::create('schools', function (Blueprint $table) {
    $table->integer('dcid')->index()->unque();
    $table->integer('school_number')->index(); // The important thing is that this is indexed
    $table->string('name');
    $table->string('abbreviation');
    $table->integer('high_grade');
    $table->integer('low_grade');
    $table->timestamps();
    $table->primary('dcid');
});

Schema::create('students', function (Blueprint $table) {
      $table->increments('id');
      $table->integer('dcid')->index()->unique()->nullable();
      $table->unsignedInteger('student_number')->nullable();
      $table->integer('schoolid')->nullable();
      $table->foreign('schoolid')->references('school_number')->on('schools')->onDelete('set null');
      // ...
});

Ignorieren Sie die schreckliche Benennung, sie stammt von einem anderen schrecklich gestalteten System.

Gewähren
quelle
1

Manchmal kann dieser Fehler aufgrund der Reihenfolge der Migrationen auftreten.

Like Users und Order sind zwei Tabellen

Die Bestelltabelle hat einen Foriegn-Schlüssel für Benutzer (Wenn während der Migration die Bestelltabelle zuerst migriert wird, tritt das Problem auf, da keine Benutzer mit dem Fremdschlüssel übereinstimmen.)

Lösung: Legen Sie einfach Ihre Bestellaktualisierungstabelle zur Aktualisierung unter die Benutzer

Beispiel: In meinem Fall Bildung und Universitätstabelle Bildungstabelle

public function up()
{
    Schema::create('doc_education', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('uni_id')->unsigned()->nullable();
        $table->timestamps();
    });
}

In der Universität

    Schema::create('doc_universties', function (Blueprint $table) {
        $table->increments('id');
        $table->string('uni_name');
        $table->string('location')->nullable();
        $table->timestamps();

        //
    });



Schema::table('doc_education', function(Blueprint $table) {
        $table->foreign('uni_id')->references('id')
        ->on('doc_universties')->onDelete('cascade');
    });
BlockCode
quelle
0

Eine Sache, die meiner Meinung nach in den Antworten hier fehlt, und bitte korrigieren Sie mich, wenn ich falsch liege, aber die Fremdschlüssel müssen in der Pivot-Tabelle indiziert werden. Zumindest in MySQL scheint dies der Fall zu sein.

public function up()
{
    Schema::create('image_post', function (Blueprint $table) {
        $table->engine = 'InnoDB';
        $table->increments('id');
        $table->integer('image_id')->unsigned()->index();
        $table->integer('post_id')->unsigned()->index();
        $table->timestamps();
    });

    Schema::table('image_post', function($table) {
        $table->foreign('image_id')->references('id')->on('image')->onDelete('cascade');
        $table->foreign('post_id')->references('id')->on('post')->onDelete('cascade');
    });

}
Ossi
quelle