insert时created_at不自动赋值因默认值优先于触发器;update时updated_at不更新因on update需实际数据变更;触发器中统一用now()并设会话时区;多时间字段需判空防覆盖;timestamp有2038年限制应选datetime。

INSERT 时 created_at 不自动赋值?检查字段默认值和触发器优先级
MySQL 触发器在 INSERT 场景下无法覆盖已有值,如果 created_at 字段本身定义了 DEFAULT CURRENT_TIMESTAMP,又在 BEFORE INSERT 触发器里手动赋值,实际生效的是字段默认值——因为 MySQL 会先应用默认值,再执行触发器逻辑,而触发器对已非 NULL 的字段赋值会被忽略。
实操建议:
- 确保
created_at字段声明为created_at DATETIME DEFAULT CURRENT_TIMESTAMP,且不设NOT NULL以外的约束(避免插入NULL被拦截) - 若必须用触发器(比如要兼容旧表结构或做额外逻辑),把字段默认值设为
DEFAULT NULL,并在BEFORE INSERT中显式判断:IF NEW.created_at IS NULL THEN SET NEW.created_at = NOW(); END IF;
- 不要在
INSERT语句中显式传入created_at值,除非你真想覆盖它
UPDATE 时 updated_at 没变?ON UPDATE CURRENT_TIMESTAMP 有前提
仅靠字段定义 updated_at DATETIME ON UPDATE CURRENT_TIMESTAMP 并不能保证每次 UPDATE 都刷新——它只在「至少一个其他字段值发生变更」时触发。如果执行 UPDATE t SET updated_at = updated_at WHERE id = 1 或更新前后所有字段值完全一致,MySQL 会跳过时间戳更新。
实操建议:
- 生产环境慎用纯字段定义方案,尤其涉及软删除、状态轮转等可能“无实质变更”的场景
- 推荐统一走
BEFORE UPDATE触发器:SET NEW.updated_at = NOW();
它强制生效,不受数据是否真变影响 - 注意:如果表里同时存在
ON UPDATE CURRENT_TIMESTAMP和触发器,两者会共存,但触发器优先级更高,可覆盖字段定义行为
触发器里用 NOW() 还是 CURRENT_TIMESTAMP?时区一致性是关键
两者在大多数情况下等价,但本质不同:NOW() 返回语句开始执行时的时间,CURRENT_TIMESTAMP 是 SQL 标准函数,在 MySQL 中与 NOW() 行为一致;真正影响结果的是会话时区设置。如果应用连接时未显式设置 time_zone,而服务器用的是系统时区(如 CST),可能导致日志、报表和数据库时间错位。
实操建议:
- 在应用层连接池初始化时,统一执行
SET time_zone = '+08:00'(按实际需求调整) - 触发器内统一用
NOW()即可,语义清晰,无需额外封装 - 避免混用
SYSDATE()—— 它返回函数执行时刻时间,同一语句中多次调用可能产生微小差异,不适合做一致性时间戳
多字段时间戳 + 软删除字段共存?触发器顺序和判空逻辑不能省
当表同时有 created_at、updated_at、deleted_at 时,常见错误是触发器里只处理 updated_at,却没判断 deleted_at 是否被设为非 NULL,导致软删除操作后 updated_at 反而被重置,掩盖了真实删除时间。
实操建议:
-
BEFORE UPDATE触发器中,先检查NEW.deleted_at是否被修改:IF NEW.deleted_at IS NOT NULL AND (OLD.deleted_at IS NULL OR OLD.deleted_at != NEW.deleted_at) THEN SET NEW.updated_at = NOW(); END IF;
- 若业务要求「软删除后禁止更新其他字段」,应在触发器开头加校验:
IF OLD.deleted_at IS NOT NULL THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Cannot update deleted record'; END IF; - 所有时间字段都建议用
DATETIME类型,而非TIMESTAMP—— 后者受 MySQL 5.6+ 自动转换时区影响,且最大范围仅到 2038 年
最易被忽略的是:触发器不会自动传播到外键关联表,如果主表更新依赖子表时间戳,得在子表单独建对应触发器,不能指望级联更新带过来。











