这不是语法错误,而是MySQL 5.7+默认启用NO_ZERO_DATE和NO_ZERO_IN_DATE模式导致零日期校验失败;需通过SELECT @@sql_mode确认是否启用,临时可SET SESSION修改,永久应修改配置文件并重启服务。

直接结论:这不是语法错误,是 MySQL 5.7+ 默认启用 NO_ZERO_DATE 和 NO_ZERO_IN_DATE 模式导致的校验失败——只要字段默认值含 '0000-00-00' 或 '0000-00-00 00:00:00',就必然报错 Err 1067。
查当前 sql_mode 是不是真有问题
先确认是不是这个原因,别白改:
- 执行
SELECT @@sql_mode;,如果结果里包含NO_ZERO_DATE和/或NO_ZERO_IN_DATE,就是它了 - 注意:
NO_ZERO_DATE禁用'0000-00-00'(DATE 类型),NO_ZERO_IN_DATE还会禁用类似'2020-00-01'这种月/日为零的写法 - 别只看文档说“5.7 默认开启”,有些 Docker 镜像或云数据库(如阿里云 RDS)可能已预调低严格度,得实查
临时绕过:只对当前会话生效(适合调试和单次导入)
适用于 Navicat 手动执行、命令行快速验证,但不解决自动化脚本问题:
- 在建表前加一句:
SET SESSION sql_mode = REPLACE(@@sql_mode, 'NO_ZERO_IN_DATE,NO_ZERO_DATE', ''); - 逗号和空格必须完全匹配当前
@@sql_mode值,否则替换失败;建议先SELECT @@sql_mode;复制粘贴再删 - 该设置对 PHP/Java 应用新建连接无效,Navicat 导入 SQL 文件时也常不复用该会话
- 它不能修复
DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00'这类组合——MySQL 5.7+ 下,只要字段是NOT NULL,零日期就永远非法
永久修复:改配置文件并重启服务(生产环境唯一推荐方式)
这是唯一能确保所有连接、所有脚本都一致生效的做法,漏重启等于白改:
- Linux:编辑
/etc/my.cnf或/etc/mysql/my.cnf,在[mysqld]段下添加:sql-mode="ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION" - Windows:修改
my.ini的[mysqld]段,内容同上 - macOS:若无
/etc/my.cnf,从/usr/local/mysql/support-files/my-default.cnf复制一份再改 - 改完必须重启服务:
sudo systemctl restart mysql(Linux)、服务管理器(Win/mac);reload不生效
更安全的替代方案:改默认值,不动 sql_mode
尤其当团队已依赖 STRICT_TRANS_TABLES 等模式做数据质量控制时,改字段比改全局配置更稳妥:
-
DATE字段避免DEFAULT '0000-00-00',换成业务可接受的兜底值,例如DEFAULT '1000-01-01'或DEFAULT '2000-01-01' -
DATETIME/TIMESTAMP字段优先用DEFAULT CURRENT_TIMESTAMP,但注意:DATETIME从 5.6.5 起才支持,且必须显式写出DEFAULT关键字 - 绝对不要写
NOT NULL DEFAULT '0000-00-00 00:00:00'—— 这个组合在 5.7+ 下无论sql_mode如何设置,都 100% 报错 - ALTER TABLE 修改字段类型时(比如把
TIMESTAMP改成DATETIME),旧的零值默认值不会自动转换,必须同步用MODIFY COLUMN ... DEFAULT '2000-01-01 00:00:00'显式覆盖
最容易被忽略的一点:配置文件改完不重启,或 SQL 脚本里混用 NOT NULL 和零日期,默认值校验会在任何 DDL 操作(CREATE、ALTER、IMPORT)中触发,而且错误提示不指明具体哪一行——得靠 SELECT @@sql_mode; 和逐字段排查来定位。


















