TSQL DATETIME ISO 8601

Mar*_*iff 55 sql t-sql sql-server datetime

我已经获得了一个需要ISO 8601日期格式的规范,任何人都知道转换代码或获取这两个示例的方法:

ISO 8601 Extended Date 2000-01-14T13:42Z 
ISO 8601 Basic Date 20090123T105321Z
Run Code Online (Sandbox Code Playgroud)

mar*_*c_s 88

在处理SQL Server中的日期时,ISO-8601格式可能是最好的方法,因为无论您的语言和文化设置如何,它都能正常工作.

为了将数据插入SQL Server表,您根本不需要任何转换代码或任何内容 - 只需将日期指定为文字字符串

INSERT INTO MyTable(DateColumn) VALUES('20090430 12:34:56.790')
Run Code Online (Sandbox Code Playgroud)

你完成了

如果需要在SELECT上将日期列转换为ISO-8601格式,则可以使用转换代码126或127(带有时区信息)来实现ISO格式.

SELECT CONVERT(VARCHAR(33), DateColumn, 126) FROM MyTable
Run Code Online (Sandbox Code Playgroud)

应该给你:

2009-04-30T12:34:56.790
Run Code Online (Sandbox Code Playgroud)

  • 如果字段是datetimeoffset,则126似乎包含时区信息.127将其转换为UTC. (4认同)
  • @Jeremy Ross - 使用CONVERT(nvarchar(30),DateField,126).那么你应该得到2004-12-14T10:05:59.000 (2认同)
  • @hvd 这可能证明 varchar 与 char 的合理性(如果尾随空格永远会成为问题;我对此表示怀疑);这并不意味着您应该完全省略某个长度。请[完整阅读](https://sqlblog.org/blogs/aaron_bertrand/archive/2009/10/09/bad-habits-to-kick-declaring-varchar-without-length.aspx)。这是关于一致性的,并且始终使用明确的长度,即使它看起来并不重要。至于 DateField 与 DateColumn - 因为我是人类? (2认同)
  • @hvd 那么为什么要***删除***长度呢?如果你真的想要,你可以通过使用 `varchar(23)`(使用旧日期/时间数据类型的最长可能值)或 `varchar(33)`(使用新类型的最长可能值)来改进我的编辑和更正我错过的名字,而不是完全撤消它。现在,您的还原实际上会以静默方式截断 `datetimeoffset` 值,因为当您不包含长度时,在这种情况下,它将截断 30 个字符。至少我的编辑不会有任何关于*为什么*的混淆。 (2认同)
  • @marc_s 127也不添加Z. (2认同)

Cyb*_*ist 22

这个

SELECT CONVERT(NVARCHAR(30), GETDATE(), 126)
Run Code Online (Sandbox Code Playgroud)

会产生这个

2009-05-01T14:18:12.430
Run Code Online (Sandbox Code Playgroud)

有关这方面的更多细节可以在MSDN上找到.

  • 由于NVARCHAR没有返回空格填充,因此赞成此答案. (3认同)
  • @PhillipSenn我强烈建议将它留在里面,即使它在技术上是多余的.没有显式大小的`nvarchar`在某些上下文中默认为"30",在其他上下文中默认为"1",这会损害可读性.试试`select convert(nvarchar,getdate(),126); 声明@v nvarchar = convert(nvarchar,getdate(),126);`:第一个语句显示这不会被截断.第二个语句看起来好像该值存储在完全相同类型的变量中.我会说,这是SQL Server非常不直观的方面. (3认同)
  • @RichardAyotte 空间填充什么时候重要?`GETDATE()` 什么时候会包含 Unicode 字符(换句话说,为什么是 `nvarchar` 而不是 `varchar`)? (2认同)

Joh*_*n P 12

如果您只需输出ISO8601格式的日期(包括尾随Z),并且您至少在SQL Server 2012上,那么您可以使用FORMAT:

FORMAT

这会给你一些类似的东西:

FORMAT

  • `SELECT FORMAT(GetUtcDate(),'yyyy-MM-ddTHH:mm:ss.fffZ')`为你工作吗? (3认同)

Jef*_*den 6

天哪,不!如果您在SQL Server中存储格式化日期,那么您会要求一个受伤的世界.始终存储您的日期和时间以及SQL Server"日期/时间"数据类型之一(DATETIME,DATE,TIME,DATETIME2,等等).让前端代码解析显示方法,并且只在构建临时表以构建文件时存储格式化日期.如果绝对必须从SQL Server显示ISO日期/时间格式,则只在显示时执行.我不能强调...不要在SQL Server中存储格式化的日期/时间.

{编辑}.原因很多,但最明显的是,即使有一个很好的ISO格式(可以排序),所有未来的日期计算和搜索(例如,搜索给定月份中的所有行)都需要至少一个隐含的转换(需要额外的时间),如果存储的格式化日期不是您当前需要的格式,则需要先将其转换为日期,然后再转换为您想要的格式.

前端代码也是如此.如果存储格式化日期(文本),则需要相同的旋转来显示由Windows或应用程序定义的本地日期格式.

我的建议是始终将日期/时间存储为DATETIME或其他时态数据类型,并仅在显示时格式化日期.

  • 我认为您误解了 - 将'20121001'插入DateTime列将始终转换相同,无论区域设置如何 - Marc并未建议列类型应为字符串. (11认同)
  • -1 OP正在询问*如何*完成某些事情而不是关于是否应该完成的建议.这不是原始问题的答案,而是基于很少或根本没有洞察用户为什么首先提出问题的意见.OP很可能要求这样做,你的回答根本没有帮助他.这些事情应该作为评论发布.答案应该总是提供答案. (5认同)
  • @JeffModen"答案应始终提供答案"直接引自[FAQ](http://meta.stackexchange.com/a/17479).你的回复没有回答OP的问题.如果说这个隐喻的人即将被活活烧死,那么头部的射击是更好的选择.上下文杀死.;-)如果你必须告诉OP为什么你认为他的决定是坏的,那么在回答之前就有理由. (4认同)