从varchar到无日期的时间转换问题

时间:2019-11-26 10:30:07

标签: sql-server tsql time sql-server-2008-r2

此查询符合预期

SELECT CAST('8:40 AM' AS TIME) Times
UNION
SELECT CAST('12:01 PM' AS TIME)
UNION
SELECT CAST('12:04 PM' AS TIME)
UNION
SELECT CAST('12:41 PM' AS TIME)
UNION
SELECT CAST('12:45 PM' AS TIME)
UNION
SELECT CAST('1:28 PM' AS TIME)
UNION
SELECT CAST('1:43 PM' AS TIME)

以上选择查询的输出

Times
----------------
08:40:00.0000000
12:01:00.0000000
12:04:00.0000000
12:41:00.0000000
12:45:00.0000000
13:28:00.0000000
13:43:00.0000000

此查询也可以正常使用

DECLARE @timeString VARCHAR(MAX) =
'
8:40 AM ,
12:01 PM,
12:04 PM,
12:41 PM,
12:45 PM,
1:28 PM ,
1:43 PM,,
'

;WITH CTE AS
(
    SELECT TIMELIST.a.value('.','VARCHAR(MAX)') Times FROM(SELECT CAST('<P>'+REPLACE(@timeString,',','</P><P>')+'</P>' AS XML) AS TIMESPLIT) AS T CROSS APPLY  T.TIMESPLIT.nodes('/P') AS TIMELIST(a)
)
SELECT LTRIM(RTRIM(Times)) Times FROM CTE WHERE Times != ''

以上选择查询的输出

Times
------------
8:40 AM
12:01 PM
12:04 PM
12:41 PM
12:45 PM
1:28 PM
1:43 PM

此查询无法正常工作

;WITH CTE AS
(
    SELECT TIMELIST.a.value('.','VARCHAR(MAX)') Times FROM(SELECT CAST('<P>'+REPLACE(@timeString,',','</P><P>')+'</P>' AS XML) AS TIMESPLIT) AS T CROSS APPLY  T.TIMESPLIT.nodes('/P') AS TIMELIST(a)
)
SELECT CAST(LTRIM(RTRIM(Times)) AS TIME) Times FROM CTE WHERE Times != ''

上述查询返回错误。

  

消息241,级别16,状态1,第83行转换时转换失败   字符串中的日期和/或时间。

1 个答案:

答案 0 :(得分:2)

“字符串”值包含换行符(CR和LF)。 LTRIM / RTRIM不会修剪这些字符,因此您需要:

WITH CTE AS
(
    SELECT TIMELIST.a.value('.','VARCHAR(MAX)') Times
    FROM (
         SELECT CAST('<P>'+REPLACE(@timeString,',','</P><P>')+'</P>' AS XML) AS TIMESPLIT
    ) AS T
    CROSS APPLY T.TIMESPLIT.nodes('/P') AS TIMELIST(a)
)
SELECT CAST(REPLACE(REPLACE(LTRIM(RTRIM(TIMES)), CHAR(10), ''), CHAR(13), '') AS VARCHAR) Times
FROM CTE WHERE Times!=''

如果您使用的是SQL 2016+,那么STRING_SPLIT是一个更为优雅的解决方案。如果您使用的是2017年以上版本,那么TRIM(... FROM ...)会简化修剪过程。