SQL Server字符串到日期的转换


186

我想这样转换一个字符串:

'10/15/2008 10:06:32 PM'

转换为Sql Server中的等效DATETIME值。

在Oracle中,我会这样说:

TO_DATE('10/15/2008 10:06:32 PM','MM/DD/YYYY HH:MI:SS AM')

这个问题意味着我必须将字符串解析为标准格式之一,然后使用这些代码之一进行转换。对于这种平凡的行动来说,这似乎很可笑。有更容易的方法吗?


Answers:


28

SQL Server(2005,2000,7.0)没有任何灵活的甚至不灵活的方式来获取字符串格式的任意结构化datetime并将其转换为datetime数据类型。

“任意”是指“一种书写形式的人,尽管可能不是您,我或地球另一端的人,但会认为它是直观且完全显而易见的。” 坦白说,我不确定是否有这样的算法。


32
有了这样的算法,Oracle已经实现了它,而SQL Server缺乏等效的特性一直是困扰。
matao 2012年

19
@matao,请启迪我们,Oracle如何神奇地确定键入的用户9/6/12是2012年9月6日,2012年6月9日,2009年12月6日,还是其他?
亚伦·伯特兰

13
不用担心,在这里:techonthenet.com/oracle/functions/to_date.php显然,它必须是开发人员指定的一致格式,但是比MS给您提供的少数格式掩码要灵活得多,这将导致痛苦的自定义解析。
matao

3
如他的示例所示,@ JosphStyons知道Oracle的TO_DATE函数。他想知道是否有一种方法可以将日期转换为字符串,不必知道字符串的格式/结构。SQL并没有这样做,而且Oracle的TO_DATE显然也没有这样做。
菲利普·凯利2013年

23
@PhilipKelley我不知道OP想要在不知道格式的情况下如何去做。他明确表示自己知道格式,并询问SQL Server是否具有与TO_DATE等效的功能,即允许开发人员输入任意格式字符串的功能。
neverfox 2014年

305

试试这个

Cast('7/7/2011' as datetime)

Convert(varchar(30),'7/7/2011',102)

有关更多详细信息,请参见CAST和CONVERT(Transact-SQL)


14
这是正确的方法,应将其标记为正确答案。请注意,这Cast('2011-07-07' as datetime)也是可行的,并且消除了月与日顺序之间的歧义。
Joe DeRose 2015年

当月是这不起作用> 12.格式化预计为mm / dd / yyyy格式

从dd / mm / yyyy转换时使用Convert(varchar(30),'7/7/2011',103)
Matias Masso

2
@Chakri(如果您的日期在SET DATEFORMAT dmy查询之前以dd / mm / yyyy使用)
Nathan Griffiths

48

通过查询处理器运行它。它像这样格式化日期和/或时间,其中之一应该可以为您提供所需的内容。很难适应:

Declare @d datetime
select @d = getdate()

select @d as OriginalDate,
convert(varchar,@d,100) as ConvertedDate,
100 as FormatValue,
'mon dd yyyy hh:miAM (or PM)' as OutputFormat
union all
select @d,convert(varchar,@d,101),101,'mm/dd/yy'
union all
select @d,convert(varchar,@d,102),102,'yy.mm.dd'
union all
select @d,convert(varchar,@d,103),103,'dd/mm/yy'
union all
select @d,convert(varchar,@d,104),104,'dd.mm.yy'
union all
select @d,convert(varchar,@d,105),105,'dd-mm-yy'
union all
select @d,convert(varchar,@d,106),106,'dd mon yy'
union all
select @d,convert(varchar,@d,107),107,'Mon dd, yy'
union all
select @d,convert(varchar,@d,108),108,'hh:mm:ss'
union all
select @d,convert(varchar,@d,109),109,'mon dd yyyy hh:mi:ss:mmmAM (or PM)'
union all
select @d,convert(varchar,@d,110),110,'mm-dd-yy'
union all
select @d,convert(varchar,@d,111),111,'yy/mm/dd'
union all
select @d,convert(varchar,@d,12),12,'yymmdd'
union all
select @d,convert(varchar,@d,112),112,'yyyymmdd'
union all
select @d,convert(varchar,@d,113),113,'dd mon yyyy hh:mm:ss:mmm(24h)'
union all
select @d,convert(varchar,@d,114),114,'hh:mi:ss:mmm(24h)'
union all
select @d,convert(varchar,@d,120),120,'yyyy-mm-dd hh:mi:ss(24h)'
union all
select @d,convert(varchar,@d,121),121,'yyyy-mm-dd hh:mi:ss.mmm(24h)'
union all
select @d,convert(varchar,@d,126),126,'yyyy-mm-dd Thh:mm:ss:mmm(no spaces)'

