我有一个比较两个日期的存储过程。从我的应用程序的逻辑,我期望它们是平等的。但是,比较失败了。这样做的原因是,其中一个值存储为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的差异?我认为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)
答案 0 :(得分:12)
SQL Server 2016中引入了breaking change,涉及datetime和datetime2的转换和比较。 this knowledge base article详细说明了这些更改。
总之,在SQL 2014及早期版本的转换过程中舍入了值,而现在考虑了全精度。这样可以提高性能,但在转换和比较这些不同类型时会引入问题。
答案 1 :(得分:4)
datetime2
是datetime2(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。因此,即使将DATETIME
与DATETIME2(3)
进行比较,这似乎具有相同的精度,DATETIME2(3)
也更加精确。
DATETIME
这个奇怪的3.33毫秒的精确度是为什么比较看似相同的值,你可以得到差异。
答案 3 :(得分:1)