报错
在我们实际开发中,经常会由于业务需要增加新的数据表,通常会通过laravel的迁移功能。假设我们此次要生成一个新表user_profiles,执行 php artisan migrate
,可能会遇到如下情况,提示说xx表已存在
1
PDOException::("SQLSTATE[42S01]: Base table or view already exists: 1050 Table 'users' already exists")
疑惑&解读
纳尼?我要生成的又不是这个表,这个表也确实早就存在了,为什么会这么提示?
当我们迁移数据库时,系统获取所有数据库迁移文件(包括 database/migrations 目录下和扩展包中注册的),然后按照文件名中包含的日期时间排序,从最早的迁移文件开始,依次执行每个迁移类中的 up 方法,最后完成数据库迁移
再简单一点说就是:在运行迁移命令 php artisan migrate
时,实际上是把database/migrations 目录下所有文件重新执行了一遍。
官网手册提供的方法就是删除所有表重新完成迁移,oh my god! 内心在抗拒好不好?!那怎么办呢?一顿搜索后,发现migrate命令可以指定目录,so ? do it !
解决办法
- 在
database/migrations
目录下创建一个新的目录,如 news- 把这次要迁移的文件移到news目录下
- 运行
make:migrate
命令时添加--path=PATH目录
选项
1 | php artisan migrate path=/database/migrations/news |
总结
这时会发现数据表新建成功了,到这里我们该知道,实际开发的时候要注意这些
- 每次数据库的变更 (如:增加删减字段、字段属性修改、新增删除表)看成是一个新的版本,应当建立相应的迁移文件
- 创建迁移文件时应使用–path选项指定路径(以版本号区分,便于回退至上版本,如v1、v1.1、v2、v3…等),如
1 | php artisan migrate:make user_profiles --path=/database/migrations/v2 |
- 迁移文件中的down方法记得完善,保证回滚迁移后再次执行迁移不会出错
- 删除表可使用drop或dropIfExists方法
1 | php artisan tinker |
- 没使用迁移命令删除表,使用了其他sql删除该表, 再执行迁移只会返回
Nothing to migrate.
这说明已经成功的迁移并不会重复执行,执行Schema::drop('user_profiles')
返回的是1
Illuminate/Database/QueryException with message 'SQLSTATE[42S02]: Base table or view not found: 1051 Unknown table 'user_profiles' (SQL: drop table `user_profiles`)'
怎么办呢?如果你足够细心的话,会知道自己数据库在使用迁移命令后,会加入一个名为migrations的新表,这个表存的是已经执行过的迁移文件名,所以找到相应的记录删掉就行啦!