47

在SQL Server Denali中,您将能够执行符合您所要查找内容的操作。但是您仍然不能仅仅传递任何任意定义的古怪日期字符串,并期望SQL Server能够容纳。这是一个使用您在自己的答案中发布的内容的示例。FORMAT()函数还可以接受语言环境作为可选参数-它基于.Net的格式,因此大多数(如果不是全部)您希望看到的令牌格式都将存在。

DECLARE @d DATETIME = '2008-10-13 18:45:19';

-- returns Oct-13/2008 18:45:19:
SELECT FORMAT(@d, N'MMM-dd/yyyy HH:mm:ss');

-- returns NULL if the conversion fails:
SELECT TRY_PARSE(FORMAT(@d, N'MMM-dd/yyyy HH:mm:ss') AS DATETIME);

-- returns an error if the conversion fails:
SELECT PARSE(FORMAT(@d, N'MMM-dd/yyyy HH:mm:ss') AS DATETIME);

我强烈建议您多加控制并清理日期输入。现在,让人们使用他们想要的任何格式在自由文本表单字段中键入日期的日子现在应该已经过去了。如果有人输入8/9/2011是8月9日还是9月8日?如果让他们在日历控件上选择日期,则该应用可以控制格式。无论您试图预测用户的行为如何,他们总是会找出一种愚蠢的方式来输入您未计划的日期。

但是,直到Denali,我认为@Ovidiu到目前为止是最好的建议...通过实现自己的CLR函数,这可以变得相当简单。然后,您可以根据需要编写许多古怪的非标准格式的保护套/开关。


@dhergert的更新

SELECT TRY_PARSE('10/15/2008 10:06:32 PM' AS DATETIME USING 'en-us');
SELECT TRY_PARSE('15/10/2008 10:06:32 PM' AS DATETIME USING 'en-gb');

结果:

2008-10-15 22:06:32.000
2008-10-15 22:06:32.000

您仍然需要首先获得其他关键信息。您不能使用本机T-SQL来确定6/9/2012是6月9日还是9月6日。


1
我认为问题是如何将字符串转换为日期时间,而不是将日期时间转换为字符串。
大卫·赫格特

1
TRY_PARSE非常完美。解析日期为“ 2016年9月22日星期四”时遇到问题,感谢分享!
西蒙(Simon)

11

对于此问题,我使用的最佳解决方案是在Sql Server 2005中具有CLR函数,该函数使用DateTime.Parse或ParseExact函数之一返回具有指定格式的DateTime值。


11

用这个:

SELECT convert(datetime, '2018-10-25 20:44:11.500', 121) -- yyyy-mm-dd hh:mm:ss.mmm

并参考官方文档中的表格以获取转换代码。


8

为什么不尝试

select convert(date,'10/15/2011 00:00:00',104) as [MM/dd/YYYY]

日期格式可以在“ SQL Server帮助器”>“ SQL Server日期格式”中找到。


您的代码示例不起作用。“从字符串转换日期和/或时间时转换失败。”
塞萨尔·莱昂

5
应该是select convert(date,'10/15/2011 00:00:00',101)docs.microsoft.com/en-us/sql/t-sql/functions/…
anotherUser

1
八个人投票赞成这个答案,甚至没有效果……
David Klempfner

4

花了我一点时间来解决这个问题,以防万一可能对某人有所帮助:

在SQL Server 2012和更高版本中,可以使用此功能:

SELECT DATEFROMPARTS(2013, 8, 19);

这是我最终提取日期部分以放入此函数的方法:

select
DATEFROMPARTS(right(cms.projectedInstallDate,4),left(cms.ProjectedInstallDate,2),right( left(cms.ProjectedInstallDate,5),2)) as 'dateFromParts'
from MyTable

3

页面对所有可用的转换函数指定的日期时间转换的一些参考。如果您的值没有落入可接受的模式之一,那么我认为最好的方法是采用ParseExact路线。


