哪一个:
是否建议在SQL Server 2008+中存储日期和时间?
我知道精度(可能还有存储空间)上的差异,但现在忽略了这些差异,是否有关于何时使用什么的最佳实践文档,或者我们应该只使用datetime2?
datetime的msdn文档建议使用datetime2。以下是他们的建议:
Use the time, date, datetime2 and
datetimeoffset data types for new
work. These types align with the SQL
Standard. They are more portable.
time, datetime2 and datetimeoffset
provide more seconds precision.
datetimeoffset provides time zone
support for globally deployed
applications.
日期时间2具有更大的日期范围、更大的默认小数精度和可选的用户指定精度。另外,根据用户指定的精度,它可能使用较少的存储空间。
- 虽然datetime2的精度有所提高,但有些客户机不支持日期、时间或datetime2,并强制您转换为字符串文字。如果您更关心的是兼容性而不是精度,请使用datetime
- 另一个选项是使用索引视图,将列转换为datetime以实现兼容性。不过,您需要能够将应用程序指向视图。
- 带有datetimeoffset的时区支持是一个误称。它只存储特定时间点的UTC偏移量,而不是时区。
- @Porad:由于"SQL标准",在实践中"更可移植"有什么好处?这不仅使您编写的代码显著增多,而且对于"端口"而言,对于另一个RDBMS来说,这些代码的可读性/可维护性明显降低,而在该代码的生命周期内,这些"端口"可能永远不会出现。除了微软提供的SQL Server工具和驱动程序(如果有的话),是否有任何应用程序实际上依赖于DATETIME2类型的特定位级表示(或其他任何SQL Server类型)?请参阅下面我7/10/17回答中的缺点,了解我为什么要问。
- @Adam Porad:而且,所有这些好处都可能是不需要的(工程或科学应用程序除外),因此不值得损失很多,更可能是需要的:更容易(甚至考虑解决方法)的能力,隐式/显式地转换为浮点数字(天,包括如果适用,从分钟起的分数天)日期时间)加、减、最小值、最大值和平均值。有关详细信息,请参阅下面我的7/10/17回答中的缺点。
- 谁想出了这些函数名?任何其他像样的编程语言都不会接受一个新版本,即在名称中添加"2"。下一步是什么,日期时间3?
DATETIME2的日期范围为"0001/01/01"到"9999/12/31",而DATETIME类型仅支持1753-9999年。
另外,如果需要,DATETIME2在时间方面更精确;日期时间限制为3 1/3毫秒,而DATETIME2可以精确到100ns。
两种类型都映射到.NET中的System.DateTime—没有区别。
如果您有选择,我建议您尽可能使用DATETIME2。我看不到使用DATETIME有什么好处(除了向后兼容性),您的麻烦会少一些(日期超出范围,这样麻烦就少了)。
另外:如果你只需要日期(不需要时间部分),那么就使用日期——它和DATETIME2一样好,也可以节省你的空间!:-)同样只适用于时间-使用TIME。这就是这些类型的产品的用途!
- 我同意马克的观点。除非出于某种原因需要向后兼容,否则始终使用datetime2。存储空间很便宜,根据我在自己的经验和在别处阅读的内容,这两者在处理开销上没有区别。
- 在将.NET日期时间值作为参数添加到sqlcommand时要小心,因为它喜欢假定它是旧的日期时间类型,并且如果尝试写入超出1753-9999年范围的日期时间值,则会出现错误,除非您为sqlcommant显式指定类型为system.data.sqldbtype.datetime2。总之,datetime2很好,因为它可以存储任何可以存储在.NET日期时间类型中的值。
- @Marc_s-不理解你在其他条件相同时选择日期时间2的观点。对于大多数应用来说,支持1-1752年的灵活性真的是一个优势吗?我从未有过比19世纪末早一年的应用程序,它似乎会鼓励像2011年错误编码为11这样的事故。
- @johnfx:我有过很多次,应用程序代表的是"未知"日期01/01/0001,这在SQL Server上总是会引起问题,除非您可以使用DATETIME2。
- @马克-这不是空的意思吗?
- @johnfx:尝试将.NET DateTime结构设置为空…..
- @Marc:到.NET类型的映射有一个区别:datetime2与.NET datetime类型是同构的,因此没有"超出范围"的错误,而且可能由于不需要转换,所以性能改进非常小。
- @johnfx—有点晚了—但您不会将datetime设置为空。您将使用nullable或datetime?哪个处理空值很好—在映射到一个过程中,只需执行param.value=somedatetime??dbvalue.null不幸的是,我们遇到了一个数据类型,数据类型后面有一个数字-看起来像是"generic":)
- 哈哈,我只是想推翻我自己的评论(上面),然后才意识到这是我自己的评论(一年前发表的)。我仍在处理.NET框架的愚蠢设计决策,即在作为sqlparameters传递时默认截断所有日期时间值,除非您显式地将其设置为更精确的sqldbtype.datetime2。自动推断出正确的类型。实际上,它们应该使更改透明化,替换不太精确、效率较低、范围有限的实现,并保留原始的"datetime"类型名。另请参阅stackoverflow.com/q/8421332/88409
- @这不是Nullable的目的吗?
- 以下是详细差异列表:sqlservercentral.com/articles/datetime/134800
- @Marc_S:我看到使用DateTime与DATETIME2相比,除了"向后兼容性"之外,还有很多显著的"好处"。请参阅下面我7/10/17回答的"缺点"部分。
除了(旧应用程序兼容性)之外,datetime2在大多数方面都获胜。
较大的值范围
较好精度
较小的存储空间(如果指定了可选的用户指定精度)
请注意以下几点
- 句法
- 精度,刻度
- 存储容量
- 精度小于3的6个字节;
- 精度3和4为7字节。
- 所有其他精度都需要8个字节。
- datetime2(3)的位数与datetime相同,但使用7字节的存储空间而不是8字节(sqlhints-datetime vs datetime2)
- 有关datetime2的详细信息(Transact-SQL msdn文章)
图像来源:MCTS自定步调培训工具包(考试70-432):微软?SQL Server?2008-实施和维护第3章:表格->第1课:创建表格->第66页
- 感谢您展示统计数据+1,datetime2太棒了(获胜者)
- @Iman Abidi:根据Oskar Berggren于2014年9月10日下午3:51在"sqlhints-datetime vs datetime2"文章中的评论,您引用的"datetime2(3)与datetime不同。它们的位数相同,但日期时间的精度为3.33ms,而日期时间2(3)的精度为1ms。"
- @潘卡杰帕卡:哇,别那么快。你可能想看看我17年10月7日的回答中的"缺点"部分。
- datetime2如何使用比datetime更少的存储空间,同时提供更大的范围和更高的精度?
我同意@marc_s和@adam_poward——datetime2是向前发展的首选方法。它具有更宽的日期范围、更高的精度,并且使用相同或更少的存储空间(取决于精度)。
然而,有一件事没有引起讨论……@马克·库斯(Marc_)的国家:埃多克斯(EDOCX1)(9)。但是,这是正确的,相反的情况是不正确的……在进行日期范围搜索时,这很重要(例如,"查找2010年5月5日修改的所有记录")。
.NET版本的DATETIME的范围和精度与DATETIME2相似。当将.NET DATETIME向下映射到旧的SQL DATETIME时,会发生隐式舍入。旧的SQL DATETIME精确到3毫秒。这就是说,11:59:59.997是最接近一天结束的。任何更高的数字都会被四舍五入到第二天。
试试这个:
1 2 3 4
| 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-grand-millisecond-part-datetime-data-sql-server-2000-a
- SQL Server 2008和毫秒
- http://improve.dk/archive/2011/06/16/getting-bit-by-datetime-rounding-or-why-235959-999-ltgt.aspx
- http://milesquaretech.com/blog/post/2011/09/12/datetime-vs-datetime2-sql-is-rounding-my-999-millises!ASPX
- 你也可以避免这种舍入,因为无论如何你都不想找到一天的"结束"。>=5月5日和<5月6日更安全,可以在任何日期/时间类型上工作(当然,时间除外)。还建议避免使用区域性的、不明确的格式,如m/d/yyyy。
- @Aaronbertrand——完全同意,但是看看我们有多少问题,这似乎是值得描述的。
- 你为什么从20100505转到5/5/2010?前一种格式适用于SQL Server中的任何区域。后者会破裂:SET LANGUAGE French; SELECT Convert(datetime, '1/7/2015')oops:2015-07-01 00:00:00.000oops
- @ EBarr:R.日期时间2是向前移动的首选方法。它的日期范围更广,精度更高,并且使用相同或更少的存储空间(取决于精度):我强烈反对。请参阅下面我7/10/17回答的"缺点"部分。简言之,这些好处可能是不需要的(外部工程/科学应用程序),因此不值得损失更多可能需要的好处,更容易(甚至考虑解决方法)隐式/显式转换为浮点数字(天,包括如果适用,自最短日期时间起的分数)的能力,+,-和VG。
如果您是一个访问开发人员,试图将now()写入相关字段,那么datetime2会造成严重破坏。刚刚执行了一个access->sql2008r2迁移,它将所有datetime字段都作为datetime2放入。在值被弹出时用now()追加一条记录。2012年1月1日下午2:53:04可以,但2012年10月1日下午2:53:04不行。
一旦性格改变了。希望它能帮助别人。
几乎所有的答案和评论都是关于正反两面的。以下是迄今为止所有利弊的概述,以及一些关键的利弊(在下面的2中),我只看到提到过一次或根本没有提到过。好的。
赞成的意见:
1.1。更符合ISO(ISO 8601)(尽管我不知道这在实践中是如何发挥作用的)。好的。
1.2。更大的范围(1/1/0001至12/31/9999对1/1/1753-12/31/9999)(尽管额外的范围,所有在1753年之前,除了在历史、天文、地质等应用中,可能不会被使用)。好的。
1.3。与.NET的DateTime类型的范围完全匹配(尽管如果值在目标类型的范围和精度范围内,除了下面的con 2.1之外,两个值之间的转换都不需要特殊编码,否则将发生错误/舍入)。好的。
1.4。更精确(100纳秒,即0.000000,1秒与3.33毫秒(即0.003,33秒)相比(尽管除了在工程/科学应用中,可能不会使用额外的精度)。好的。
1.5。当配置为与Iman Abidi所宣称的相似(1毫秒不是"相同"(3.33毫秒)时,DateTime的精度使用更少的空间(7对8字节),但当然,您将失去精度优势,这可能是两个(另一个是范围)中最受欢迎的一个(尽管可能是不必要的优势)。好的。
欺骗:
2.1。当将参数传递给.NET SqlCommand时,如果传递的值超出了SQL Server DateTime的范围和/或精度,则必须指定System.Data.SqlDbType.DateTime2,因为它默认为System.Data.SqlDbType.DateTime。好的。
2.2。在使用数值和运算符的SQL Server表达式中,无法隐式/轻松地转换为浮点数值(自最小日期时间以来的天数)值,以便对其执行以下操作:好的。
2.2.1加减天数或部分天数。注意:当您需要考虑到日期时间的多个部分(如果不是所有部分)时,使用DateAdd函数作为解决方法并不容易。好的。
2.2.2.为了计算"年龄",取两个日期时间之间的差额。注意:您不能简单地使用SQL Server的DateDiff函数,因为它不像大多数人预期的那样计算age,因为如果两个日期时间正好跨越指定单位的日历/时钟日期时间边界,即使是该单位的一小部分,它也会返回该单位与0之间的差额。例如,如果两个日期时间在不同的日历日(即"1999-12-31 23:59:59.999999"和"2000-01-01 00:00:00.0000000"),那么两个日期时间间隔只有1毫秒的DateDiff中的DateDiff将返回1对0(天)。相同的1毫秒差异日期时间如果移动到不跨越日历日,将返回0(天)的Day中的"datediff"。好的。
2.2.3.取日期时间的Avg(在聚合查询中),只需先转换为"float",然后再转换回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),但是你会失去DateTime2和DateTime的精度和范围(所有这些都是1753年以前的)好处,而DateTime2和DateTime是最大的两个,同时也是最不可能需要的两个,这就引出了一个问题:为什么在需要的时候使用它?对于加减/年龄(与DateDiff/Avg相比),您将失去隐式/易转换为浮点数字(天)的计算优势,这在我的经验中是一个很大的优势。好的。
顺便说一句,日期时间的Avg是(或至少应该是)一个重要的用例。a)除了用于获取日期时间(自公共基准日期时间以来)用于表示持续时间(一种常见做法)时的平均持续时间外,b)还可以获取仪表板类型的统计信息,了解一个范围/一组行的日期时间列中的平均日期时间。c)监控/排除列中可能不再有效和/或可能需要弃用的值的标准(或至少应该是标准的)即席查询是为每个值列出事件计数和(如果可用)与该值相关联的Min、Avg和Max日期时间戳。好的。好啊。
- 就像逆向观点一样,它指出了方程的C边。再加上所有其他的"专家",这将使人们能够根据自己想承受的痛苦做出一个好的选择。
- @伊巴尔:只有我的"逆向观点"的缺点1部分指出了方程的C边。其余的(cons的2.2.1-2.2.3),正如我所说的,是更可能需要的好处(datetime的好处),都与对SQL Server查询和语句的影响有关。
here is an example,the Show You Will之间的大小(字节)存储datetime和smalldatetime类型之间,datetime2(0),(7):与datetime2P></
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 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 |
which归来P></
1 2
| 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 |
我知道如果我第二次到店信息- but not to the millisecond -可以保存datetime2 each如果使用2字节(0)instead of datetime或datetime2(7)。P></
当increased there is with some clients datetime2精密,不支持或日期,时间和力量,你datetime2 convert to literal字符串。专门开发的"唐氏mentions Microsoft ODBC,OLE DB级",这些问题与JDBC和SqlClient数据,在图表类型和how each has the map可以表现型。P></
如果电压值compatability精密,使用datetimeP></
对字符串和日期datetimeinto of datetime2can be when using不太一样,中美DATEFORMATsettings。例如P></
1 2 3 4
| 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)for(即六月5,2013-06-05for datetime2)。不管一个人多,与DATEFORMATto mdy集,都@d@d22013-06-05和回车。P></
the datetime行为似乎在MSDN文档SET DATEFORMATOR with the which some of character strings:美国formats for example,ISO 8601,interpreted DataFormat independently are of the setting。明显不是真的!P></
直到我bitten by this,that yyyy-mm-dd我总是一只会思想handled好吧,regardless of the Language Settings /地方。P></
- 不。对于ISO 8601,我认为您的意思是YYMMDD(无破折号)。SET LANGUAGE FRENCH; DECLARE @d DATETIME = '20130605'; SELECT @d;用破折号再试一次。
- 该标准允许日历日期表示的YYYY-MM-DD和YYYYMMDD格式。我认为,对于ISO 8601规范的哪一个子集是独立解释的,msdn应该更具体一些!
- 我知道,但在SQL Server中,只有无破折号语法是安全的。
老问题。但我想stated add something by not already here的人……(注:这是我自己的观察,我不知道任何参考ask for)P></
datetime2 is when used in filter标准更快。P></
TLDR:P></
我在SQL表中与2016年百千行和datetime时间因为它_ column条目来店时间精确up to the seconds。在同时执行多joins复合查询与子查询的布尔used as,when where子句的:P></
1
| WHERE ENTRY_TIME >= '2017-01-01 00:00:00' AND ENTRY_TIME < '2018-01-01 00:00:00' |
最后initially when there was the query是hundreds of Rows rows,but when the number of increased查询开始,给这个误差:P></
1 2
| Execution Timeout Expired. The timeout period elapsed prior
TO completion OF the operation OR the server IS NOT responding. |
在这些条款和unexpectedly removed the,the Run,查询是在1秒,尽管现在使用的是在一fetched for。在茶内运行查询和条款,我和它没有在第85秒,和0.01 secs恩了。P></
多线程的肉类在这里this as DateTime的过滤性能问题。P></
optimized查询到的数据位。but the real was by changing the速得datetime2 DateTime column to。P></
查询超时时间一样,现在需要在第二previously less。P></
干杯P></
根据这一条,如果你会喜欢have the same精密使用简单的DateTime datetime2 of You have to datetime2使用(3)。这应该给你一个不一样的精密跟踪,提供安fewer字节,和扩大范围。P></
- 显然,它的精度与SQL日期时间相同,而不是.NET日期时间。
- 这是正确的,我假设每个人都会理解上下文,但它值得具体说明。
我只是在一个更多stumbled for datetime2优势:avoids bug in the Python模块adodbapi,which吹弹出如果标准库passed which has datetime值是非零microseconds for a column but if the datetime工作结束定义datetime2column is as。P></
1 2
| SELECT ValidUntil + 1
FROM Documents |
the above SQL与datetime2场不会工作。恩归来"和错误的操作数是不兼容与datetime2型冲突:int"P></
增1 to get the next day is something with have been for developers做一年。现在有一场超微软新datetime2 that cannot handle this simple功能性。P></
"让我们用新型that is this比原有老人",我不想知道!P></
- 正如我们在这里清楚地看到的,datetime和datetime2数据类型都是在SQL Server 2008中引入的。您还可以从date类型中获得Operand type clash: date is incompatible with int,该类型自day dot以来一直存在。不过,这三种数据类型都可以与dateadd(dd, 1, ...)一起工作。
- 这还不清楚。我有一个sqlserver 2005数据库,其中包含日期时间字段。
我认为最好的方式datetime2 is the to store the日期,因为它有更多的效率比the的DateTime。你可以使用在SQL Server 2008 datetime2店日期和时间,它需要6~8个字节,在商店和has to nanoseconds精密of 100。任何人谁需要知道时间会想datetime2更精密。P></