哪一个:
是 推荐的在SQL Server 2008 +中存储日期和时间的方法吗?
我知道精度(和存储空间可能)存在差异,但暂时忽略这些差异,是否有关于何时使用内容的最佳实践文档,或者我们应该只使用datetime2
?< / p>
答案 0 :(得分:571)
datetime的MSDN文档建议使用datetime2。以下是他们的建议:
使用
time
,date
,datetime2
和 新的datetimeoffset
数据类型 工作。这些类型与SQL一致 标准。它们更便携。time
,datetime2
和datetimeoffset
提供更多的秒精度。datetimeoffset
提供时区 支持全球部署 应用
datetime2具有更大的日期范围,更大的默认小数精度和可选的用户指定精度。此外,根据用户指定的精度,它可能使用较少的存储空间。
答案 1 :(得分:463)
DATETIME2
的日期范围为“0001/01/01”至“9999/12/31”,而DATETIME
类型仅支持1753-9999年。
此外,如果您需要,DATETIME2
可以在时间上更精确; DATETIME限制为3 1/3毫秒,而DATETIME2
可以精确到100ns。
两种类型都映射到.NET中的System.DateTime
- 没有区别。
如果您有选择,我建议您尽可能使用DATETIME2
。我没有看到使用DATETIME
带来任何好处(向后兼容性除外) - 你会遇到更少麻烦(日期超出范围并且麻烦)。
另外:如果您只需要日期(没有时间部分),请使用DATE - 它与DATETIME2
一样好,也可以节省空间! :-)同样只是时间 - 使用TIME
。这就是这些类型的用途!
答案 2 :(得分:184)
datetime2 在大多数方面都胜出(旧应用兼容性)
请注意以下几点
图片来源: MCTS Self-Paced Training Kit (Exam 70-432): Microsoft® SQL Server® 2008 - Implementation and Maintenance 第3章:表格 - &gt;第1课:创建表 - &gt;第66页
答案 3 :(得分:103)
我同意@marc_s和@Adam_Poward - DateTime2是前进的首选方法。它具有更广泛的日期,更高的精度,并使用相同或更少的存储(取决于精度)。
讨论错过了一件事,但是......
@Marc_s声明:Both types map to System.DateTime in .NET - no difference there
。这是正确的,然而,反之则不正确 ...并且在进行日期范围搜索时很重要(例如&#34;找到我在2010年5月5日修改的所有记录&#34;) 。
.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的重要原因。隐含的日期舍入显然会引起混淆:
答案 4 :(得分:15)
如果您是一名尝试将Now()写入相关字段的Access开发人员,则DateTime2会造成严重破坏。刚做了Access - &gt; SQL 2008 R2迁移,它将所有日期时间字段都放在DateTime2中。使用Now()追加记录作为被轰炸的值。这是在2012年1月1日下午2:53:04没关系,但不是在2012年1月10日下午2:53:04。
一旦角色出现差异。希望它对某人有所帮助。
答案 5 :(得分:14)
这是一个示例,它将向您展示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个字节。
答案 6 :(得分:14)
几乎所有的答案和评论都很重要。以下是迄今为止所有优点和缺点的回顾以及一些重要的缺点(下面的#2)我只见过一次或根本没有提到过。
1.1。更符合ISO标准(ISO 8601)(虽然我不知道这在实践中如何发挥作用)。
1.2。更多范围(1/1/0001至12/31/9999对比1/1 / 1753-12 / 31/9999)(尽管额外的范围,所有在1753年之前,可能不会被使用,除了ex。,在历史,天文,地质等应用程序。)
1.3。完全匹配.NET的DateTime
类型范围(尽管如果值在目标类型的范围和精度范围内,除了下面的Con#2.1之外,两者都来回转换没有特殊编码,否则将发生错误/舍入)。 / p>
1.4。更精确(100纳秒又名0.000,000,1秒与3.33毫秒又名0.003,33秒)(尽管除了ex。之外,在工程/科学应用中可能不会使用额外的精度)。
1.5。当配置为类似(如1毫秒不是&#34;相同&#34;(如3.33毫秒),如Iman Abidi声称的那样)精度为DateTime
时,使用更少的空间(7当然,当然,你将失去精确利益,这可能是两个中的一个(另一个是范围)最受欢迎,尽管可能是不必要的好处。)
2.1。将参数传递给.NET SqlCommand
时,如果您传递的值超出SQL Server System.Data.SqlDbType.DateTime2
的范围和/或精度,则必须指定DateTime
,因为它默认为System.Data.SqlDbType.DateTime
。
2.2。无法使用数值和运算符在SQL Server表达式中隐式/轻松转换为浮点数字(自最小日期时间以来的天数)值,以便对其执行以下操作:
2.2.1。添加或减去天数或部分天数。注意:当您需要考虑日期时间的多个(如果不是全部)部分时,使用DateAdd
函数作为变通方法并非易事。
2.2.2。为了“年龄”计算,取两个日期时间之间的差异。注意:您不能简单地使用SQL Server的DateDiff
函数,因为它不会像大多数人预期的那样计算age
,如果两个日期时间恰好跨越日历/时钟日期 - 时间边界如果即使对于该单位的一小部分指定的单位,它也会将差异作为该单位的1与0相比。例如,DateDiff
中的Day
的两个日期 - 如果这些日期时间在不同的日历日(即“1999-12-31 23:59:59.9999999”和“2000-01-01 00:00:00.0000000”,则相隔仅1毫秒的时间将返回1对0(天) “)。相同的1毫秒差异日期 - 如果移动以便它们不跨越日历日,将在Day
的0(天)中返回“DateDiff”。
2.2.3。通过首先转换为“Float”然后再转回Avg
来获取DateTime
日期时间(在聚合查询中)。
注意:要将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
),但你会失去精确度和范围(所有之前) 1753年)DateTime2
与DateTime
的好处,它们是最大的两个,同时也是最不可能的2个,这就是为什么当你失去隐含/简单的转换时使用它的问题加法/减法/&#34;年龄&#34;到浮点数字(天数) (与DateDiff
)/ Avg
计算效益相比,这是我的经验中的一个重要因素。
顺便说一下,日期时间的Avg
是(或者至少应该)一个重要的用例。 a)除了用于获得平均持续时间时,日期时间(因为共同的基准日期时间)用于表示持续时间(通常的做法),b)获得关于平均日期的仪表板类型统计数据也是有用的 - time位于范围/行组的日期时间列中。 c)标准(或至少应该是标准的)ad-hoc查询来监视/排除列中可能无效/不再有效和/或可能需要弃用的值列出每个值的发生次数和(如果可用)与该值相关联的Min
,Avg
和Max
日期时间戳。
答案 7 :(得分:9)
虽然datetime2的精度增加,但有些客户端不支持 date , time 或 datetime2 并强制您转换为字符串文字。特别是Microsoft提到这些数据类型的“低级”ODBC,OLE DB,JDBC和SqlClient问题,并且chart显示了每个数据类型的映射方式。
如果值兼容性超过精度,请使用datetime
答案 8 :(得分:8)
使用非美国datetime
设置时,将日期字符串解释为datetime2
和DATEFORMAT
也可能有所不同。 E.g。
set dateformat dmy
declare @d datetime, @d2 datetime2
select @d = '2013-06-05', @d2 = '2013-06-05'
select @d, @d2
这会为2013-05-06
返回datetime
(即5月6日),为2013-06-05
返回datetime2
(即6月5日)。但是,如果dateformat
设置为mdy
,则@d
和@d2
都会返回2013-06-05
。
datetime
行为似乎与SET DATEFORMAT
的{{1}}不一致,其中指出:某些字符串格式(例如ISO 8601)的解释与DATEFORMAT设置无关< / em>的。显然不是真的!
在我被这种情况所困扰之前,我一直认为无论语言/语言环境设置如何,yyyy-mm-dd
日期都会被正确处理。
答案 9 :(得分:7)
旧问题......但我想在这里添加一些尚未说明的内容...(注意:这是我自己的观察,所以不要求任何参考)
在过滤条件中使用时,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 filtering performance
我优化了一点查询。但我得到的真正速度是将datetime列更改为datetime2。
现在,先前超时的同一查询不到一秒钟。
欢呼声
答案 10 :(得分:5)
根据this article,如果您希望使用DateTime2具有相同的DateTime精度,则只需使用DateTime2(3)。这应该给你相同的精度,占用更少的字节,并提供扩展的范围。
答案 11 :(得分:4)
我偶然发现了DATETIME2
的另一个优势:它避免了Python adodbapi
模块中的错误,如果传递的标准库datetime
值为非DATETIME
列的零微秒,但如果列定义为DATETIME2
,则可以正常工作。
答案 12 :(得分:1)
如其他答案所示,建议使用 public class SomeOtherView extends Div {
public SomeOtherView() {
HorizontalLayout hl = new HorizontalLayout();
HelloWorld2 helloComponent = new HelloWorld2();
helloComponent.setName("Vaadin");
hl.add(helloComponent);
add(hl);
}
}
,因为尺寸更小且精度更高,但这里有一些关于 why NOT to use datetime2 from Nikola Ilic 的想法:
public class SomeOtherView extends HorizontalLayout {
public SomeOtherView() {
HelloWorld2 helloComponent = new HelloWorld2();
helloComponent.setName("Vaadin");
add(helloComponent);
}
}
datetime2
或 GETDATE()+1
进行比较时,都会将隐式数据转换为 DATEADD
答案 13 :(得分:0)
我认为DATETIME2
是存储date
的更好方法,因为它的效率高于。{1}}
DATETIME
。在SQL Server 2008
中,您可以使用DATETIME2
,它会存储日期和时间,需要存储6到8 bytes
,精度为100 nanoseconds
。因此,任何需要更高时间精度的人都需要DATETIME2
。
答案 14 :(得分:0)
Select ValidUntil + 1
from Documents
上面的SQL不能使用DateTime2字段。 它返回并且错误&#34;操作数类型冲突:datetime2与int&#34;
不兼容添加1来获得第二天是开发人员多年来一直在做的事情。现在微软有一个超级新的datetime2字段,无法处理这个简单的功能。
&#34;让我们使用比旧版本更糟糕的新类型&#34;,我不这么认为!
答案 15 :(得分:0)
接受的答案很好,只要知道如果您向前端发送 DateTime2 - 它会四舍五入为正常的 DateTime 等效值。
这给我带来了一个问题,因为在我的解决方案中,我必须将重新提交时发送的内容与数据库中的内容进行比较,而我的简单比较“==”不允许四舍五入。所以必须添加。