链接断开。
迈克尔·波特

3

就个人而言,如果您要处理任意格式或完全不适用的格式,只要您知道它们提前或将要使用的格式,则只需使用regexp即可提取所需日期的部分并形成有效的date / datetime组件。


1

我知道这是一篇邪恶的老文章,提供了很多答案,但是很多人认为他们需要将事情拆散再放回去,或者他们坚持认为没有办法隐含地进行OP原件要求的转换。

为了复习并希望向其他提出相同问题的人提供简单的答案,OP询问如何将“ 10/15/2008 10:06:32 PM”转换为DATETIME。现在,SQL Server确实对时间转换具有某些语言依赖性,但是如果语言是英语或类似语言,这将成为一个简单的问题...只需执行转换,而不必担心格式。例如(您可以使用CONVERT或CAST)...

 SELECT UsingCONVERT = CONVERT(DATETIME,'10/15/2008 10:06:32 PM')
        ,UsingCAST   = CAST('10/15/2008 10:06:32 PM' AS DATETIME)
;

...并得出以下答案,两者都是正确的。

在此处输入图片说明

就像他们在电视广告中说的那样:“但是等等!还不订购!无需额外费用,它还能做更多!”

让我们看看使用DATETIME进行时间转换的真正力量,并部分检查称为DATETIME2的错误。看看DATETIME可以自动处理而DATETIME2无法自动处理的怪异格式。运行以下代码,然后查看...

--===== Set the language for this example.
    SET LANGUAGE ENGLISH --Same a US-English
;
--===== Use a table constructor as if it were a table for this example.
 SELECT *
        ,DateTimeCONVERT  = TRY_CONVERT(DATETIME,StringDT)
        ,DateTimeCAST     = TRY_CAST(StringDT AS DATETIME)
        ,DateTime2CONVERT = TRY_CONVERT(DATETIME2,StringDT)
        ,DateTime2CAST    = TRY_CAST(StringDT AS DATETIME2)
   FROM (
         VALUES
         ('Same Format As In The OP'    ,'12/16/2001 01:51:01 PM')
        ,('Almost Normal'               ,'16 December, 2001 1:51:01 PM')
        ,('More Normal'                 ,'December 16, 2001 01:51:01 PM')
        ,('Time Up Front + Spaces'      ,'   13:51:01  16 December   2001')
        ,('Totally Whacky Format #01'   ,'  16  13:51:01  December   2001')
        ,('Totally Whacky Format #02'   ,'  16    December 13:51:01  2001  ')
        ,('Totally Whacky Format #03'   ,'  16    December 01:51:01  PM 2001  ')
        ,('Totally Whacky Format #04'   ,' 2001 16    December 01:51:01  PM ')
        ,('Totally Whacky Format #05'   ,' 2001    December 01:51:01  PM  16  ')
        ,('Totally Whacky Format #06'   ,' 2001 16    December  01:51:01 PM  ')
        ,('Totally Whacky Format #07'   ,' 2001 16    December  13:51:01 PM  ')
        ,('Totally Whacky Format #08'   ,' 2001 16  13:51:01 PM  December    ')
        ,('Totally Whacky Format #09'   ,'   13:51:01   PM  2001.12/16 ')
        ,('Totally Whacky Format #10'   ,'   13:51:01   PM  2001.December/16 ')
        ,('Totally Whacky Format #11'   ,'   13:51:01   PM  2001.Dec/16 ')
        ,('Totally Whacky Format #12'   ,'   13:51:01   PM  2001.Dec.16 ')
        ,('Totally Whacky Format #13'   ,'   13:51:01   PM  2001/Dec.16')
        ,('Totally Whacky Format #14'   ,'   13:51:01   PM  2001 . 12/16 ')
        ,('Totally Whacky Format #15'   ,'   13:51:01   PM  2001 . December / 16 ')
        ,('Totally Whacky Format #16'   ,'   13:51:01   PM  2001 . Dec /   16 ')
        ,('Totally Whacky Format #17'   ,'   13:51:01   PM  2001 . Dec .   16 ')
        ,('Totally Whacky Format #18'   ,'   13:51:01   PM  2001 / Dec .   16')
        ,('Totally Whacky Format #19'   ,'   13:51:01   PM  2001 . Dec -   16 ')
        ,('Totally Whacky Format #20'   ,'   13:51:01   PM  2001 - Dec -   16 ')
        ,('Totally Whacky Format #21'   ,'   13:51:01   PM  2001 - Dec .   16')
        ,('Totally Whacky Format #22'   ,'   13:51:01   PM  2001 - Dec /   16 ')
        ,('Totally Whacky Format #23'   ,'   13:51:01   PM  2001 / Dec -   16')
        ,('Just the year'               ,' 2001      ')
        ,('YYYYMM'                      ,' 200112      ')
        ,('YYYY MMM'                    ,'2001 Dec')
        ,('YYYY-MMM'                    ,'2001-Dec')
        ,('YYYY    .     MMM'           ,'2001    .     Dec')
        ,('YYYY    /     MMM'           ,'2001    /     Dec')
        ,('YYYY    -     MMM'           ,'2001    /     Dec')
        ,('Forgot The Spaces #1'        ,'2001December26')
        ,('Forgot The Spaces #2'        ,'2001Dec26')
        ,('Forgot The Spaces #3'        ,'26December2001')
        ,('Forgot The Spaces #4'        ,'26Dec2001')
        ,('Forgot The Spaces #5'        ,'26Dec2001 13:51:01')
        ,('Forgot The Spaces #6'        ,'26Dec2001 13:51:01PM')
        ,('Oddly, this doesn''t work'   ,'2001-12')
        ,('Oddly, this doesn''t work'   ,'12-2001')
        ) v (Description,StringDT)
