Answers:
有关datetime的MSDN文档建议使用datetime2。这是他们的建议:
使用
time
,date
,datetime2
和datetimeoffset
数据类型的新工作。这些类型符合SQL标准。它们更便携。time
,datetime2
并datetimeoffset
提供更高的秒精度。datetimeoffset
为全球部署的应用程序提供时区支持。
datetime2具有较大的日期范围,较大的默认小数精度和可选的用户指定精度。另外,根据用户指定的精度,它可能会使用较少的存储空间。
DateTime2
类型的特定位级别表示(或其他任何SQL Server)?键入这个问题),请参阅缺点在我下面的17年7月10日回答我为什么问这个?
DATETIME2
日期范围为“ DATETIME
0001/01/01 ”到“ 9999/12/31 ”,而该类型仅支持1753-9999年。
另外,如果需要,DATETIME2
可以在时间上更精确;DATETIME限制为3 1/3毫秒,而DATETIME2
精确到100ns。
两种类型都映射到System.DateTime
.NET中-在那里没有区别。
如果您有选择,我建议您DATETIME2
尽可能使用。我看不到使用有什么好处DATETIME
(除了向后兼容性以外),您的麻烦会更少(日期超出范围并且像这样麻烦)。
另外:如果您只需要日期(没有时间部分),请使用DATE-它既好DATETIME2
又节省空间!:-)相同的只是时间-使用TIME
。这就是这些类型的用途!
Nullable<DateTime>
吗?
datetime2在大多数方面都胜出,但(旧应用程序兼容性)除外
请注意以下几点
图像来源: MCTS自定进度培训套件(考试70-432):Microsoft®SQLServer®2008-实施和维护 第3章:表->第1课:创建表->第66页
datetime2
datetime2
比使用更少的存储空间datetime
却又提供更大的范围和更高的精度?
我同意@marc_s和@Adam_Poward-DateTime2是前进的首选方法。它具有更宽的日期范围,更高的精度,并使用相等或更少的存储量(取决于精度)。
但是,讨论错过了一件事……
@Marc_s指出:Both types map to System.DateTime in .NET - no difference there
。这是正确的,但是,相反的说法不正确 ……它在进行日期范围搜索时很重要(例如“查找我在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的重要原因。日期的隐式舍入显然会引起混乱:
20100505
到5/5/2010
?前一种格式适用于SQL Server中的任何区域。后者将中断:SET LANGUAGE French; SELECT Convert(datetime, '1/7/2015')
糟糕:2015-07-01 00:00:00.000
几乎所有的答案和评论都对赞成者表示沉重而对缺点表示反对。这是迄今为止所有优点和缺点的概述,以及一些关键的缺点(在下面的第2条中),我只看到过一次或根本没有提到过。
1.1。更加符合ISO标准(ISO 8601)(尽管我不知道这在实践中如何发挥作用)。
1.2。更大的范围(1/1/0001到12/31/9999与1/1 / 1753-12 / 31/9999)(尽管超出范围,除了ex。,在历史,天文,地质等应用中)。
1.3。完全匹配.NET的DateTime
Type范围(尽管如果值在目标类型的范围和精度之内(除非下面的Con#2.1除外),则两者都可以进行无特殊编码的来回转换,否则会发生错误/舍入)。
1.4。更高的精度(100纳秒,也就是0.000,000,1秒与3.33毫秒,也就是0.003,33秒。)(尽管除了工程,科学应用程序外,可能不会使用额外的精度)。
1.5。当配置为类似时(如Iman Abidi所称,在1毫秒中而不是“相同”(在3.33毫秒中)),精度为DateTime
,使用的空间更少(7个字节对8个字节),但是,当然,您会失去精确度收益,尽管这可能是不必要的收益,但它可能是最受吹捧的两者之一(另一个是范围)。
2.1。在将参数传递到.NET时SqlCommand
,必须指定System.Data.SqlDbType.DateTime2
是否要传递SQL Server DateTime
范围和/或精度之外的值,因为它的默认值为System.Data.SqlDbType.DateTime
。
2.2。无法隐式/轻松地将其转换为浮点数字(自最小日期时间起的天数)值,以在SQL Server表达式中使用数字值和运算符对其执行以下操作:
2.2.1。添加或减去天数或部分天数。注意:DateAdd
如果您需要考虑日期时间的多个(如果不是全部)部分,那么使用Function作为解决方法并非易事。
2.2.2。为了计算“年龄”,请取两个日期时间之间的差。注意:您不能简单地使用SQL Server的DateDiff
Function来代替,因为它不能age
像大多数人期望的那样进行计算,如果两个日期时间恰好越过了指定单位的日历/时钟日期时间边界,即使很小的一部分该单位的时间,则返回的差值为该单位的1与0。例如,两个日期时间的DateDiff
in Day
仅相差1毫秒,如果这些日期时间为,则返回1与0(天)。在不同的日历日(即“ 1999-12-31 23:59:59.9999999”和“ 2000-01-01 00:00:00.0000000”)。如果移动了相同的1毫秒时差日期时间,以使它们不跨越日历日,则将返回以Day
0的天数表示的“ DateDiff” 。
2.2.3。Avg
首先简单地转换为“浮点数”,然后再转换为,即可获取日期时间(在汇总查询中)DateTime
。
注意:要转换DateTime2
为数字,您必须执行类似以下公式的操作,该公式仍假定您的值不小于1970年(这意味着您将丢失所有额外范围以及另外217年。)注意:无法简单地调整公式以允许更大的范围,因为您可能会遇到数值溢出问题。
25567 + (DATEDIFF(SECOND, {d '1970-01-01'}, @Time) + DATEPART(nanosecond, @Time) / 1.0E + 9) / 86400.0
–来源:“ https://siderite.dev/blog/how-to-translate-t-sql-datetime2-to.html “
当然,您也Cast
可以DateTime
先(如果有必要,再返回DateTime2
),但是您会失去DateTime2
vs. 的精度和范围(都在1753年之前)带来的好处,DateTime
这是最大的2个,同时也是这是最不可能需要的2个问题,当您失去对加法/减法/“年龄”(vs。DateDiff
)/ Avg
计算收益的隐式/简单转换为浮点数字(天数)时的收益时,为什么要使用它是一个很大的问题在我的经验中。
顺便说一句,Avg
日期时间是(或至少应该是)一个重要的用例。a)除了用于获取使用日期时间(因为有一个通用的基准日期时间)来表示持续时间(平均惯例)时的平均持续时间外,b)获取平均日期的仪表板类型统计信息也很有用,时间位于行/行组的日期时间列中。c)一个标准(或至少应该是标准)临时查询,以监视/排除可能不再有效/不再有效和/或可能不建议使用的列中的值,该值是为每个值列出出现次数和(如果可用)的Min
,Avg
并Max
与该值相关联的日期的时间标记。
DateTime
,它们都与对SQL Server查询和语句的影响有关。
DateTime2
我已经提到的(由于溢出的可能性很高))。回覆。“不适用于大多数日期类型”:您只需要将它与一个日期类型一起使用,并且大多数应用程序中的大多数日期在整个生命周期中都可能永远不需要转换为另一种日期类型(也许,除了我也提到过) ,DateTime2
到DateTime
(如做“的日期算术”; P)鉴于这种情况,这是不值得所有的额外不仅编程,而且还特设研究查询使用非算术友好日期类型的编码。
这是一个示例,它将向您显示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个字节。
旧问题...但是我想添加一些此处尚未有人说过的内容...(注意:这是我自己的观察,所以请不要提供任何参考)
在过滤条件中使用Datetime2更快。
TLDR:
在SQL 2016中,我有一个包含十万行的表和一个datetime列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。
现在,以前超时的同一查询只需不到一秒钟的时间。
干杯
使用非美国设置时,日期字符串对datetime
和的解释datetime2
也可以不同DATEFORMAT
。例如
set dateformat dmy
declare @d datetime, @d2 datetime2
select @d = '2013-06-05', @d2 = '2013-06-05'
select @d, @d2
会传回2013-05-06
(即5月6日)datetime
和的2013-06-05
(即6月5日)datetime2
。但是,将dateformat
设置为mdy
,则将@d
和都@d2
返回2013-06-05
。
该datetime
行为似乎与MSDN文档的SET DATEFORMAT
状态不一致:某些字符串格式(例如ISO 8601)独立于DATEFORMAT设置进行解释。显然不是真的!
直到我对此感到吃惊,我一直认为yyyy-mm-dd
,不管语言/区域设置如何,日期都将被正确处理。
SET LANGUAGE FRENCH; DECLARE @d DATETIME = '20130605'; SELECT @d;
再用破折号再试一次。
Select ValidUntil + 1
from Documents
上面的SQL不适用于DateTime2字段。它返回错误“操作数类型冲突:datetime2与int不兼容”
加1以获得第二天是开发人员多年来一直在处理日期的事情。现在,Microsoft有一个超级新的datetime2字段,无法处理此简单功能。
“让我们使用比旧类型更糟糕的新型”,我不这么认为!
datetime
和datetime2
SQL Server 2008中都引入了和数据类型。您还可以Operand type clash: date is incompatible with int
从点号之后的date
类型中获得数据。这三种数据类型都可以正常工作dateadd(dd, 1, ...)
。