MySQL 5.7升级后因默认启用NO_ZERO_DATE和NO_ZERO_IN_DATE严格模式,禁止'0000-00-00'及'0000-00-00 00:00:00'作为datetime/timestamp默认值,导致Err 1067报错;需通过配置文件修改sql_mode并重启服务,或显式使用合法日期(如'1000-01-01')或CURRENT_TIMESTAMP解决。

MySQL 5.6 升级到 5.7 后,datetime 或 timestamp 字段设为 '0000-00-00 00:00:00' 或 '0000-00-00' 会直接报错,不是语法问题,是 5.7 默认启用了更严格的 SQL 模式校验。
为什么 Invalid default value for 'xxx' 会突然出现
根本原因是 MySQL 5.7 默认的 sql_mode 包含 NO_ZERO_DATE 和 NO_ZERO_IN_DATE:
-
NO_ZERO_DATE:禁止把'0000-00-00'当作合法的DATE默认值(哪怕字段允许 NULL) -
NO_ZERO_IN_DATE:禁止把'0000-00-00 00:00:00'这类含零年月日的时间值用于DATETIME/TIMESTAMP - 这两个选项在 5.6 中默认关闭,5.7 开启后,建表时只要碰到零日期字面量,就立刻触发
Err 1067
修改 sql_mode 去掉 NO_ZERO_DATE 的实操要点
不推荐直接清空 sql_mode,而是精准移除两个限制项。关键在于作用域和持久性:
- 临时生效(当前会话):
SET SESSION sql_mode = REPLACE(@@sql_mode, 'NO_ZERO_DATE,NO_ZERO_IN_DATE', '');但仅对当前连接有效,Navicat 导入、脚本执行等多数场景不继承该设置 - 全局生效(需重启或用 GLOBAL):
SET GLOBAL sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';注意:GLOBAL 修改在服务重启后丢失,必须同步改配置文件 - 配置文件修改位置:
- Linux:
/etc/my.cnf或/etc/mysql/my.cnf的[mysqld]段下加sql-mode="..." - Windows:
my.ini的[mysqld]段 - macOS:若无
my.cnf,从/usr/local/mysql/support-files/my-default.cnf复制并重命名为/etc/my.cnf
- Linux:
- 改完必须重启 MySQL:
sudo systemctl restart mysql(Linux)或服务管理器重启(Win/mac)
CURRENT_TIMESTAMP 在 datetime 上也报错?
是的——5.7 要求 datetime 类型使用 CURRENT_TIMESTAMP 作为默认值时,必须显式声明 DEFAULT CURRENT_TIMESTAMP,且不能同时设 NOT NULL DEFAULT '0000-00-00 00:00:00'。常见错误写法:
CREATE TABLE t (dt datetime NOT NULL DEFAULT '0000-00-00 00:00:00' DEFAULT CURRENT_TIMESTAMP);
正确写法应二选一:
- 用时间戳(推荐):
dt datetime DEFAULT CURRENT_TIMESTAMP(允许 NULL) - 用合法日期:
dt datetime NOT NULL DEFAULT '1970-01-01 00:00:00' - 或者干脆设为
NULL:dt datetime DEFAULT NULL
注意:timestamp 类型原生支持 CURRENT_TIMESTAMP,但 datetime 在 5.6+ 才支持,且受 sql_mode 影响更敏感。
真正容易被忽略的点
很多人在 Navicat 或 mysqldump 导入时只改了会话级 sql_mode,却没意识到导入工具通常新建独立连接,根本读不到你手动 SET 的 SESSION 设置;还有人改了配置文件但忘记重启 MySQL,导致改完白改。最稳妥的做法是:先确认 SELECT @@sql_mode 输出里确实不含 NO_ZERO_DATE 和 NO_ZERO_IN_DATE,再执行建表或导入操作。


















