SQL Server中GETDATE()与存储值比较结果异常问题
为什么你的CASE表达式偶尔会返回0?
这问题的根源在于两个关键点:GETDATE()的精度限制,以及SQL Server对这个函数的多次求值。
让我拆解一下:
GETDATE()返回的是datetime类型,它的精度只有3.33毫秒(也就是1/300秒)。这意味着它只能返回类似12:00:00.000、12:00:00.003、12:00:00.007这样的毫秒值——中间的数值会被截断到最近的有效刻度。- 你把这个低精度的
datetime值赋值给了datetime2类型的变量@x,datetime2的精度能到100纳秒,但它只能保留GETDATE()给它的那点精度(也就是那些.000/.003/.007的刻度)。 - 最关键的是:你的查询里调用了两次
GETDATE()——一次是给@x赋值,一次是在CASE的判断条件里。虽然时间通常是单向前进的,但有两种情况会导致第二次调用的结果比第一次的@x小:- 系统时钟回拨:比如你的服务器开启了NTP时间同步,当服务器时钟被调整回退几毫秒时,第二次
GETDATE()就会返回一个更早的时间。 - 精度截断的巧合:假设第一次调用
GETDATE()时,系统实际时间是12:00:00.003(刚好踩在datetime的刻度上),返回.003并赋值给@x。紧接着,系统时间因为某种微小波动回退到12:00:00.002,这时候第二次GETDATE()会返回.000(因为.002属于.000的截断区间),这就导致@x > GETDATE(),CASE返回0。
- 系统时钟回拨:比如你的服务器开启了NTP时间同步,当服务器时钟被调整回退几毫秒时,第二次
怎么解决这个问题?
最简单的办法就是只调用一次GETDATE(),把结果存下来之后重复使用,避免多次求值的差异:
DECLARE @x datetime2 SET @x = GETDATE() SELECT CASE WHEN @x > @x THEN 0 ELSE 1 END -- 永远返回1,复用同一个变量的值
或者,如果你想使用更高精度的时间函数,可以换成SYSDATETIME()(返回datetime2类型,精度到100纳秒),它能减少因为精度截断导致的问题,但还是无法完全避免系统时钟回拨的情况——所以最稳妥的还是只调用一次时间函数,复用结果。
内容的提问来源于stack exchange,提问作者csname1910
相关产品推荐
相关产品推荐

