Cannot truncate a table referenced in a foreign key constraintがlaravelのシーディング中に発生したら

目的(purpose)

laravelの勉強中にシーディングなるものがあることを知りました。
これはテストデータ等をコマンドでデータベースの任意のテーブルに登録できる仕組みらしい
早速使ってみたところ


 SQLSTATE[42000]: Syntax error or access violation: 1701 Cannot truncate a table referenced in a foreign key constraint

このようなな感じでなぜかうまくいかなかった。
laravelのファイルを使った解決方法を探すのにとても苦労したので今回まとめてみました。

開発環境(Development environment)

原因(Cause)

関連したテーブル同士を結合するために子テーブル内に外部キーを設定していました。
その結果制約ができ、テーブル内のデータを削除しようとtruncateをしたところ


SQLSTATE[42000]: Syntax error or access violation: 1701 Cannot truncate a table referenced in a foreign key constraint

のエラーが出てしまった

解決(Solution)

外部キーの制約がエラーの問題であるので制約を一時的に外して対処しようと思います。
ネット上ではターミナルで直接操作する方法が多いですがlaravelのseedファイルを使って対処もできるのでその方法もまとめます。
seedファイル(seed file)

SampleTableSeeder.php

<?php

use Illuminate\Database\Seeder;

class SampleTableSeeder extends Seeder
{
    public function run()
    {
        DB::statement('set foreign_key_checks = 0;');  // 外部キー制約を無視する
        DB::table('samples')->truncate();  // samplesテーブル(自分で用意したテーブル)内のデータを削除する
        DB::statement('set foreign_key_checks = 1;');  // 無視した外部キーの制約を元に戻す
    }
}

set foreign_key_checks0に設定することで外部キーの制約を無視することができます。
このコードは親のテーブル、子のテーブルのseedファイルどちらも同じやり方で対処できます。

ターミナル(Terminal)

一応ターミナルでSQLコマンドを使ってテーブルを操作する方法もまとめます。
公式のドキュメントと他の記事を参考にしました。
以下二つの記事参照

readouble.com

hacknote.jp


$ mysql -u ユーザ名 -p

まずは上記のコマンドでmysqlにログインします。
ユーザ名のところはrootでも良いのですが
自分で作成したユーザでも良いです。
以下のコマンドでユーザの一覧を確認できます。

mysql> select Host, User from mysql.user;
+-----------+------------------+
| Host      | User             |
+-----------+------------------+
| localhost | mysql.infoschema |
| localhost | mysql.session    |
| localhost | mysql.sys        |
| localhost | root             |  <= rootユーザー
| localhost | sampleUser       |  <= 自分で作成した新規ユーザー
+-----------+------------------+
5 rows in set (0.00 sec)

ログインするとmysql>が表示されます

mysql> use sampleDB  ‥1
mysql> set foreign_key_checks = 0;  ..2
Query OK, 0 rows affected (0.00 sec)

mysql> truncate table samples;  ..3
Query OK, 0 rows affected (0.02 sec)

mysql> set foreign_key_checks = 1;  ..4
Query OK, 0 rows affected (0.00 sec)

  • 1: 操作したいテーブルが存在するデータベースを使うための設定
  • 2: 外部キーの制約を無視する
  • 3: samplesテーブル(自分で用意したテーブル)内のデータを削除する
  • 4: 2で外部キーの制約を無視したのを元に戻す
以上でターミナル操作でも外部キーが設定されているテーブルを操作することができます。

最後に(Finally)

今回はlaravelでシーディングをした際に発生したエラーの対処方法をまとめてみました。
何か参考になれば幸いです。
ここまで読んでくれてありがとう!!