在SQL Server中将varchar转换为datetime

69
如何在SQL Server 2008中将格式为mmddyyyy的字符串转换为datetime
目标列应为DateTime
我已经尝试使用Convert函数和大多数Date样式值,但是我收到了一个错误消息:

'将varchar数据类型转换为datetime数据类型导致超出范围的值。'


1
T-SQL是否有类似MySQL的str_to_date函数?http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_str-to-date - dnagirl
2
OP想要mmddyyyy格式;选择convert(datetime,'12312009') -->>>_Msg 242, Level 16, State 3, Line 1 将char数据类型转换为datetime数据类型时,导致超出范围的datetime值。 - KM.
13个回答

77

楼主需要mmddyy格式的日期,普通的转换方法无法实现:

select convert(datetime,'12312009')

Msg 242, Level 16, State 3, Line 1 
The conversion of a char data type to a datetime data type resulted in 
an out-of-range datetime value

那么尝试这个:

DECLARE @Date char(8)
set @Date='12312009'
SELECT CONVERT(datetime,RIGHT(@Date,4)+LEFT(@Date,2)+SUBSTRING(@Date,3,2))

输出:

-----------------------
2009-12-31 00:00:00.000

(1 row(s) affected)

2
+1,但是不用拼接字符串会更好吧?http://www.techonthenet.com/oracle/functions/to_date.php - dwerner
11
如果你不想做那样的事情,就不要存储在错误的数据类型中。 - HLGEM
2
请纠正我,但这是问题提出的问题。我的建议是使用专为此目的量身定制的函数。 - dwerner
1
你的“建议”对我来说似乎是一种普通的公司推销。对于几乎所有的数据库开发人员,甚至是首席架构师,使用完全不同的数据库技术的建议是否有用或实际呢?并不是真的。似乎将信息存储为非varchar字符串,或者至少作为ISO格式化字符串可能更容易些。 - Lucas Leblanc
@LucasLeblanc,你必须考虑到OP所要求的内容。OP没有详细说明为什么需要这样做,可能是因为他们正在与无法更改的事物进行接口交互。此外,我永远不会建议你将日期存储为字符串,否则就会出现这样的问题。 - KM.
就数据类型而言,那就是我所说的,尽管再读一遍我的评论,我的措辞并不好。我应该说“似乎将信息存储为除varchar字符串以外的任何东西可能更容易。” - Lucas Leblanc

7

SQL Server可以将形如“YYYYMMDD”的字符串隐式转换为日期时间——所有其他字符串必须显式转换。以下是两个快速的代码块,可以将您所说的格式进行转换:

版本1使用单位变量:

BEGIN 
DECLARE @input VARCHAR(8), @mon CHAR(2), 
@day char(2), @year char(4), @output DATETIME

SET @input = '10022009'   --today's date


SELECT @mon = LEFT(@input, 2), @day = SUBSTRING(@input, 3,2), @year = RIGHT(@input,4)

SELECT @output = @year+@mon+@day 
SELECT @output 
END

版本2不使用单位变量:

BEGIN 
DECLARE @input CHAR(8), @output DATETIME
SET @input = '10022009' --today's date 

SELECT @output = RIGHT(@input,4) + SUBSTRING(@input, 3,2) + LEFT(@input, 2)

SELECT @output
END

这两种情况都依赖于SQL Server进行隐式转换的能力。


6
可能您有无法转换的错误数据。日期不应该存储在varchar中,因为它会允许像ASAP或02/30/2009这样的日期。请对您的数据使用isdate()函数查找无法转换的记录。
好的,我用已知的正确数据进行了测试,但仍然得到了相同的消息。您需要将其转换为不同的格式,因为它不知道12302009是mmddyyyy还是ddmmyyyy。yyyymmdd的格式不含歧义,SQL Server将正确地进行转换。
我已经让它起作用了:
cast( right(@date,4) + left(@date,4) as datetime)

