Laravel 9迁移建表时created_at默认值错误及字符集疑问
问题解答
疑问一:建表语句为何使用utf8mb4_unicode_ci而非数据库的utf8_general_ci?
这是Laravel框架的默认配置行为:
- 在Laravel的
config/database.php配置文件中,MySQL数据库的默认字符集被设置为utf8mb4,排序规则为utf8mb4_unicode_ci。 - 执行迁移时,Laravel会忽略数据库层面的字符集设置,直接使用配置文件中定义的参数生成建表语句,所以最终表的字符集为
utf8mb4_unicode_ci。
如果需要改为和数据库一致的utf8_general_ci,有两种方式:
- 修改
config/database.php中的mysql配置项:
'mysql' => [ // ...其他配置 'charset' => 'utf8', 'collation' => 'utf8_general_ci', ],
- 在迁移文件中手动指定表的字符集:
Schema::create('user_meetings', function (Blueprint $table) { $table->charset = 'utf8'; $table->collation = 'utf8_general_ci'; // ...其他字段定义 });
疑问二:建表操作为何触发created_at默认值无效的错误?
问题出在MySQL的sql_mode设置和迁移字段定义上:
- 你的
created_at字段被定义为$table->timestamp('created_at');,意味着该字段非空但未设置默认值。 - 你的MySQL服务器开启了
NO_ZERO_IN_DATE或NO_ZERO_DATE的sql模式,这两个模式禁止将'0000-00-00 00:00:00'作为timestamp字段的默认值(MySQL在未指定默认值时会尝试用这个值填充非空timestamp字段),因此触发了1067 Invalid default value错误。
解决方法有两种:
- 修改迁移字段定义:给
created_at设置默认值为当前时间,或者直接使用Laravel内置的timestamps()方法(自动处理created_at和updated_at的非空+默认规则):
// 方式一:手动设置默认值 $table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP')); $table->timestamp('updated_at')->nullable(); // 方式二:使用Laravel内置方法 $table->timestamps();
- 调整MySQL的sql_mode:去掉
NO_ZERO_IN_DATE和NO_ZERO_DATE模式。在MySQL配置文件(如/etc/mysql/my.cnf)中修改:
[mysqld] sql_mode = "ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"
修改后重启MySQL服务生效。
内容的提问来源于stack exchange,提问作者mstdmstd
相关产品推荐
相关产品推荐

