MySQL 8.0报“Invalid default value for 'xxx'”根本原因是NO_ZERO_DATE和NO_ZERO_IN_DATE严格模式拒绝'0000-00-00'等零日期默认值,需通过SET SESSION临时绕过或修改配置文件永久修复。

MySQL 8.0 报 Invalid default value for 'xxx',基本就是 NO_ZERO_DATE 或 NO_ZERO_IN_DATE 在拦路——不是语法错,是默认值被严格模式直接拒绝了。
查当前 sql_mode 是不是真含那俩禁令
连上 MySQL 后第一件事:SELECT @@sql_mode;。只要结果里有 NO_ZERO_DATE 和/或 NO_ZERO_IN_DATE,就坐实了问题根源。这两个模式在 8.0 默认开启,而老脚本里常见的 DEFAULT '0000-00-00' 或 DEFAULT '0000-00-00 00:00:00' 直接越界。
- DATE 类型最小合法值是
'1000-01-01','0000-00-00'不在范围内 - DATETIME 最小是
'1000-01-01 00:00:00',TIMESTAMP 最小是'1970-01-01 00:00:01' - 哪怕字段声明了
NOT NULL,MySQL 8.0 也不认零值“占位”,它认为这是语义错误
临时绕过:只对当前会话松绑(导入 SQL 文件时最实用)
不改全局配置、不重启服务,适合一次性导入旧脚本。在 SQL 文件最开头加这一行:
SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode, 'NO_ZERO_IN_DATE,NO_ZERO_DATE', ''));
注意点:
- 必须写在建表语句之前,且是第一条可执行语句
- 只影响本次连接,关掉终端或断开重连就失效,不影响其他会话
- 别写成
SET GLOBAL,否则需要 SUPER 权限,而且可能影响线上行为 - 如果两个 mode 不是紧挨着的(比如中间有空格或顺序不同),用两次
REPLACE更稳妥
ALTER TABLE 时报 1067 错误:不能只改类型不清理默认值
比如想把 timestamp 改成 datetime,但原字段定义是 DEFAULT '0000-00-00 00:00:00',执行 MODIFY COLUMN create_time datetime NOT NULL DEFAULT '0000-00-00 00:00:00' 必报错。
- MySQL 会在修改时校验:新类型下,这个默认值是否合法?答案是否定的
- 必须显式替换为有效值,例如:
DEFAULT '2000-01-01 00:00:00'或DEFAULT CURRENT_TIMESTAMP - 多个字段一起改要用逗号分隔,不能拆成两条
MODIFY,否则第二条会因事务未提交而失败 - 如果字段允许
NULL,改成DEFAULT NULL也行,但得确认业务逻辑能接受空值
永久修复要改配置文件,但千万别删错关键字
编辑 /etc/my.cnf(Linux)或 my.ini(Windows),在 [mysqld] 下加一行:
sql-mode="STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"
重点:
- MySQL 8.0 已彻底移除
NO_AUTO_CREATE_USER,如果配置里还留着,MySQL 启动会失败 - 别清空整个
sql-mode,尤其是别去掉STRICT_TRANS_TABLES——否则可能引发静默截断等更难排查的问题 - 改完必须重启 MySQL 服务,且所有新连接才会生效;已存在的连接仍沿用旧 session mode
- 生产环境建议优先改表结构而非降级 sql_mode,毕竟零日期本身就不具备业务含义
真正容易被忽略的是:即使你把 sql_mode 调得再宽松,explicit_defaults_for_timestamp=ON(8.0 默认)也会让 NOT NULL timestamp 字段在插入时不显式赋值就直接报 1048 - Column xxx cannot be null——这和零日期无关,是另一层机制,得单独处理。


















