MySQL 5.7 禁止在 DEFAULT 中使用 NOW() 等非确定性函数,仅允许 CURRENT_TIMESTAMP(及其同义词)用于 TIMESTAMP/DATETIME 类型,且 DATETIME 需显式精度;推荐用 TIMESTAMP DEFAULT CURRENT_TIMESTAMP 以保兼容。

MySQL 5.7 报 Invalid default value for 'xxx' 的根本原因
不是语法写错了,也不是权限问题,而是 MySQL 5.7 明确禁止在 DEFAULT 子句中使用 NOW()(以及 SYS_DATE()、CURRENT_TIME() 等)作为非时间类型字段的默认值。只有 CURRENT_TIMESTAMP(及其同义词 LOCALTIME、LOCALTIMESTAMP)被允许,且仅限于 TIMESTAMP 和 DATETIME 类型。
DATETIME DEFAULT NOW() 为什么在 5.7 里直接报错?
MySQL 5.7 的 SQL 模式和默认行为严格区分“确定性”与“非确定性”函数:NOW() 被视为非确定性函数(即使事务内结果一致),而 DEFAULT 要求表达式必须是确定性的。官方只把 CURRENT_TIMESTAMP 当作特例豁免。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
-
DEFAULT CURRENT_TIMESTAMP✅ 合法,5.7 支持(需配合DATETIME或TIMESTAMP) -
DEFAULT NOW()❌ 报错 1064,无论字段类型是DATETIME还是TIMESTAMP -
DEFAULT CURRENT_DATE❌ 在 5.7 中不合法(8.0.13+ 才支持带括号的(CURRENT_DATE))
想在 5.7 里让 DATETIME 字段自动填当前时间,只能这样干
别指望靠改个默认值一劳永逸——5.7 对 DATETIME 的默认值支持是有条件的:必须用 CURRENT_TIMESTAMP,且建表时要显式声明精度(如 DATETIME(0)),否则可能因隐式精度不匹配再报错。
- ✅ 正确写法:
create_time DATETIME DEFAULT CURRENT_TIMESTAMP - ✅ 兼容性更强写法(推荐):
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP(TIMESTAMP在所有 5.7 版本中都稳) - ⚠️ 注意:
TIMESTAMP自动转时区,DATETIME不转;如果业务依赖固定时区(比如全用 UTC 存储),选DATETIME更可控 - ? 触发器兜底虽可行,但增加执行开销,且对批量
INSERT ... SELECT场景无效(触发器不触发)
容易被忽略的兼容性细节
很多人在本地开发环境(MySQL 8.0+)写好 DEFAULT NOW(),上线到生产(5.7)就炸,不是版本没对齐,而是连 explicit_defaults_for_timestamp 这个参数都可能影响行为:若设为 OFF(5.7 默认),TIMESTAMP 字段会隐式加 NOT NULL 和默认值,导致你手动写的 DEFAULT CURRENT_TIMESTAMP 被覆盖或冲突。
- 检查当前值:
SELECT @@explicit_defaults_for_timestamp; - 安全起见,建表时显式写全:
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP - 已有表加默认值?别用
MODIFY COLUMN,要用CHANGE COLUMN重定义字段,否则原NOT NULL或注释等属性会丢

















