哪一个:

日期时间日期时间2

在SQL Server 2008+中存储日期和时间的建议方法是什么?

我知道精度(可能还有存储空间)的差异,但现在忽略这些,是否有关于何时使用what的最佳实践文档,或者我们应该只使用datetime2?


当前回答

Select ValidUntil + 1
from Documents

上面的SQL不适用于DateTime2字段。它返回错误“操作数类型冲突:datetime2与int不兼容”

添加1以获得第二天,这是开发人员多年来一直在使用日期的做法。现在微软有了一个超级新的datetime2字段,无法处理这个简单的功能。

“让我们使用比旧型号更糟糕的新型号”,我不这么认为!

其他回答

我刚刚偶然发现了DATETIME2的另一个优点:它避免了Python adodbapi模块中的一个错误,如果传递标准库datetime值,该值对于datetime列具有非零微秒,但如果将该列定义为DATETIME2,则会很好。

正如其他答案所示,由于尺寸更小、精度更高,建议使用datetime2,但以下是Nikola Ilic关于为什么不使用datetime1的一些想法:

缺少(简单)对日期进行基本数学运算的可能性,如GETDATE()+1每次使用DATEADD或DATEDIFF进行比较时,都会完成到datetime的隐式数据转换SQL Server无法正确使用Datetime2列的统计信息,因为存储数据的方式会导致非最佳查询计划,从而降低性能

我同意@marc_s和@Adam_Poward的观点——DateTime2是前进的首选方法。它的日期范围更广,精度更高,使用的存储量相等或更少(取决于精度)。

然而,讨论中遗漏了一件事。。。@Marc_s状态:这两种类型都映射到.NET中的System.DateTime-没有区别。这是正确的,然而,相反的是不正确的。。。在进行日期范围搜索时很重要(例如“查找2010年5月5日修改的所有记录”)。

.NET版本的Datetime具有与DateTime2相似的范围和精度。将.net Datetime向下映射到旧的SQL Datetime时,会发生隐式舍入。旧的SQL DateTime精确到3毫秒。这意味着11:59:59.997将尽可能接近一天的结束。任何更高的值都将舍入到第二天。

试试看:

declare @d1 datetime   = '5/5/2010 23:59:59.999'
declare @d2 datetime2  = '5/5/2010 23:59:59.999'
declare @d3 datetime   = '5/5/2010 23:59:59.997'
select @d1 as 'IAmMay6BecauseOfRounding', @d2 'May5', @d3 'StillMay5Because2msEarlier'

避免这种隐式舍入是转移到DateTime2的一个重要原因。日期的隐式舍入显然会引起混淆:

SQL Server中奇怪的日期时间行为http://bytes.com/topic/sql-server/answers/578416-weird-millisecond-part-datetime-data-sql-server-2000-aSQL Server 2008和毫秒http://improve.dk/archive/2011/06/16/getting-bit-by-datetime-rounding-or-why-235959-999-ltgt.aspxhttp://milesquaretech.com/Blog/post/2011/09/12/DateTime-vs-DateTime2-SQL-is-Rounding-My-999-Milliseconds!.aspx公司

如果您是Access开发人员,试图将Now()写入相关字段,则DateTime2会造成严重破坏。刚刚执行了Access->SQL 2008 R2迁移,它将所有日期时间字段作为DateTime2放入。当值爆炸时,用Now()追加一条记录。2012年1月1日下午2:53:04没事,但2012年10月1日凌晨2:53:44没有。

一旦性格改变了。希望它能帮助到某人。

老问题。。。但我想补充一些这里没有人说过的话。。。(注:这是我自己的观察结果,所以不要要求任何参考)

在筛选条件中使用Datetime2更快。

TLDR:

在SQL 2016中,我有一个包含十万行和日期时间列ENTRY_TIME的表,因为它需要存储精确到秒的时间。当我使用where子句作为:

WHERE ENTRY_TIME >= '2017-01-01 00:00:00' AND ENTRY_TIME < '2018-01-01 00:00:00'

最初,当有数百行时,查询很好,但当行数增加时,查询开始出现以下错误:

Execution Timeout Expired. The timeout period elapsed prior
to completion of the operation or the server is not responding.

我删除了where子句,出乎意料的是,查询在1秒内运行,尽管现在所有日期的所有行都已提取。我用where子句运行内部查询,用了85秒,没有where子句用了0.01秒。

我在这里遇到了许多关于日期时间过滤性能的线程

我优化了一下查询。但我得到的真正速度是将datetime列更改为datetime2。

现在,以前超时的同一个查询只需要不到一秒钟的时间。

干杯