DateTime2与SQL Server中的DateTime

哪一个:

  • datetime
  • datetime2

是SQL Server 2008+中存储date和时间推荐方法?

我意识到精度(和存储空间大概)的差异,但是现在忽略这些差异,有什么时候使用什么的最佳实践文档,或者我们应该只使用datetime2

datetime的MSDN文档build议使用datetime2 。 这是他们的build议:

使用时间,date,datetime2和datetimeoffset数据types的新工作。 这些types与SQL标准一致。 他们更便携。 时间,datetime2和datetimeoffset提供更多的秒精度。 datetimeoffset为全局部署的应用程序提供时区支持。

datetime2具有较大的date范围,较大的默认小数精度和可选的用户指定精度。 也取决于用户指定的精度,它可能使用较less的存储空间。

DATETIME2的date范围为“0001/01/01”至“9999/12/31”,而DATETIMEtypes仅支持1753-9999年。

另外,如果您需要, DATETIME2可以在时间上更精确; DATETIME被限制为3 1/3毫秒,而DATETIME2可以精确到100ns。

这两种types映射到.NET中的System.DateTime – 没有差别。

如果您有select,我会build议尽可能使用DATETIME2 。 我没有看到使用DATETIME任何好处(除了向后兼容性) – 你会有更less的麻烦(date超出范围和麻烦就是这样)。

另外:如果你只需要date(没有时间部分),使用date – 它和DATETIME2一样好,并且节省空间! :-)只用于时间 – 使用TIME 。 这就是这些types的!

datetime2除了(老应用程序兼容性)外,

  1. 更大的价值范围
  2. 更好的准确性
  3. 较小的存储空间 (如果指定了可选的用户指定的精度)

SQL日期和时间数据类型compare  -  datetime,datetime2,date,TIME

请注意以下几点

  • 句法
    • datetime2 [(分数秒精度=>查看下面的存储大小)]
  • 精确,规模
    • 0到7位数字,准确度为100ns。
    • 默认精度是7位数。
  • 存储大小
    • 精度小于3的6个字节;
    • 精度为3和4的7个字节。
    • 所有其他精度需要8个字节
  • DateTime2(3)DateTime具有相同的位数,但使用7个字节的存储而不是8个字节( SQLHINTS-DateTime Vs DateTime2 )
  • 在datetime2上查找更多(Transact-SQL MSDN文章)

图像来源: MCTS Self-Paced Training Kit(考试70-432):Microsoft®SQLServer®2008 – 实施和维护第3章:表格 – >第1课:创build表格 – >第66页

我同意@marc_s和@Adam_Poward – DateTime2是前进的首选方法。 它具有更广泛的date,更高的精度,并使用相同或更less的存储(取决于精度)。

讨论错过了一件事,但是…
@Marc_s状态: Both types map to System.DateTime in .NET - no difference there 。 这是正确的, 但是,反过来是不正确的 ……而且在做date范围search时很重要(例如“find我在5/5/2010修改的所有logging”)。

.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的重要原因。 隐含的四舍五入date显然会造成混乱:

如果您是试图将Now()写入相关字段的Access开发人员,则DateTime2会造成严重破坏。 刚刚进行了Access – > SQL 2008 R2迁移,并将所有datetime字段放入DateTime2中。 用Now()追加一个logging作为轰炸的价值。 2012年1月1日下午2时53分04秒还好,但不是在2012年1月10日下午2时53分04秒。

一旦性格造成了差异。 希望它有助于某人。

下面是一个示例,它将显示smalldatetime,datetime,datetime2(0)和datetime2(7)之间存储大小(字节)和精度的差异:

 DECLARE @temp TABLE ( sdt smalldatetime, dt datetime, dt20 datetime2(0), dt27 datetime2(7) ) INSERT @temp SELECT getdate(),getdate(),getdate(),getdate() SELECT sdt,DATALENGTH(sdt) as sdt_bytes, dt,DATALENGTH(dt) as dt_bytes, dt20,DATALENGTH(dt20) as dt20_bytes, dt27, DATALENGTH(dt27) as dt27_bytes FROM @temp 

哪个返回

 sdt sdt_bytes dt dt_bytes dt20 dt20_bytes dt27 dt27_bytes 2015-09-11 11:26:00 4 2015-09-11 11:25:42.417 8 2015-09-11 11:25:42 6 2015-09-11 11:25:42.4170000 8 

所以,如果我想存储信息到秒 – 但不是毫秒 – 如果我使用datetime2(0)而不是datetime或datetime2(7),我可以节省2个字节。

在使用非美国DATEFORMAT设置时,将datestring解释为datetimedatetime2可能也不同。 例如

 set dateformat dmy declare @d datetime, @d2 datetime2 select @d = '2013-06-05', @d2 = '2013-06-05' select @d, @d2 

datetime返回2013-05-06 (即5月6日), datetime返回2013-06-05 (即6月5日)。 但是,如果将dateformat设置为mdy@d@d2返回2013-06-05

datetime行为似乎与SET DATEFORMAT的MSDN文档不一致,该文档指出: 某些string格式(例如ISO 8601)独立于DATEFORMAT设置进行解释 。 显然不是真的!

在这之前,我一直认为yyyy-mm-dddate是正确的,不pipe语言/语言环境设置如何。

虽然datetime2的 精度有所提高,但某些客户端不支持date时间datetime2,并强制您将其转换为string文字。 具体来说,Microsoft提到了这些数据types的“低级别”ODBC,OLE DB,JDBC和SqlClient问题,并有一个图表显示了每种types如何映射types。

