Laravel migration: “Foreign key constraint is incorrectly formed” (errno 150)

拜拜、爱过 提交于 2019-12-17 10:58:27

问题


When migrating my DB this error appears, below is my code followed by the error that I am getting when trying to run the migration.

Code

public function up()
{
    Schema::create('meals', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('user_id')->unsigned();
        $table->integer('category_id')->unsigned();
        $table->string('title');
        $table->string('body');
        $table->string('meal_av');
        $table->timestamps();
        $table->foreign('user_id')
            ->references('id')
            ->on('users')
            ->onDelete('cascade');
        $table->foreign('category_id')
            ->references('id')
            ->on('categories')
            ->onDelete('cascade');
    });
}  

Error message

[Illuminate\Database\QueryException]
SQLSTATE[HY000]: General error: 1005 Can't create table meal.#sql-11d2_1 4 (errno: 150 "Foreign key constraint is incorrectly formed") (SQL: alter
table meals add constraint meals_category_id_foreign foreign key (category_id) references categories (id) on delete cascade)


回答1:


When creating a new table in Laravel. A migration will be generated like:

$table->bigIncrements('id');

Instead of (in older Laravel versions):

$table->increments('id');

When using bigIncrements the foreign key expects a bigInteger instead of an integer. So your code will look like this:

public function up()
    {
        Schema::create('meals', function (Blueprint $table) {
            $table->increments('id');
            $table->unsignedBigInteger('user_id'); //changed this line
            $table->unsignedBigInteger('category_id'); //changed this line
            $table->string('title');
            $table->string('body');
            $table->string('meal_av');
            $table->timestamps();

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

            $table->foreign('category_id')
                ->references('id')
                ->on('categories')
                ->onDelete('cascade');
        });
    }  

You could also use increments instead of bigIncrements like Kiko Sejio said.

The difference between Integer and BigInteger is the size:

  • int => 32-bit
  • bigint => 64-bit



回答2:


@JuanBonnett Your question has inspired me to the answer ,i adopted on laravel to automate the process without considering the creation time of the file itself ,According to workflow meals will be created before table (categories) because i have created schema file (meals) before categories. that was my fault.




回答3:


just add ->unsigned()->index() at the end of the foreign key and it will work




回答4:


For me everything was in correct order, but it still didn't work. Then I found out by fiddling that the primary key must be unsigned.

//this didn't work
$table->integer('id')->unique();
$table->primary('id');

//this worked
$table->integer('id')->unsigned()->unique();
$table->primary('id');

//this worked 
$table->increments('id');



回答5:


I got the same message for data type miss-matched problem.

I used bigIncrements() for 'id' and when I used it as foreign key (used bigInteger()) I got the error.

I have found the solution, bigIncrements() returns unsignedBigInteger. So need to use unsignedBigInteger() instead of bigInteger() in foreign key

Sharing this because it might help others




回答6:


You should create your migration in order for example I want my users to have a role_id field which is from my roles table

I first start to make my role migration php artisan make:migration create_roles_table --create=roles

then my second user migration php artisan make:migration create_users_table --create=users

php artisan migration will execute using the order of the created files 2017_08_22_074128_create_roles_table.php and 2017_08_22_134306_create_users_table check the datetime order, that will be the execution order.

files 2017_08_22_074128_create_roles_table.php

public function up()
{
    Schema::create('roles', function (Blueprint $table) {
        $table->increments('id');
        $table->string('name', 50);
        $table->timestamps();
    });
}

2017_08_22_134306_create_users_table

public function up()
{
    Schema::create('users', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('role_id')->unsigned();
        $table->string('name');
        $table->string('phone', 20)->unique();
        $table->string('password');
        $table->rememberToken();
        $table->boolean('active');
        $table->timestamps();
        $table->foreign('role_id')->references('id')->on('roles');
    });
}



回答7:


In my case, the new laravel convention was causing this error.

Just by a simple swap of the table creation id did the trick.

$table->increments('id'); // ok

, instead of:

$table->bigIncrements('id'); // was the error.

Already working with Laravel v5.8, never had this error before.




回答8:


Migrations must be created top-down.

First create the migrations for the tables who don't belong to anyone.

Then create the migrations for tables that belong to the previous.


Simplified answer to the table engine problem:

To set the storage engine for a table, set the engine property on the schema builder:

Schema::create('users', function ($table) {
    $table->engine = 'InnoDB';

    $table->increments('id');
});

From Laravel Docs: https://laravel.com/docs/5.2/migrations




回答9:


if you are using ->onDelete('set null') in your foreign key definition make sure the foreign key field itself is nullable() ie

//Column definition
$table->integer('user_id')->unsigned()->index()->nullable(); //index() is optional

//...
//...

//Foreign key 
$table->foreign('user_id')
      ->references('id')
      ->on('users')
      ->onDelete('set null');



回答10:


In my case the problem was that one of the referenced tables was InnoDB and the other one was MyISAM.

MyISAM doesn't have support for foreign key relations.

So, now both tables are InnoDB. Problem solved.




回答11:


Maybe it can be of help to anyone landing here : I just experienced this same issue, and in my case it was that I had a (composite) unique constraint set on the foreign key column BEFORE the foreign key constraint. I resolved the issue by having the "unique" statement placed AFTER the "foreign" statement.

Works:

$table->foreign('step_id')->references('id')->on('steps')->onDelete('cascade');
$table->unique(['step_id','lang']);

Doesn't work:

$table->unique(['step_id','lang']);
$table->foreign('step_id')->references('id')->on('steps')->onDelete('cascade');



回答12:


The order of creation of migration files should be sorted and the foreign key should have exactly similar property as the primary key in the other table.




回答13:


laravel 5.8

in the foreign key column use unsignedBigInteger to avoid mismatch foreign key data type problem . Example let us assume we have tow tables questions and replies
Questions table will look:

 public function up()
    {
        Schema::create('questions', function (Blueprint $table) {
            $table->bigIncrements('id');
             $table->text('body');
             $table->integer('user_id')->unsigned();
            $table->timestamps();
        });
    }

Replies table look like :

public function up()
{
    Schema::create('replies', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->text('body');
        $table->unsignedBigInteger('question_id');
        $table->integer('user_id')->unsigned();
        $table->foreign('question_id')->references('id')->on('questions')->onDelete('cascade');
        $table->timestamps();
    });
}



回答14:


Add ->nullable() on your field and make sure that all the fields you're referring to really exists.




回答15:


Remember that this is important the referenced and referencing fields must have exactly the same data type.




回答16:


It is a simple question, so give a simple answer and stop beating about the bush, change your example $table->integer('user_id')->unsigned(); to $table->BigInteger('user_id')->unsigned(); to solve the foreign key error. so change integer to BigInteger in the migration file...




回答17:


You should first create Categories and users Table when create "meals"

To solve the issue you should rename migration files of Category and Users to date of before Meals Migration file that create those before Meals table.


sample:
2019_04_10_050958_create_users_table 
2019_04_10_051958_create_categories_table
2019_04_10_052958_create_meals_table


来源:https://stackoverflow.com/questions/32669880/laravel-migration-foreign-key-constraint-is-incorrectly-formed-errno-150

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!