You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel迁移报SQL默认值错误,但手动执行SQL正常

多非nullable Timestamp字段在MariaDB 5.5.x下的Laravel迁移报错解析

底层原因

MariaDB 5.5(及同版本线的MySQL)对TIMESTAMP类型存在历史限制:

  • 单表中最多仅能有一个非nullable且无显式默认值的TIMESTAMP字段,该字段会被自动赋予DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP属性。
  • 当尝试创建第二个这类TIMESTAMP字段时,数据库因无法生成合法默认值,再结合你的SQL_MODE中开启的NO_ZERO_DATE和NO_ZERO_IN_DATE规则,直接抛出1067 Invalid default value错误。

直接执行SQL无报错的原因

Laravel迁移执行与手动执行SQL的逻辑存在差异:

  • 通过php artisan migrate执行时,Schema Builder会隐式尝试为非nullable的TIMESTAMP字段设置默认值,而老版本MariaDB不支持多字段的这种自动处理,引发冲突。
  • 手动执行生成的SQL时,语句未显式指定默认值,数据库此时的解析逻辑会绕过该限制,但实际上这个表结构在严格模式下存在隐患——插入数据时若未指定send_after和send_before的值,仍会报错。

DateTime类型正常的原因

DATETIME类型从不存在TIMESTAMP的“单字段默认值绑定”限制,它不会自动生成默认值,只要插入时提供合法日期值,就不会触发SQL_MODE的相关限制。

解决方案

有以下几种可行处理方式:

  • 显式指定默认值:修改迁移代码,为非nullable的TIMESTAMP字段设置合法默认值,比如使用当前时间:
    $table->timestamp('send_after')->index()->useCurrent();
    $table->timestamp('send_before')->index()->useCurrent();
    
    也可根据业务需求设置其他固定默认值。
  • 改用DateTime类型:若不需要TIMESTAMP的自动更新特性,直接替换为datetime类型:
    $table->dateTime('send_after')->index();
    $table->dateTime('send_before')->index();
    
  • 调整SQL_MODE(不推荐):临时移除NO_ZERO_DATE和NO_ZERO_IN_DATE模式,但这会降低数据严格性,可能引入无效日期值,生产环境不建议使用。

内容的提问来源于stack exchange,提问作者Yevgen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 12:50:23