SQL Server获取当前日期最稳妥的函数是GETDATE(),返回datetime类型(精确到3.33毫秒),不支持NOW(),CURRENT_DATE行为不一致;慎用CAST截断以防索引失效,推荐范围查询;GETDATE()在语句执行前求值一次,非逐行调用;日期计算应优先使用DATEADD()避免隐式转换陷阱。

SQL Server里获取当前日期的函数是 GETDATE(),不是 NOW() 或 CURRENT_DATE
SQL Server 不支持 MySQL 的 NOW() 或标准 SQL 的 CURRENT_DATE(虽然后者在部分版本中可用,但行为不一致)。最稳妥、最常用的是 GETDATE(),它返回 datetime 类型(精确到 3.33 毫秒),适用于绝大多数日期计算场景。
如果只需要日期部分(不含时间),别直接用 CAST(GETDATE() AS DATE) 就完事——虽然语法对,但要注意索引失效风险。更安全的做法是用范围查询代替截断:
WHERE OrderDate >= '2024-06-01' AND OrderDate —— 可走索引- 避免写成
WHERE CAST(OrderDate AS DATE) = CAST(GETDATE() AS DATE)—— 会阻止索引使用
需要更高精度或时区感知?用 SYSDATETIME() 和 SYSDATETIMEOFFSET()
GETDATE() 返回本地服务器时间,类型是 datetime;而 SYSDATETIME() 返回 datetime2(7),精度达 100 纳秒,且不受服务器 datetime 类型精度限制影响。若做毫秒级日志比对或高并发时间戳生成,优先选它。
跨时区系统必须考虑时区——GETDATE() 和 SYSDATETIME() 都不带时区信息。此时应改用 SYSDATETIMEOFFSET(),它返回带本地偏移的 datetimeoffset 值,可直接与 UTC 时间转换:
-
SELECT SYSDATETIMEOFFSET() AT TIME ZONE 'UTC'→ 转为 UTC 时间 -
WHERE CreatedAt > DATEADD(day, -7, SYSDATETIMEOFFSET())→ 用带时区的时间做计算,避免夏令时偏差
在 WHERE 子句里直接用 GETDATE() 是安全的,但注意执行时机
GETDATE() 在语句编译后、执行前求值一次,整条查询中所有地方都用同一个时间戳。这点和某些 ORM 中“每次调用都重新取时间”的行为不同,容易误判逻辑。
例如下面这个看似查“今天订单”的语句:
SELECT * FROM Orders WHERE CAST(OrderDate AS DATE) = CAST(GETDATE() AS DATE)
实际执行时,GETDATE() 只算一次,但因为用了 CAST,导致无法利用 OrderDate 列上的索引。更糟的是,如果该语句被封装进视图或内联表值函数,且被多次引用,仍只取一次时间——这未必是你想要的“动态实时性”。
真正需要“每行独立判断”的场景(极少见),得用 GETUTCDATE() + 计算列或触发器,而不是依赖函数重复调用。
用 GETDATE() 做日期计算时,别忽略 datetime 类型的隐式转换陷阱
SQL Server 对 datetime 类型做加减运算时,单位是“天”,比如 GETDATE() + 1 是明天同一时刻;但 GETDATE() + 0.5 是 12 小时后。这种浮点数换算易出错,建议统一用 DATEADD():
- ✅
DATEADD(day, 1, GETDATE()) - ✅
DATEADD(hour, -2, GETDATE()) - ❌
GETDATE() - 0.0416666666666667(这是 1 小时,但难读难维护)
另外,datetime 最小值是 1753-01-01,如果计算结果早于该值(比如 GETDATE() - 100000),会直接报错 Msg 517, Level 16。生产环境做跨度大的日期推算,务必加 TRY_CONVERT() 或前置校验。
最常被忽略的一点:在存储过程中用 GETDATE() 作为默认参数值是不允许的——T-SQL 不支持函数作参数默认值。必须显式传入,或在过程体内赋值。

