如果数值兼容性超过精度,则使用datetime

根据这篇文章 ,如果你想使用DateTime2具有相同的DateTime精度,你只需要使用DateTime2(3)。 这应该给你相同的精度,占用less一个字节,并提供一个扩大的范围。

几乎所有的答案和评论都是对“利弊”的重视。 以下是所有优点和缺点,以及一些重要的缺点(在下面的#2中)。我只看到过提到过一次,或者根本没有。

  1. 优点:

1.1。 更符合ISO标准(ISO 8601)(虽然我不知道这是如何发挥作用)。

1.2。 更多的范围(1/1/0001至12/31/9999与1/1 / 1753-12 / 31/9999)(虽然额外的范围,所有之前的1753年,可能不会使用除了例外,在历史,天文,地质等应用程序)。

1.3。 完全匹配.NET的DateTimetypes范围的范围(尽pipe如果值在目标types的范围和精度范围内,除了Con#2.1以外,否则错误/舍入将发生,都不需要特殊编码来回转换)。

1.4。 更精确(100纳秒,又称0.000,000,1秒,3.33毫秒又称0.003,33秒)(尽pipe除了例如工程/科学应用程序,额外的精度可能不会被使用)。

1.5。 当被configuration为类似的 (比如Iman Abidi声称的1毫秒不是“相同”(如3.33毫秒))精度为DateTime ,使用较less的空间(7对8字节),但当然,你会失去尽pipe可能是不必要的好处,但可能是两者之一的精确收益(另一个是范围)。

  1. 缺点:

2.1。 将parameter passing给.NET SqlCommand ,如果您可能正在传递SQL Server DateTime的范围和/或精度以外的值,则必须指定System.Data.SqlDbType.DateTime2 ,因为它缺省为System.Data.SqlDbType.DateTime

2.2。 无法隐式/轻松地转换为浮点数字(自min-date-time以来的天数)值,以使用数值和运算符在SQL Serverexpression式中对其执行以下操作:

2.2.1。 增加或减less天数或部分天数。 注意:当需要考虑多个(如果不是所有date时间的)部分时,使用DateAdd函数作为解决方法并不是微不足道的。

2.2.2。 为了“年龄”计算的目的,取两个date时间之间的差异。 注意:您不能简单地使用SQL Server的DateDiff函数,因为它不会像大多数人所期望的那样计算age ,因为如果两个date时间跨越指定单位的日历/时钟date – 时间边界,即使对于例如,如果这两个date时间间隔仅为1毫秒,那么DateDiff将返回1与0(天)之间的差异date时间在不同日历日(即“1999-12-31 23:59:59.9999999”和“2000-01-01 00:00:00.0000000”)。 如果移动相同的1毫秒差异date时间,以便它们不跨越日历date,则将在0(天)的天内返回“DateDiff”。

2.2.3。 通过简单地转换为“浮动”,然后再返回到date时间采取Avgdate时间(在一个聚合查询)。

注意:要将DateTime2转换成数字,你必须做一些类似于下面的公式,它仍然假设你的值不低于1970年(这意味着你失去了所有额外的范围加上另外的217年。可能无法简单地调整公式以允许额外的范围,因为您可能会遇到数字溢出问题。

25567 + (DATEDIFF(SECOND, {d '1970-01-01'}, @Time) + DATEPART(nanosecond, @Time) / 1.0E + 9) / 86400.0 – 来源:“ https://siderite.blogspot.com /2015/08/how-to-translate-t-sql-datetime2-to.html “

当然,你也可以先Cast DateTime (如果有必要再回到DateTime2 ),但是你会失去DateTime2的精度和范围(全部在1753年之前),而DateTime2对于DateTime是最大的,也是最大的同时扩大了最不可能的需要,这引发了一个问题,为什么要使用它,当你失去隐式/简单的转换为浮点数(天数)加/减/“年龄”(与DateDiff )/ Avg计算好处是我的经验中的一个很大的收益。

顺便说一下,date时间的Avg (或至less应该是)是一个重要的用例。 a)除了使用date时间(由于通用的基准date – 时间)来表示持续时间(一种常见做法)之外,还可以获得平均持续时间,b)获取有关平均date的统计信息也很有用,时间在一行/一行的date时间列中。 c)一个标准的(或至less应该是标准的)专门的查询来监视/排除列中可能无效/不再有效和/或可能需要被弃用的值是列出每个值的发生次数和(如果可用)与该值关联的MinAvgMaxdate时间戳。

 Select ValidUntil + 1 from Documents 

上面的SQL不能用于DateTime2字段。 它返回和错误“操作数types冲突:date时间2与int不兼容”

开发人员join1来获得第二天的日子已经有好几年了。 现在微软有一个超级新的datetime2字段,不能处理这个简单的function。

“我们用这个比老的还差的新型”,我不这么认为!

我只是偶然发现了DATETIME2一个优点:它避免了Python adodbapi模块中的一个bug,如果一个标准的库datetime值被传递,对DATETIME列有非零微秒,但是如果列被定义为DATETIME2

我认为DATETIME2是更好的方式来存储date,因为它比DATETIME更有效率。 在SQL Server 2008中,您可以使用DATETIME2,它存储date和时间,需要6-8个字节来存储,精度为100纳秒。 所以任何需要更高时间精度的人都需要DATETIME2。