如果您的日期格式不是标准格式,例如 '112009' 或某些文本值或超出范围的日期,您仍然会收到错误消息。


在对类似于OP的mmddyyyy格式的一百万个随机日期字符串进行了一些测试后,发现这是运行最快且编码最容易的方法。还有其他方法可以与之并列,但在所有实际按照OP在本线程中要求工作的代码中,这个方法每次都获胜。在一百万行数据中,它的优势不超过25毫秒,但考虑到编码的简便性和我测试的其他方法的负载,这个方法获胜了。 - Jeff Moden

6

但这不是OP拥有的格式。OP被困在将mmddyyyy转换为日期时间的问题中。 - Jeff Moden

5

转换通常是正常的答案,但是该格式不是转换器识别的格式,mm/dd/yyyy可以使用convert(datetime,yourdatestring,101)进行转换,但您没有该格式,因此失败。

问题在于格式不标准,您必须将其操作为转换器可以从可用格式中理解的标准格式。

如果您能保证格式,则可以将其组合在一起。

declare @date char(8)
set @date = '12312009'
select convert(datetime, substring(@date,5,4) + substring(@date,1,2) + substring(@date,3,2),112)

4

请查看 BOL 中的 CAST / CONVERT,这应该是一个好的开始。

如果您的目标列是 datetime,则不需要进行转换,SQL 会自动处理。

否则

CONVERT(datetime, '20090101')

应该这样做。

这是一个链接,也应该有所帮助:


但这并不是原帖的格式。原帖作者需要将mmddyyyy转换为datetime类型。 - Jeff Moden

3

我会使用STUFF函数插入分隔符,然后再使用适当的样式来使用CONVERT函数。类似这样:

DECLARE @dt VARCHAR(100)='111290';
SELECT CONVERT(DATETIME,STUFF(STUFF(@dt,3,0,'/'),6,0,'/'),3)

首先您需要使用两次STUFF来获取11/12/90而不是111290,然后您使用3将其转换为datetime(或任何其他适合的格式:对于德国,请使用,对于英国,请使用-...)有关CAST和CONVERT的更多详细信息

最好的方法是正确存储日期和时间值。

任何特定于文化的格式迟早会导致麻烦...


这非常有用,特别是当你有类似于201901或201905的字符串格式时。 - Photops

2
使用Try_Convert:如果强制转换成功,则返回一个转换为指定数据类型的值;否则返回null。
DECLARE @DateString VARCHAR(10) ='20160805'
SELECT TRY_CONVERT(DATETIME,@DateString)

SET @DateString ='Invalid Date'
SELECT TRY_CONVERT(DATETIME,@DateString)

Link:MSDN TRY_CONVERT (Transact-SQL)


但这不是OP拥有的格式。OP被困在将mmddyyyy转换为日期时间的问题中。 - Jeff Moden

1

我在类似的事情上运气不错:

Convert(DATETIME, CONVERT(VARCHAR(2), @Month) + '/' + CONVERT(VARCHAR(2), @Day)
+ '/' + CONVERT(VARCHAR(4), @Year))

OP没有可用的变量。只有一个以MMDDYYYY格式表示的字符串。 - Jeff Moden

0
DECLARE @d char(8)
SET @d = '06082020'    /* MMDDYYYY means June 8. 2020 */
SELECT CAST(FORMAT (CAST (@d AS INT), '##/##/####') as DATETIME)

返回的结果是 @d 中的原始日期字符串作为 DateTime。


但这不是OP拥有的格式。 OP必须将mmddyyyy转换为datetime。 - Jeff Moden
Jeff Moden同意了,答案已更新以反映问题的要求。 - Kevin Horgan
感谢反馈。提醒一下,如果您还不知道的话,FORMAT函数通常需要比一些更复杂的CAST/CONVERT功能执行时间长43倍甚至更多。由于它太慢了,我通常会像避开瘟疫一样避免使用它。 - Jeff Moden

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接