小编典典

以毫秒为单位的日期时间字段查询在SQL Server中给出错误的结果

sql

我在SQL Server
2005中使用datetime字段遇到了一个奇怪的错误。datetime字段以毫秒级的精度显示,但看起来并不总是使用毫秒。这是我的测试查询:

SELECT col1, YEAR(col1) AS yr, MONTH(col1) AS mn, DAY(col1) AS dy
FROM mytable
WHERE col1 >= '2009-12-31 00:00:00.0' AND col1 <= '2009-12-31 23:59:59.999'
ORDER BY col1

在我的结果中,我得到:

col1 | yr | mn | dy
---------------------------- + ------ + ---- + ----
 2009-12-31 00:00:00:00.000 | 2009 | 12 | 31
 2010-01-01 00:00:00:00.000 | 2010 | 1 | 1个

问题是我的日期是2010年1月1日,即使该日期不能小于或等于“ 2009-12-31 23:59:59.999”。但是,如果我将查询更改为使用“
2009-12-31 23:59:59.99 8 ”,则它可以正常运行(不返回2010日期时间)。

这是Bug,还是SQL
Server的工作方式?如果这是它的工作方式,那么有什么理由吗?我遇到了从MySQL迁移一些查询的问题,该查询可以按预期运行(即使MySQL甚至不存储毫秒!)。


阅读 203

收藏
2021-03-10

共1个答案

小编典典

SQL Server将时间部分存储为1/300从午夜起的第二个长滴答声的数量。

23:59:59.999将四舍五入到00:00:00.000第二天的最接近刻度。

SELECT  CAST(CAST('2009-12-01 00:00:00.000' AS DATETIME) AS BINARY(8)),
        CAST(CAST('2009-12-01 23:59:59.997' AS DATETIME) AS BINARY(8)),
        CAST(CAST('2009-12-01 23:59:59.999' AS DATETIME) AS BINARY(8))



0x00009B8F 00000000    0x00009B8F 018B81FF    0x00009B90 00000000

在第一个值中,日期部分0x9B8F39823)是自以来的天数,Jan 1st, 1900时间部分0是自午夜以来的滴答数。

在第二个值中,0x018B81FF2591999924 * 60 * 60 * 300 - 1)是自午夜以来的最大滴答数。

最后,第三个值0在时间部分和日期部分增加了一个。

2021-03-10