为什么从DATETIME到DATETIME2的转换似乎会更改值?

时间:2018-01-18 17:25:50

标签: sql sql-server tsql datetime

我有一个比较两个日期的存储过程。从我的应用程序的逻辑,我期望它们是平等的。但是,比较失败了。这样做的原因是,其中一个值存储为DATETIME,并且必须CONVERT - 编辑为DATETIME2,然后才与其他DATETIME2进行比较。显然,这改变了它的价值。我做了这个小测试:

DECLARE @DateTime DATETIME='2018-01-18 16:12:25.113'
DECLARE @DateTime2 DATETIME2='2018-01-18 16:12:25.1130000'
SELECT @DateTime, @DateTime2, DATEDIFF(NANOSECOND, @DateTime, @DateTime2)

这给了我以下结果: -333333ns difference

为什么这些值之间存在333333ns的差异?我认为DATETIME2作为一种更精确的类型,应该能够准确地表示可以存储在DATETIME中的所有值? The documentation of DATETIME2只说:

  

转换来自datetime时,会复制日期和时间。分数精度扩展到7位数。

没有关于转换在值中添加或减去333333ns的警告!那么为什么会这样呢?

我正在使用SQL Server 2016.

编辑:奇怪的是,在另一台服务器上,我得到零差异。两者都是SQL Server 2016,但是我遇到问题的那个兼容级别设置为130,我没有将它设置为120.在它们之间切换会改变这种行为。

edit2 :DavidG在评论中建议我使用的值可以表示为DATETIME2,但不能表示为DATETIME。所以我修改了我的测试,以确保我分配给@DateTime2的值是有效的DATETIME值:

DECLARE @DateTime DATETIME='2018-01-18 16:12:25.113'
DECLARE @DateTime2 DATETIME2=CONVERT(DATETIME2, @DateTime)
SELECT @DateTime, @DateTime2, DATEDIFF(NANOSECOND, @DateTime, @DateTime2)

这有点帮助,因为差异较小但仍不为零: -33ns difference

4 个答案:

答案 0 :(得分:12)

SQL Server 2016中引入了breaking change,涉及datetime和datetime2的转换和比较。 this knowledge base article详细说明了这些更改。

总之,在SQL 2014及早期版本的转换过程中舍入了值,而现在考虑了全精度。这样可以提高性能,但在转换和比较这些不同类型时会引入问题。

答案 1 :(得分:4)

datetime2datetime2(7)的简写,表示您需要7位小数秒(最大值)。如果您想要更接近datetime2(3)的内容,请尝试datetime

另请注意,datetime2(3)datetime更准确。后者按设计舍入到最接近的0.000,0.003或0.007。

答案 2 :(得分:3)

基于this MSDN blog post DATETIME精确度为.00333秒,而DATETIME2(或DATETIME2(7)明确表示)精确度为100 ns。因此,即使将DATETIMEDATETIME2(3)进行比较,这似乎具有相同的精度,DATETIME2(3)也更加精确。

DATETIME这个奇怪的3.33毫秒的精确度是为什么比较看似相同的值,你可以得到差异。

答案 3 :(得分:1)

对我来说,当你进行比较时,你实际上应该将高精度数据转换为低精度以避免这种“差异”

DECLARE @DateTime DATETIME='2018-01-18 16:12:25.113'
DECLARE @DateTime2 DATETIME2='2018-01-18 16:12:25.1130000'
SELECT @DateTime, cast(@DateTime2 as datetime), DATEDIFF(NANOSECOND, @DateTime, cast(@DateTime2 as datetime))

结果是

enter image description here