应优先用 current_timestamp 衍生日期和时间,因其原子性可确保二者严格同步;current_date 和 current_time 独立调用,可能来自不同系统时钟快照,存在跨秒偏差风险。

用 CURRENT_DATE 和 CURRENT_TIME 获取独立的日期与时间值
PostgreSQL、MySQL 8.0+、SQL Server(部分模式)和 SQLite 都支持这两个函数,但行为有差异。它们不是“从当前时间戳里拆出日期/时间”,而是各自独立获取系统当前日期或时间——这意味着在高并发或跨毫秒级操作中,CURRENT_DATE 和 CURRENT_TIME 可能来自不同系统时钟快照,不保证严格同步。
-
CURRENT_DATE返回DATE类型(如'2024-06-12'),不含时区信息(除非数据库配置为带时区的DATE,但极少如此) -
CURRENT_TIME返回TIME WITH TIME ZONE(PostgreSQL)或TIME(MySQL),精度取决于数据库,默认可能只到秒,需显式指定如CURRENT_TIME(3)获取毫秒 - 不要试图用
CURRENT_DATE + CURRENT_TIME拼回完整时间戳——类型不兼容,且语义上不是原子操作
为什么不能用 NOW() 或 CURRENT_TIMESTAMP 然后截取?
虽然 CURRENT_TIMESTAMP 是原子获取的完整时间戳,但用它再做 CAST(CURRENT_TIMESTAMP AS DATE) 或 CAST(CURRENT_TIMESTAMP AS TIME) 在多数场景下更安全。问题在于:某些旧版 MySQL(如 5.7)中 CURRENT_DATE 和 CURRENT_TIME 实际是基于同一内部调用,而 PostgreSQL 明确文档指出二者“可能不一致”。所以如果你需要逻辑上严格配对的日期+时间(比如记录某事件发生的“当天”和“当时”),优先用 CURRENT_TIMESTAMP 衍生:
SELECT CURRENT_TIMESTAMP AS ts, CAST(CURRENT_TIMESTAMP AS DATE) AS d, CAST(CURRENT_TIMESTAMP AS TIME) AS t;
这样 d 和 t 来自同一个时间点,避免跨秒偏差。
CURRENT_TIME 的时区陷阱
PostgreSQL 中 CURRENT_TIME 默认返回带时区的 TIME WITH TIME ZONE,例如 '14:23:05.123+08';而 MySQL 的 CURRENT_TIME 返回本地时区的 TIME,无时区标识。如果应用依赖时区一致性:
- PostgreSQL:用
CURRENT_TIME AT TIME ZONE 'UTC'强制转换,或改用CLOCK_TIMESTAMP()配合TIME OF DAY - MySQL:确认
time_zone系统变量设置(SELECT @@time_zone),避免会话级临时修改导致CURRENT_TIME偏移 - SQLite:没有原生时区支持,
datetime('now')是唯一可靠方式,time('now')仅返回本地时间字符串,不可用于跨时区比较
INSERT 场景下如何安全写入分离字段
假设表结构为 events(date_col DATE, time_col TIME),最简写法是:
INSERT INTO events (date_col, time_col) VALUES (CURRENT_DATE, CURRENT_TIME);
但要注意:
- 若业务要求“同一次事务内日期和时间必须反映同一时刻”,请改用
INSERT ... SELECT CAST(ts AS DATE), CAST(ts AS TIME) FROM (SELECT CURRENT_TIMESTAMP AS ts) _ - MySQL 中
CURRENT_TIME在严格模式下可能被拒绝插入到TIME字段(如果含微秒而字段精度不足),需提前定义字段为TIME(3) - PostgreSQL 中
CURRENT_TIME插入到TIME WITHOUT TIME ZONE字段会隐式丢弃时区,但不会报错——容易掩盖时区误配问题
真正麻烦的是跨数据库迁移:SQLite 没有 CURRENT_TIME 函数,只能用 time('now'),而该函数返回字符串,不能直接插入 TIME 类型字段(需配合 strftime 解析)。这种细节往往在线上环境才暴露。










