Mysql

关注公众号 jb51net

关闭
首页 > 数据库 > Mysql > MySQL为时间字段设置当前时间

MySQL为时间字段设置默认当前时间的方法技巧

作者:李少兄

文章详细介绍了MySQL中记录创建时间和最后修改时间的最佳实践,包括时间类型的支持、默认值函数的使用、MySQL版本的演进、常见错误的修复以及高级技巧,建议使用DATETIME或TIMESTAMP类型,并在DEFAULT子句中使用CURRENT_TIMESTAMP函数,需要的朋友可以参考下

前言

在现代应用系统中,记录数据的创建时间create_time)和最后修改时间update_time)是数据库设计的基本规范。这类字段不仅用于业务逻辑(如“最近更新”排序),更是审计追踪、数据同步、缓存失效策略的核心依据。

然而,许多开发者在实现这一看似简单的功能时,常因对 MySQL 时间类型、函数支持、版本兼容性理解不足而写出语法错误行为异常的 SQL。例如:

一、核心概念:哪些时间类型支持“当前时间”默认值?

MySQL 提供多种时间相关数据类型,但并非都支持动态默认值:

数据类型是否支持 DEFAULT CURRENT_TIMESTAMP是否支持 ON UPDATE CURRENT_TIMESTAMP备注
DATE❌(8.0.13+ 支持 (CURRENT_DATE)仅存储日期,无时间部分
TIME仅存储时间
DATETIME✅(5.6.5+)✅(5.6.5+)存储范围大(1000–9999年),与时区无关
TIMESTAMP✅(所有版本)✅(所有版本)存储范围小(1970–2038),自动时区转换

结论

  • 若需自动记录当前时间,必须使用 DATETIME 或 TIMESTAMP
  • DATE 和 TIME 不适合用于自动时间戳场景(除非明确使用 MySQL 8.0.13+ 的新特性)。

二、唯一合法的默认时间函数:CURRENT_TIMESTAMP

DEFAULT 子句中,只有以下函数形式被允许

CURRENT_TIMESTAMP
LOCALTIME
LOCALTIMESTAMP

它们是等价的,且必须以无参数形式出现(可带精度,如 CURRENT_TIMESTAMP(6))。

常见非法写法(会导致 1064 错误):

错误写法原因
DEFAULT NOW()NOW() 不是合法的默认值表达式
DEFAULT current_timeCURRENT_TIMETIME 类型函数,不能用于 DATETIME 默认值
DEFAULT CURRENT_DATE(无括号)即使在 8.0.13+,也必须写成 (CURRENT_DATE)
DEFAULT sysdate()不支持

记住:在 DEFAULT 中,只认 CURRENT_TIMESTAMP

三、MySQL 版本演进

3.1 MySQL 5.6.5 之前(已淘汰)

3.2 MySQL 5.6.5 ~ 8.0.12(主流稳定版本)

DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP

3.3 MySQL 8.0.13+(现代特性)

report_date DATE DEFAULT (CURRENT_DATE)
expire_at DATETIME DEFAULT (NOW() + INTERVAL 30 DAY)

建议:除非你 100% 确定生产环境为 8.0.13+,否则不要依赖 DATE 的函数默认值。

四、标准建表示例

示例 1:基础自动时间字段(兼容 5.6.5+)

CREATE TABLE user_account (
    id            BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    username      VARCHAR(64) NOT NULL UNIQUE,
    email         VARCHAR(128) NOT NULL,

    -- 创建时间:插入时自动设为当前时间
    create_time   DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,

    -- 更新时间:插入时设为当前时间,每次 UPDATE 自动刷新
    update_time   DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP 
                               ON UPDATE CURRENT_TIMESTAMP,

    INDEX idx_update_time (update_time)
) ENGINE=InnoDB 
  DEFAULT CHARSET=utf8mb4 
  COLLATE=utf8mb4_unicode_ci 
  COMMENT='用户账户表';

优势

示例 2:仅记录创建时间(不可变)

CREATE TABLE audit_log (
    id          CHAR(36) PRIMARY KEY,  -- UUID
    event_type  VARCHAR(50) NOT NULL,
    payload     JSON NOT NULL,

    -- 仅创建时记录,后续永不修改
    create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
) COMMENT='审计日志表';

🔒 注意:若需确保 create_time 不被意外更新,可在应用层禁止修改,或通过触发器保护。

示例 3:使用 TIMESTAMP(谨慎选择)

CREATE TABLE system_event (
    id         BIGINT AUTO_INCREMENT PRIMARY KEY,
    message    TEXT NOT NULL,

    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP 
                              ON UPDATE CURRENT_TIMESTAMP
) COMMENT='系统事件表';

⚠️ 风险提示

示例 4:MySQL 8.0.13+:为 DATE 设置默认当前日期

-- 仅适用于 MySQL >= 8.0.13
CREATE TABLE daily_summary (
    id           INT AUTO_INCREMENT PRIMARY KEY,
    total_orders INT NOT NULL,

    -- 自动设为当前日期(无时间)
    summary_date DATE NOT NULL DEFAULT (CURRENT_DATE),

    -- 完整时间戳
    created_at   DATETIME NOT NULL DEFAULT (NOW())
) COMMENT='每日汇总表';

关键:必须使用 括号 (CURRENT_DATE),这是函数默认值的语法要求。

五、常见错误

错误 1:[1064] near 'current_date null comment ...'

错误语句

create_date DATE DEFAULT current_date NULL COMMENT '创建日期'

原因

  1. current_date 是保留关键字,未转义(虽非主因);
  2. 更关键的是:在大多数 MySQL 版本中,DATE 类型不支持 CURRENT_DATE 作为默认值;
  3. 即使支持(8.0.13+),也必须写成 (CURRENT_DATE)

修复

-- 方案A:升级到 8.0.13+ 并加括号
create_date DATE DEFAULT (CURRENT_DATE)

-- 方案B:放弃默认值,由应用插入 CURDATE()
create_date DATE

-- 方案C:改用 DATETIME
create_time DATETIME DEFAULT CURRENT_TIMESTAMP

错误 2:DEFAULT current_time

错误语句

create_time DATETIME DEFAULT current_time

原因

修复

create_time DATETIME DEFAULT CURRENT_TIMESTAMP

错误 3:混淆NULL与默认值顺序

不规范写法

create_time DATETIME DEFAULT CURRENT_TIMESTAMP NULL

规范写法

create_time DATETIME NULL DEFAULT CURRENT_TIMESTAMP
-- 或(更推荐)
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP

💡 时间字段通常不应为 NULL,建议设为 NOT NULL

六、高级技巧

6.1 微秒精度(MySQL 5.6.4+)

create_time DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
update_time DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) 
                             ON UPDATE CURRENT_TIMESTAMP(6)

