考虑如下 SQL 语句:
select * from itpow where dt<='2020-07-21 23:59:59.999'
我们会发现 22 日零点的数据也会被查询出来,为什么呢?
因为:datetime 的小数秒精度精确到三百分之一秒(相当于 3.33 毫秒或 0.00333 秒)。值舍入到 .000、.003 或 .007 秒三个增量。
原来 999 越界了,被收上去了,就变成 22 日了。
所以我们只能写到 998。
具体规则
上述文档中微软使用的“增量”太误导人,实际就是指最后一位往 0、3、7 上靠,其中 5 位于 3、7 中间,往 7 靠。
0.000 -> 0.000
0.001 -> 0.000
0.002 -> 0.003
0.003 -> 0.003
0.004 -> 0.003
0.005 -> 0.007
0.006 -> 0.007
0.007 -> 0.007
0.008 -> 0.007
0.009 -> 0.010
0.010 -> 0.010
0.011 -> 0.010
0.012 -> 0.013
0.013 -> 0.013
0.014 -> 0.013
0.015 -> 0.017
0.016 -> 0.017
0.017 -> 0.017
0.018 -> 0.017
0.019 -> 0.020
扩展
SQL Server 文档中说,字符串隐式转换成 datetime、datetime2 时,支持 SQL 标准格式 YYY-MM-DD hh:mi:ss.[nnnnnnn]
这里有 7 个 n,然而,datetime 在应用第 4 个 n 时就会提示:从字符串转换日期和/或时间时,转换失败。其实 datetime 精度本来就没那么高,超过 3 位即使能转换,也是没有意义的。
也就是说 SQL Server 文档那里,其实应该分开说:
datetime 3 个 n。
datetime2 7 个 n。
另外文档中提到了 ISO 8601 格式,这个格式:日期、时间之间不是用空格隔开的,而是用 T。
比如:2020-07-22T17:54:08,但是这种格式要注意补 0,比如 7 那里,如果我们不补 0,就会出错。