18

Im trying to create a foreign keys using artisan, but this error show up.

[Illuminate\Database\QueryException]                                                                                                                                                                             
  SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL: alter table `comments` add constraint `comments_comment_lot_id_foreign` foreign key (`comment_lot_id`) references `lots` (`lot_id`  
  ) on delete cascade) 

This is my migration:

<?php

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

class CreateCommentsTable extends Migration
{

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('comments', function (Blueprint $table) {
            $table->increments('id');
            $table->text('comment');
            $table->integer('comment_lot_id')->unsigned();
            $table->timestamps();
        });

        Schema::table('comments', function ($table) {
            $table->foreign('comment_lot_id')->references('lot_id')->on('lots')->onDelete('cascade');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropForeign(['comment_lot_id']);
        Schema::dropIfExists('comments');
    }
}

in the lots table i use lot_id as id it model Lot.php i add:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Lot extends Model {
    protected $primaryKey = 'lot_id';

}

Any idea how can i resolve this error?

Dmitry Malys
  • 1,293
  • 4
  • 25
  • 46
  • 1
    as said below make sure both ints are EXACTLY the same, unsigned, length etc. that's usually why this fails. – ATechGuy Apr 28 '17 at 20:01
  • To find the specific error run this `SHOW ENGINE INNODB STATUS;` on database motor. Credits https://stackoverflow.com/questions/15534977/mysql-cannot-add-foreign-key-constraint – anayarojo Nov 29 '18 at 04:35

3 Answers3

28

Apply these rules below to your migration files:

[1]

The parent, pivot table(s) must be based on engines that supports foreign key referencing (e.g InnoDB for mysql).

Do $table->engine = “InnoDB”; in your migration file, right before other column definitions.

I observe laravel always default to MyISAM hence this line is a must.

[2]

The referenced columns in the parent must be a primary or unique key(s).

These declarations in the parent table are fine:

$table->increments(“id”); means column “id” is referencable

$table->column_type(“column_name”)->unique(); means column “column_name” is referencable

[3]

The pivot table column must be of the same type as that of its referenced parent table column.

So for example, the pivot table column that should reference increments(“id”) must of type of unsignedInteger.

If parent table is type char(20), then pivot table column used to reference it must be type char(20) as well.

Having done all three above, define your foreign key relationship as appropriate.

korwalskiy
  • 927
  • 12
  • 12
  • 2
    thank you ! it worked.1. ' $table->engine = ' MyISAM'; ' because the parent table also MyISAM 2. $table->integer('comment_lot_id')->unique()->unsigned(); to much the parent table – Dmitry Malys May 02 '17 at 06:33
28

Looks like this was not the problem for you, but I arrived at this same error in Laravel 5.8 and found an interesting issue: Laravel now defaults the 'id' column to 'bigIncrements' instead of just 'increments'. So instead of referencing it with 'integer' like before, you have to reference it with 'bigInteger'.

If your parent table looks like this:

$table->bigIncrements('id');

Then the child migration needs to look like this:

$table->bigInteger('parent_id')->unsigned()->index();
$table->foreign('parent_id')->references('id')->on('parent');

Hopefully this helps anyone else encountering this problem in 5.8 and beyond.

Symphony0084
  • 1,257
  • 16
  • 33
  • 1
    So this helped a whole lot. I was stuck on same problem in laravel 5.8. Big Ups – Miracool Aug 21 '19 at 09:24
  • **or** when creating each new model in an existing app, you could switch it from *bigIncrements('id')* to *increments('id')* before running the migration, which'll give you INT to match your existing models. Consider the [MySQL docs](https://dev.mysql.com/doc/refman/5.7/en/integer-types.html) say an unsigned INT will still give you a maximum value of 4,294,967,295. Which I think is big enough for everything I do… – William Turrell May 13 '21 at 11:09
8

Quoting this answer:

To find the specific error run this:

SHOW ENGINE INNODB STATUS;

And look in the LATEST FOREIGN KEY ERROR section.

It may be a problem of type. comment_lot_id must be the exact same type as lot_id. Maybe one is signed and the other unsigned.

Community
  • 1
  • 1
rap-2-h
  • 30,204
  • 37
  • 167
  • 263