何が発生?
Adminerにて、とあるデータベース内にあるテーブルすべてを
TRUNCATE TABLE テーブル名;
でトランケート(テーブル内のレコードのみを削除)し、
Seederでデータを一括登録し直し、
migrateした際、
SQLSTATE[42S01]: Base table or view already exists: 1050 Table 'users' already exists (Connection: mysql, SQL: create table users
(id
bigint unsigned not null auto_increment primary key, name
varchar(255) not null, email
varchar(255) not null, email_verified_at
timestamp null, password
varchar(255) not null, remember_token
varchar(100) null, created_at
timestamp null, updated_at
timestamp null) default character set utf8mb4 collate 'utf8mb4_unicode_ci')
と出た件。
users
という名前のテーブルが既に存在しているのに、再度作成しようとしているとのこと。
いつ発生?
Laravelにて開発中案件のデータに不備があり、Gitでリモートのdevelopリポジトリから最新の情報をpullした際
なぜ発生?
上司曰く、
migrationsテーブルもトランケートした場合、最初からマイグレーションファイルを動かすので、その影響だと思う
とのこと。
というわけで、migrations
テーブルの中身を(Seederで再登録してから)確認してみた。
なるほど、
migrations
テーブル内のデータが、マイグレーションのログ、バージョン管理になっているので、このデータを消すとテーブルごと全部消さないと、再実行できない
みたいですね。
解決策
なので、今後、データを消す場合などは、
migrations
テーブルを残して消す
か、
テーブルごと、ごっそり消すか
という対応を取ると良いそう。
ちなみに、トランケートする場合は、すべてのテーブルを一括してというコマンドが無いので、いちいちテーブル名を指定して、トランケートしたいテーブル名の数だけ
TRUNCATE TABLE テーブル名;
と書く必要があるみたいなので、実行したいテーブルが多いと・・・これはやめといたほうが良さげかな🤔
というわけで、テーブルごとごっそり消した上で、Seederの実行と一緒にmigrationまでを行なってくれる、
php artisan migrate:fresh --seed
を実行し、無事にエラーが出ずに通りました!
ちなみに、
php artisan migrate:freshとは別に、
php artisan migrate:refresh
というコマンドもあるみたいで、その違いをざっと調べてみたところ、
php artisan migrate:fresh
- すべてのマイグレーションをロールバック(逆の手順で実行)して、テーブルを削除します。
- 全てのマイグレーションを再実行して、新しいテーブルとカラムを作成します。
php artisan migrate:refresh
- 一度実行されたマイグレーションをロールバックし、テーブルを削除します。
- ロールバックされたマイグレーションを再実行し、テーブルとカラムを再作成します。
- データベース内のデータは、ロールバック時に一時的に保存され、再実行後に再挿入されます。
うん、わからん😅
もうちょい詳しく調べてみると・・・
「refresh」のほうは、
- マイグレーションテーブルのデータ: migrations テーブルに格納されているマイグレーションの実行状態は保持されます。これにより、マイグレーションの実行履歴が保持されます。
- Seeder の実行結果: DatabaseSeeder クラスなどで定義されたシーディング処理によって挿入されたデータは保持されます。つまり、シーダーで作成されたデータはリセット後も存在し、再実行されます。
ということらしい。
なら、今回はmigrations
テーブルの中身を消しちゃってたので、「fresh」のほうでよかったということですかね💡