【问题标题】:Getting Conversion failed error when converting date and/or time from character string从字符串转换日期和/或时间时出现转换失败错误
【发布时间】:2021-02-24 13:59:36
【问题描述】:

在我的表中,值保存为Thursday November 12, 2020 07:01。我想将这些值转换为日期时间。这是我写的查询。

select  
 convert(varchar(200), replace(replace(replace(replace(replace(replace(replace(publishedon,'Monday',''),'Saturday',''),'Sunday',''),'Tuesday',''),'Wednesday',''),'Thursday',''),'Friday','')) 
from py_EconNext 

一旦我从值中删除了日期,我就可以得到November 12, 2020 11:04 的值。之后我尝试将其转换为日期时间。将其转换为日期时间时,出现错误

从字符转换日期和/或时间时转换失败 字符串。

但是当我运行如下选择时

select  convert(datetime,convert(varchar(200),(' November 12, 2020  11:04'))) 

我可以得到2020-11-12 11:04:00.000 的值而没有任何错误。

表列数据类型 - varchar(200)

【问题讨论】:

  • 您成为classic blunders 之一的受害者——其中最著名的是“永远不要卷入亚洲的陆战”——但鲜为人知的是:“永远不要把类型为 varchar 的列中的日期!"
  • @JoelCoehoorn 你就是喜欢这句话和电影!
  • @SM 我愿意。 :) 每次复制/粘贴相同的内容也更容易,当您需要告诉某人他们做错了时,幽默有助于减轻打击。

标签: sql sql-server tsql


【解决方案1】:

问题在于您的日期样式不一致,即(愚蠢地)存储为varchar。这就是为什么将日期存储为varchar总是是个坏主意。 真正的解决方案是修复您的设计。

你可以通过几个TRY_CONVERTs 来解决这个问题,假设你的风格总是mon dd, yyyy hh:mi:ssday, mon dd, yyyy hh:mi:ss。我正在使用样式代码109 来明确样式代码mon dd yyyy hh:mi:ss:mmmAM (or PM)(请注意,它也很乐意接受24 时钟):

SELECT ISNULL(TRY_CONVERT(datetime,V.YourString,109),TRY_CONVERT(datetime,STUFF(V.YourString,1,CHARINDEX(' ',V.YourString),''),109))
FROM (VALUES('Thursday November 12, 2020 17:01'),('Thursday November 12, 2020 07:01'),('November 12, 2020 07:01'))V(YourString)

【讨论】:

    【解决方案2】:

    与其转换成VARCHAR(已经是这样),不如直接转换成DATETIME

    除此之外,不需要所有嵌入的 REPLACE 语句 - 只需从第一个空格之后的字符串中获取所有文本。

    试试这个代码:

    CREATE TABLE #py_EconNext (publishedon VARCHAR(200));
    INSERT INTO #py_econNext VALUES ('Thursday November 12, 2020 07:01');
    
    select convert(datetime, RIGHT(publishedon, LEN(publishedon) - CHARINDEX(' ', publishedon))) 
     from #py_EconNext;
    
    DROP TABLE #py_EconNext;
    

    输出:

    2020-11-12 07:01:00.000
    

    编辑以下建议以使用TRY_CONVERT

    根据有用的评论建议使用TRY_CONVERT 代替CONVERT,请查看使用其他函数的等效代码:

    CREATE TABLE #py_EconNext (publishedon VARCHAR(200));
    INSERT INTO #py_econNext VALUES ('Thursday November 12, 2020 07:01'),('Not valid');
    
    select try_convert(datetime, RIGHT(publishedon, LEN(publishedon) - CHARINDEX(' ', publishedon))) 
     from #py_EconNext 
    
    DROP TABLE #py_EconNext;
    

    输出:

    2020-11-12 07:01:00.000
    NULL
    

    这得益于如果转换失败不会导致错误,而是返回NULL

    我个人的观点是,数据转换失败是一个错误,应该这样处理,但所需的解决方案最终将由 OP 概述的用例决定。

    【讨论】:

    • 我怀疑 OP 有虚假数据。这仍然会引发错误。使用 try_convert()
    • @JohnCappelletti 如果数据不符合要求不应该抛出错误吗?它适用于数据,因为 OP 表明它已格式化
    • 至少可以识别一个虚假值并将其保留为 NULL,直到它可以解决
    • @JohnCappelletti 感谢您在这种情况下的建议。我已经修改了答案以提供任一解决方案
    【解决方案3】:

    在 varchar 列中存储日期时间是个坏主意。存储数据时使用适当的列类型。

    考虑到您的问题,我假设 CR、LF 或 CR+LF 等数据中包含无效字符。

    尝试将它们替换为

    SELECT REPLACE(REPLACE(@str, CHAR(13), ''), CHAR(10), '')
    

    【讨论】:

    • 是的,由于字符串中包含特殊字符,它会出错。更换后它开始工作。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-17
    • 2017-12-07
    相关资源
    最近更新 更多