now()和current_timestamp在mysql等主流数据库中本质相同,均返回事务开始时的时间戳;推荐建表用current_timestamp(无括号)作默认值,查询时用now(3)或current_timestamp(3)显式指定精度。

SQL里用 NOW() 还是 CURRENT_TIMESTAMP?本质没区别
在绝大多数主流数据库(MySQL、PostgreSQL、MariaDB)中,NOW() 和 CURRENT_TIMESTAMP 是同义词,都返回当前事务开始时的时间戳(注意:不是执行语句的瞬间),类型通常是 DATETIME 或 TIMESTAMP。MySQL 甚至允许省略括号写成 CURRENT_TIMESTAMP,但加括号更统一、可读性更好。
常见误区是以为它们“实时刷新”,其实只要在同一个事务里多次调用,结果完全一致。比如:
START TRANSACTION; SELECT NOW(), SLEEP(2), NOW(); -- 两个 <code>NOW()</code> 返回相同时间 COMMIT;
MySQL 中带秒精度的写法要注意括号和参数
如果需要毫秒级精度(如 2024-05-20 14:23:18.123),MySQL 要求显式指定精度参数,且必须带括号:
-
NOW(3)✅ 正确:返回带 3 位小数的秒 -
CURRENT_TIMESTAMP(6)✅ 正确:支持最多 6 位微秒精度 -
NOW(无括号)❌ 在严格模式下可能报错,尤其在 DDL 语句中作为默认值时 -
CURRENT_TIMESTAMP(无括号)✅ 允许,但仅限于列默认值场景(如CREATE TABLE t (ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP))
实际建表时推荐统一用 CURRENT_TIMESTAMP(无括号)作默认值,写查询时一律用 NOW(3) 或 CURRENT_TIMESTAMP(3) 显式控制精度。
跨数据库兼容性差,别指望一个写法走天下
PostgreSQL 支持 NOW() 和 CURRENT_TIMESTAMP,行为一致;SQL Server 完全不认这两个,得用 GETDATE() 或 SYSDATETIME();SQLite 只支持 datetime('now')。所以如果你的 SQL 要跑在多个数据库上:
- 应用层生成时间戳(如 Python 的
datetime.now())再传入,最可控 - 避免在视图或函数里硬编码时间函数,改用参数化
- 测试阶段务必在目标数据库上验证,尤其是默认值和触发器里的调用
例如 MySQL 建表语句里写 created_at TIMESTAMP DEFAULT NOW(),迁到 SQL Server 就会直接失败。
INSERT 时自动填充时间戳,优先用 DEFAULT 而非函数调用
想让某列(如 created_at)在 INSERT 时不填就自动设为当前时间,应该依赖 DDL 的 DEFAULT 子句,而不是在 INSERT 语句里手动写 NOW():
CREATE TABLE log ( id INT PRIMARY KEY, msg TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP );
这样做的好处:
- 应用代码不用关心时间生成逻辑,减少出错点
- 数据库统一管理时区(注意:
TIMESTAMP存的是 UTC,DATETIME存的是本地时间) - 避免 ORM 拼 SQL 时漏掉时间字段导致
NULL插入
唯一要注意的是:MySQL 5.6.5+ 才支持 TIMESTAMP 和 DATETIME 列同时用 CURRENT_TIMESTAMP 作默认值,老版本只能有一个。
真正容易被忽略的其实是时区——NOW() 返回的时间取决于 MySQL 服务端的 time_zone 设置,而客户端连接的时区设置(SET time_zone = '+08:00')只影响显示格式,不影响存储值。查数据前先确认 SELECT @@time_zone, @@system_time_zone;。










