MySQL中DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP需显式声明NOT NULL才生效,否则ON UPDATE被忽略;INSERT...ON DUPLICATE KEY UPDATE不触发ON UPDATE,须显式赋值;DATETIME不支持该语法,需用触发器模拟。

MySQL 5.6.5+ 支持 CURRENT_TIMESTAMP 作为 DEFAULT 和 ON UPDATE 的值,但直接写 DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 在某些版本或存储引擎下会报错或行为异常——关键在于字段定义顺序、是否允许 NULL、以及是否显式声明 NOT NULL。
为什么 DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 有时不生效
MySQL 要求:如果字段同时指定 DEFAULT CURRENT_TIMESTAMP 和 ON UPDATE CURRENT_TIMESTAMP,该字段必须是 NOT NULL,且不能有默认值为 NULL(哪怕没显式写)。InnoDB 表中若字段定义为 TIMESTAMP NULL,即使写了 DEFAULT CURRENT_TIMESTAMP,MySQL 也会忽略 ON UPDATE 子句。
-
CREATE TABLE t (updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);—— 在 MySQL 8.0+ 默认成功,但 5.7 某些配置下可能静默降级为仅DEFAULT - 更稳妥写法是显式加
NOT NULL:updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP - 如果字段已存在,
ALTER TABLE ... MODIFY时未重申NOT NULL,会导致ON UPDATE被丢弃
ON UPDATE CURRENT_TIMESTAMP 只对 UPDATE 语句生效,不响应 INSERT ... ON DUPLICATE KEY UPDATE
这是常被忽略的边界场景:INSERT ... ON DUPLICATE KEY UPDATE 中的 UPDATE 分支,**不会自动触发** ON UPDATE CURRENT_TIMESTAMP,除非你在 SET 子句里显式赋值,比如 SET updated_at = CURRENT_TIMESTAMP。
- 错误预期:
INSERT INTO t (id, name) VALUES (1, 'a') ON DUPLICATE KEY UPDATE name = VALUES(name);→ 希望updated_at自动更新?不会 - 正确写法:
INSERT INTO t (id, name) VALUES (1, 'a') ON DUPLICATE KEY UPDATE name = VALUES(name), updated_at = CURRENT_TIMESTAMP; - 否则,该字段将保持原值,哪怕表定义里写了
ON UPDATE
使用 DATETIME 替代 TIMESTAMP 时必须用触发器模拟 ON UPDATE
MySQL 的 DATETIME 类型**不支持** ON UPDATE CURRENT_TIMESTAMP(仅 TIMESTAMP 支持),所以如果你因时区需求或精度要求选了 DATETIME,就得靠触发器补足:
CREATE TRIGGER t_update_updated_at BEFORE UPDATE ON t FOR EACH ROW SET NEW.updated_at = NOW();
- 触发器在
UPDATE时强制覆盖NEW.updated_at,效果等同于ON UPDATE - 注意:触发器无法处理
INSERT ... ON DUPLICATE KEY UPDATE的UPDATE分支(它走的是 INSERT 流程),仍需在 SQL 中显式赋值 - 触发器增加维护成本,且在批量更新时可能影响性能;若业务允许,优先用
TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
真正容易出问题的地方不是语法写错,而是跨版本兼容性(5.6/5.7/8.0 对 DEFAULT 和 ON UPDATE 的解析差异)、字段是否隐式为 NULL、以及 ON DUPLICATE KEY UPDATE 这种“看起来像 UPDATE 实际不算”的场景——这些地方不测数据,只看 DDL 很难发现时间戳停更。