6.2 生成列派生日期(避免 DATE 默认值问题)

CREATE TABLE log_entry (
    id          BIGINT PRIMARY KEY,
    event_time  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,

    -- 自动生成日期部分,物理存储
    event_date  DATE AS (DATE(event_time)) STORED
);

6.3 多个自动更新字段(MySQL 5.7+)

虽然一个表通常只需一个 update_time,但技术上可定义多个:

last_modified DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
synced_at     DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP

但业务上应避免冗余。

七、最佳实践

项目推荐做法
数据类型优先 DATETIME(范围大、无时区干扰)
创建时间create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
更新时间update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
是否允许 NULL时间字段建议 NOT NULL
命名规范create_time / update_timecreated_at / updated_at(团队统一)
时区策略应用层统一使用 UTC 时间,数据库存 DATETIME
旧版本兼容避免 DATE 默认值,用 DATETIME 替代
保留字切勿使用 current_datetime 等作列名

补充说明:MySQL 8.0.13+ 的“函数默认值”(Functional Default Values)

MySQL 8.0.13 开始,官方引入了 WL#12593: Functional key parts and functional default values,其中一项重大改进是:

允许在任何列类型上使用“标量表达式”作为默认值,只要该表达式满足确定性、无副作用、不依赖子查询或用户变量等条件。

这意味着:

支持的典型时间类表达式示例(MySQL ≥ 8.0.13):

-- 1. DATE 类型:默认当前日期
report_date DATE DEFAULT (CURRENT_DATE),

-- 2. DATETIME 类型:仍可使用 CURRENT_TIMESTAMP(无需括号,因属历史特例)
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,

-- 3. DATETIME 类型:也可用括号形式(推荐统一风格)
created_at DATETIME DEFAULT (NOW()),

-- 4. DATETIME 类型:复杂表达式(如 7 天后过期)
expire_at DATETIME DEFAULT (NOW() + INTERVAL 7 DAY),

-- 5. YEAR 类型
fiscal_year YEAR DEFAULT (YEAR(CURDATE())),

-- 6. 甚至非时间类型
random_code VARCHAR(10) DEFAULT (SUBSTRING(MD5(RAND()), 1, 10)),
initial_score INT DEFAULT (0),

重要区别:带括号 vs 不带括号

写法含义是否合法
DEFAULT CURRENT_TIMESTAMP特殊保留语法(向后兼容)✅ 所有版本(5.6.5+ 对 DATETIME)
DEFAULT (CURRENT_TIMESTAMP)函数默认值表达式✅ 仅 8.0.13+
DEFAULT CURRENT_DATE非法(DATE 不支持此特例)❌ 所有版本
DEFAULT (CURRENT_DATE)函数默认值表达式✅ 仅 8.0.13+

结论

以上就是MySQL为时间字段设置默认当前时间的方法技巧的详细内容,更多关于MySQL为时间字段设置当前时间的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文