mysql 8.0 报“invalid default value for 'xxx'”根本原因是严格模式默认启用no_zero_date和no_zero_in_date,禁止date/datetime/timestamp使用'0000-00-00'等零值作为默认值,因其超出合法范围(如timestamp最小为'1970-01-01 00:00:01'),且alter table或导入旧脚本时未同步修正默认值导致校验失败。

MySQL 8.0 报 Invalid default value for 'xxx',基本就是日期类字段(DATE、DATETIME、TIMESTAMP)用了 '0000-00-00' 或 '0000-00-00 00:00:00' 这类零值默认值,且当前 sql_mode 含 NO_ZERO_DATE 或 NO_ZERO_IN_DATE。
为什么 '0000-00-00' 在 MySQL 8.0 不合法
MySQL 8.0 默认启用严格模式,其中 NO_ZERO_DATE 禁止 DATE 类型用全零日期作默认值;NO_ZERO_IN_DATE 则进一步禁止年/月/日中任意部分为零(比如 '2020-00-01')。而老项目 SQL 脚本常沿用 MySQL 5.6/5.7 宽松模式下的写法,直接写 DEFAULT '0000-00-00',升级后就卡在这儿。
-
SELECT @@sql_mode;一定能查出NO_ZERO_DATE和NO_ZERO_IN_DATE(除非你已手动改过) -
DATETIME和TIMESTAMP的合法最小值分别是'1000-01-01 00:00:00'和'1970-01-01 00:00:01','0000-00-00'不在范围内 - 哪怕字段是
NOT NULL,也不能靠零值“占位”——MySQL 8.0 认为这是语义错误,不是缺失值
ALTER TABLE 修改字段时触发 1067 - Invalid default value
这不是建表报错,而是改结构时报的。典型场景:把 TIMESTAMP 改成 DATETIME,但原 DEFAULT '0000-00-00 00:00:00' 没清理干净。
- 单条
MODIFY COLUMN语句里带零值默认值,必报1067 - 不能只改类型不改默认值,MySQL 会校验新类型下旧默认值是否合法
- 必须显式替换为有效日期,例如:
DEFAULT '2000-01-01 00:00:00'或DEFAULT CURRENT_TIMESTAMP - 多个字段要一起改(用逗号分隔),否则第二次
MODIFY会因前一次未提交而失败
导入 SQL 文件时怎么绕过或修复
直接运行老脚本失败,有两个务实路径:
- 在 SQL 文件最开头加一行:
SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode, 'NO_ZERO_IN_DATE,NO_ZERO_DATE', ''));—— 仅对当前导入会话生效,不影响全局 - 逐个定位出错字段,把
DEFAULT '0000-00-00'改成DEFAULT '1970-01-01'或DEFAULT NULL(前提是字段允许NULL) - 如果字段定义含
CURRENT_TIMESTAMP但报错,说明是低版本语法混入(如DATETIME不支持该默认值),得换成TIMESTAMP或删掉默认值 - 千万别用
SET GLOBAL sql_mode = ''清空所有模式——会关掉STRICT_TRANS_TABLES,导致数据静默截断等更隐蔽问题
真正麻烦的不是改一句 SQL,而是得确认业务逻辑是否依赖那个“零日期”语义。如果代码里写了 WHERE date_field = '0000-00-00',那换掉默认值后,这部分逻辑也得同步调整。这点容易被忽略。











