SQL Server:DATEPART提取datetime毫秒值出现舍入异常的原因及解决
问题原因与解决方法
核心原因:SQL Server datetime 类型的精度限制
SQL Server 的 datetime 类型并非精确到1毫秒,它的时间精度是 3.33毫秒(即1/300秒)。也就是说,datetime 只能存储以下固定间隔的时间值:0、3、7、10、13...以此类推(对应0.000s、0.003s、0.007s、0.010s等)。
当你用 GETDATE() 生成默认值时,系统会将实际当前时间舍入到最近的datetime可存储精度值。比如你看到表面上的.7毫秒,实际存储的是.66667秒(约666.67毫秒)——这是最接近实际时间的datetime允许值。
为什么DATEPART()和CONVERT()表现不同?
DATEPART(ms, 列名)提取的是datetime列实际存储的近似值,所以会显示666、667这类符合3.33毫秒间隔的数值,看起来像"舍入",但其实是读取了真实存储的值。CONVERT函数在格式化datetime时,会将存储的近似值四舍五入为更易读的显示值,比如把.66667秒格式化为700毫秒(即显示为.7),但这只是显示层面的优化,并非实际存储的精确值。
解决方法
如果你需要精确到1毫秒的时间存储和读取,建议:
- 将列类型从
datetime改为**datetime2(3)**:datetime2支持最高100纳秒的精度,datetime2(3)则精确到1毫秒,完全满足需求。 - 若无法修改表结构,要读取和
CONVERT显示一致的毫秒值,可以用以下方式:
注意:此方法获取的是格式化后的显示值,并非SELECT CAST(RIGHT(CONVERT(VARCHAR(23), 你的datetime列, 121), 3) AS INT) AS 显示一致的毫秒值datetime实际存储的精确值,仅用于和CONVERT显示对齐。
测试验证(结合你的场景)
比如你的测试表脚本:
CREATE TABLE TestDateTime ( ID INT IDENTITY(1,1), CreateTime DATETIME DEFAULT GETDATE(), CreateTime2 DATETIME2(3) DEFAULT SYSDATETIME() )
插入数据后执行查询:
SELECT CreateTime, DATEPART(ms, CreateTime) AS DATEPART提取的毫秒, CONVERT(VARCHAR(23), CreateTime, 121) AS CONVERT格式化结果, CreateTime2, DATEPART(ms, CreateTime2) AS DATETIME2提取的毫秒 FROM TestDateTime
会看到CreateTime的DATEPART结果是666或667,而CONVERT显示为.700,CreateTime2则能精确存储并提取实际的毫秒值。
内容的提问来源于stack exchange,提问作者Fevzi Kartal
相关产品推荐
相关产品推荐

