MySQL错误1067:Invalid default value for 'xxx'
这个错误不是服务启动失败的系统级报错(那是Windows服务1067),而是执行
CREATE TABLE或
ALTER TABLE时触发的SQL层面报错,核心原因是字段默认值不合法——最常见的是给
NOT NULL的
DATETIME或
TIMESTAMP字段设了
DEFAULT NULL,或者用了已废弃的零日期(如
'0000-00-00')。
为什么严格模式下会报1067,而旧版本不报?
MySQL 5.7+ 默认启用严格SQL模式(
STRICT_TRANS_TABLES),此时对默认值校验变严。关键点:
TIMESTAMP字段若声明
NOT NULL,却指定
DEFAULT NULL→ 直接报1067
DATETIME在 5.7.5+ 不再隐式接受
'0000-00-00'作为默认值,除非显式关闭
NO_ZERO_DATE即使字段允许 NULL,
DEFAULT '0000-00-00 00:00:00'也会被拒绝(除非 SQL mode 中移除了
NO_ZERO_DATE)
快速修复:改默认值 or 调整SQL mode
优先推荐改表结构,避免依赖宽松模式:
把DEFAULT NULL改成有效时间,例如:
DEFAULT CURRENT_TIMESTAMP(
TIMESTAMP/5.6.5+
DATETIME支持) 把
NOT NULL去掉,如果业务允许该字段为空 用
CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP替代固定零值 临时绕过(不推荐生产):启动时加参数
--sql-mode="STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION"并去掉
NO_ZERO_DATE,但会掩盖数据质量问题
检查当前SQL mode和日期行为
运行这条语句确认实际生效的模式:
SELECT @@sql_mode;
重点关注是否含
STRICT_TRANS_TABLES、
NO_ZERO_DATE、
NO_ZERO_IN_DATE。再查零日期是否被禁用:
SELECT @@sql_mode LIKE '%NO_ZERO_DATE%';
如果返回
1,说明零日期已被禁止——这时任何含
'0000-00-00'的默认值都会触发1067。迁移老表时最容易漏掉这点,尤其从5.6升级到8.0后。
