AUTOVICE

TECH BLOG

外部キー制約を設定したマイグレーションでエラーが発生する原因と対処法

2020-02-23

はじめに

【入門】Laravelチュートリアル - 掲示板を作成してみよう | 実践的Web開発メソッド

こちらの手順に従ってマイグレーションファイルを作成しマイグレートを行おうとしたところ、以下のエラーが出力されました。

$ php artisan migrate
Migration table created successfully.
Migrating: 2020_02_23_164117_create_posts_table
Migrated:  2020_02_23_164117_create_posts_table (0.01 seconds)
Migrating: 2020_02_23_164211_create_comments_table

   Illuminate\Database\QueryException  : SQLSTATE[HY000]: General error: 3780 Referencing column 'post_id' and referenced column 'id' in foreign key constraint 'comments_post_id_foreign' are incompatible. (SQL: alter table `comments` add constraint `comments_post_id_foreign` foreign key (`post_id`) references `posts` (`id`))

  at /Users/user/Products/MyProject/vendor/laravel/framework/src/Illuminate/Database/Connection.php:669
    665|         // If an exception occurs when attempting to run a query, we'll format the error
    666|         // message to include the bindings with SQL, which will make this exception a
    667|         // lot more helpful to the developer instead of just the database's errors.
    668|         catch (Exception $e) {
  > 669|             throw new QueryException(
    670|                 $query, $this->prepareBindings($bindings), $e
    671|             );
    672|         }
    673| 

  Exception trace:

  1   PDOException::("SQLSTATE[HY000]: General error: 3780 Referencing column 'post_id' and referenced column 'id' in foreign key constraint 'comments_post_id_foreign' are incompatible.")
      /Users/user/Products/MyProject/vendor/laravel/framework/src/Illuminate/Database/Connection.php:463

  2   PDOStatement::execute()
      /Users/user/Products/MyProject/vendor/laravel/framework/src/Illuminate/Database/Connection.php:463

  Please use the argument -v to see more details.

マイグレーション内容

今回実行しようとしたマイグレーションファイルは以下の通りです。
詳しくは上記リンクを参照してください。

database/migrations/2020_02_23_171858_create_posts_table.php

<?php

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

class CreatePostsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('title',50);
            $table->text('body');
            $table->timestamps();
        });
    }

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

database/migrations/2020_02_23_171919_create_comments_table.php

<?php

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

class CreateCommentsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('comments', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->unsignedInteger('post_id');
            $table->text('body');
            $table->timestamps();

            $table->foreign('post_id')->references('id')->on('posts');
        });
    }

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

ひとつのpostに複数のcommentsを関連づられるよう、commentsテーブルに外部キー制約を設定しています。

原因

外部キーを呼び出す側(comments.post_id)と呼び出される側(posts.id)のデータ型が一致していないため。
※ここではunsignedは無視してください。

外部キーを呼び出す側(comments.post_id

$table->unsignedInteger('post_id');   # int unsigned

呼び出される側(posts.id

$table->bigIncrements('id');          # bigint

対処

外部キーを呼び出す側(comments.post_id)を以下のように変更します。

$table->unsignedBigInteger('post_id');   # bigint unsigned