前言
在现代应用系统中,记录数据的创建时间()和()是数据库设计的基本规范。这类字段不仅用于业务逻辑(如'最近更新'排序),更是审计追踪、数据同步、缓存失效策略的核心依据。
MySQL 时间字段设置默认当前时间的规范。对比 DATETIME 与 TIMESTAMP 类型在动态默认值支持上的差异,明确只有 CURRENT_TIMESTAMP 是合法默认函数。梳理从 5.6.5 到 8.0.13+ 的版本特性变化,特别是函数默认值的引入。提供兼容性强且符合行业惯例的建表示例,分析常见 1064 语法错误原因及修复方法。建议优先使用 DATETIME 类型,避免时区干扰,并采用 NOT NULL 约束确保数据完整性。

在现代应用系统中,记录数据的创建时间()和()是数据库设计的基本规范。这类字段不仅用于业务逻辑(如'最近更新'排序),更是审计追踪、数据同步、缓存失效策略的核心依据。
create_timeupdate_time然而,许多开发者在实现这一看似简单的功能时,常因对 MySQL 时间类型、函数支持、版本兼容性理解不足而写出语法错误或行为异常的 SQL。例如:
DEFAULT current_date 导致 [1064] You have an error in your SQL syntax;DATE 类型上尝试设置动态默认值却在旧版本中失败;CURRENT_TIME 与 CURRENT_TIMESTAMP;TIMESTAMP 的时区转换特性,引发数据不一致。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))。
| 错误写法 | 原因 |
|---|---|
DEFAULT NOW() | NOW() 不是合法的默认值表达式 |
DEFAULT current_time | CURRENT_TIME 是 TIME 类型函数,不能用于 DATETIME 默认值 |
DEFAULT CURRENT_DATE(无括号) | 即使在 8.0.13+,也必须写成 (CURRENT_DATE) |
DEFAULT sysdate() | 不支持 |
✅ 记住:在
DEFAULT中,只认CURRENT_TIMESTAMP。
TIMESTAMP 支持自动初始化/更新。TIMESTAMP 字段带 DEFAULT CURRENT_TIMESTAMP。DATETIME 完全不支持函数默认值。DATETIME(6) 表示微秒。DATETIME 和 TIMESTAMP 均支持:
DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP
( ),否则语法错误。引入 函数默认值(Functional Default Values):
report_date DATE DEFAULT(CURRENT_DATE)
expire_at DATETIME DEFAULT(NOW()+INTERVAL 30 DAY)
💡 建议:除非你 100% 确定生产环境为 8.0.13+,否则不要依赖
DATE的函数默认值。
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='用户账户表';
✅ 优势:
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不被意外更新,可在应用层禁止修改,或通过触发器保护。
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='系统事件表';
⚠️ 风险提示:
TIMESTAMP 存储为 UTC,查询时根据 time_zone 会话变量转换;DATETIME + 应用层处理时区(如始终存 UTC 时间)。-- 仅适用于 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),这是函数默认值的语法要求。
[1064] near 'current_date null comment ...'错误语句:
create_date DATE DEFAULT current_date NULL COMMENT'创建日期'
原因:
current_date 是保留关键字,未转义(虽非主因);DATE 类型不支持 CURRENT_DATE 作为默认值;(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
DEFAULT current_time错误语句:
create_time DATETIME DEFAULT current_time
原因:
CURRENT_TIME 返回 TIME 类型(如 14:30:00),不能赋值给 DATETIME;CURRENT_TIME不是合法的默认值函数。修复:
create_time DATETIME DEFAULT CURRENT_TIMESTAMP
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。
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) 表示 6 位微秒精度;CREATE TABLE log_entry (
id BIGINT PRIMARY KEY,
event_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
-- 自动生成日期部分,物理存储
event_date DATE AS(DATE(event_time)) STORED
);
event_date 无需函数计算,可建索引。虽然一个表通常只需一个 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_time 或 created_at / updated_at(团队统一) |
| 时区策略 | 应用层统一使用 UTC 时间,数据库存 DATETIME |
| 旧版本兼容 | 避免 DATE 默认值,用 DATETIME 替代 |
| 保留字 | 切勿使用 current_date、time 等作列名 |
从 MySQL 8.0.13 开始,官方引入了 WL#12593: Functional key parts and functional default values,其中一项重大改进是:
允许在任何列类型上使用'标量表达式'作为默认值,只要该表达式满足确定性、无副作用、不依赖子查询或用户变量等条件。
这意味着:
CURRENT_TIMESTAMP 这一特例;DATE、DATETIME、INT、VARCHAR 等类型均可使用括号包裹的函数或表达式作为默认值;( ) 显式声明这是一个表达式,这是语法强制要求。-- 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),
| 写法 | 含义 | 是否合法 |
|---|---|---|
DEFAULT CURRENT_TIMESTAMP | 特殊保留语法(向后兼容) | ✅ 所有版本(5.6.5+ 对 DATETIME) |
DEFAULT (CURRENT_TIMESTAMP) | 函数默认值表达式 | ✅ 仅 8.0.13+ |
DEFAULT CURRENT_DATE | 非法(DATE 不支持此特例) | ❌ 所有版本 |
DEFAULT (CURRENT_DATE) | 函数默认值表达式 | ✅ 仅 8.0.13+ |
📌 结论:在 8.0.13+ 中,
DATETIME字段既可以继续使用传统的DEFAULT CURRENT_TIMESTAMP(无括号),也可以使用新式的DEFAULT (NOW());而DATE字段只能通过DEFAULT (CURRENT_DATE)实现自动默认值;括号是新语法的标志,缺失则被视为普通标识符或非法函数调用。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
在线格式化和美化您的 SQL 查询(它支持各种 SQL 方言)。 在线工具,SQL 美化和格式化在线工具,online
解析 INSERT 等受限 SQL,导出为 CSV、JSON、XML、YAML、HTML 表格(见页内语法说明)。 在线工具,SQL转CSV/JSON/XML在线工具,online
CSV 与 JSON/XML/HTML/TSV/SQL 等互转,单页多 Tab。 在线工具,CSV 工具包在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online