;

所以,是的... SQL Server实际上有一种相当灵活的方法来处理各种奇怪的时间格式,并且不需要特殊的处理。我们甚至不需要删除添加到24小时内的“ PM”。这是“ PFM”(纯粹的“怪胎”魔术)。

根据您为服务器选择的语言,情况会有所不同,但是无论哪种方式都可以处理。

这些“自动魔术”转换并不是什么新鲜事物。他们走了很长的路要走。


邪恶的旧问题的邪恶的新答案。谢谢!
6

感谢您的反馈,@ JosephStyons。
杰夫·摩登

0

如果您想让SQL Server尝试解决问题,只需使用CAST CAST(“ whatever” AS datetime)即可。但是,通常这是一个坏主意。国际日期会出现问题。因此,您已经发现,为了避免这些问题,您想使用日期的ODBC规范格式。即格式编号120,20是仅两位数年份的格式。我认为SQL Server没有内置功能可以让您提供用户指定的格式。您可以编写自己的文章,如果在线搜索甚至可能会找到一个。


如果您在单列中有国际日期,我绝对同意使用格式编号是个好主意。如果您将国际日期和美国日期都混合在同一列中,那么除非您有一个解释该格式的姊妹列,否则无法确定7/6/2000和6/7/2000之类的区别。因此,源头的数据质量必定是一回事。如果您知道自己拥有所有美国日期,请让隐式转换完成任务。如果它们失败了,那么您肯定会知道该列中的某些问题需要修复。
杰夫·摩登

0

在MSSQL中隐式将字符串转换为日期时间

create table tmp 
(
  ENTRYDATETIME datetime
);

insert into tmp (ENTRYDATETIME) values (getdate());
insert into tmp (ENTRYDATETIME) values ('20190101');  --convert string 'yyyymmdd' to datetime


select * from tmp where ENTRYDATETIME > '20190925'  --yyyymmdd 
select * from tmp where ENTRYDATETIME > '20190925 12:11:09.555'--yyyymmdd HH:MIN:SS:MS



您好,欢迎来到stackoverflow,并感谢您的回答。尽管此代码可以回答问题,但是您可以考虑添加一些说明来解决什么问题以及如何解决吗?这将帮助将来的读者更好地理解您的答案并从中学习。
普卢安

-4
dateadd(day,0,'10/15/2008 10:06:32 PM')

3
欢迎来到StackOverflow!请编辑您的答案以添加代码说明。这个问题已经有11年历史了,并且已经有了很多可以解释的,颇受好评的答案。如果您在回答中没有解释,那么与其他产品相比,它的质量要低得多,并且很可能会被低估或删除。添加该说明将有助于在此处证明您答案的存在性。
Das_Geek

是的,但“经过充分解释的”帖子,甚至是被推荐的帖子,都太复杂了。此处发布的实际上是更好的版本之一,有或没有解释,
杰夫·莫登
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.