【问题标题】:Varchar to Datetime in TSQLSQL中的Varchar到日期时间
【发布时间】:2020-04-06 11:19:55
【问题描述】:

如何转换存储的日期和时间值

20200406151341

到 DATETIME 值 2020/04/06 15:31:41 (YYYY/MM/DD HH:MM:SS.000)?我找不到合适的 CONVERT() 格式,目前唯一的方法是解析 VARCHAR,如下所示。

select dateadd(second, cast(substring('20200406151341',13,2) as int),dateadd(minute, cast(substring('20200406151341',11,2) as int), dateadd(hour,cast(substring('20200406151341',9,2) as int),convert(datetime, left('20200406151341',8), 112)))).

它可以工作,但很难阅读和理解,尤其是当我必须在 SELECT 语句中多次使用它时。

我也很惊讶上述转换的查询与直接以 DATETIME 格式存储日期的查询一样快。 MSSQL 服务器是否使用某种缓存,所以它必须每行只进行一次转换?

我使用 MSSQL Server 2016。

【问题讨论】:

  • 保留您的substrings,但将它们放在datetimefromparts 中。 I am surprised query with above conversions is as fast - 找到行后在最终选择中计算标量非常快。
  • 最好的办法是将日期时间值存储为数据时间数据类型。如果您无法更改结构,那么我建议您在表中创建一个计算列。
  • 或使用视图 - 并准备处理无法转换的值。当架构没有得到太多考虑时,就会发生这种情况。

标签: sql sql-server tsql type-conversion


【解决方案1】:

我认为没有内置的简单方法可以做到这一点。

您无需前往seconds 即可执行此操作。您可以轻松地将前 8 个字符转换为日期。通过一些字符串操作,您可以将最后六个转换为时间——然后添加时间(作为datetime 值):

select convert(datetime, left(dt, 8)) + convert(datetime, stuff(stuff(right(dt, 6), 5, 0, ':'), 3, 0, ':'))
from (values ('20200406151341')) v(dt);

您也可以使用算术而不是 3 dateadd()s:

select dateadd(second,
               right(dt, 2) + 60*substring(dt, 11, 2) + 60*60*substring(dt, 9, 2),
               convert(datetime, left(dt, 8)))
from (values ('20200406151341')) v(dt)

注意:这使用从字符串到整数的隐式转换(与您的版本一样)。

【讨论】:

  • 谢谢你的东西是路要走,我也喜欢算术版
【解决方案2】:

您可以使用stuff()

select convert(datetime, 
               stuff(stuff(stuff(stuff(col, 9, 0, ' '), 10, 0, ''), 12, 0, ':'), 15, 0, ':'
              )

【讨论】:

    【解决方案3】:

    让我们添加更多选项:

    DECLARE @StrDate varchar(14) = '20200406151341'
    
    SELECT  DATETIMEFROMPARTS(
                LEFT(@StrDate, 4), -- year
                SUBSTRING(@StrDate, 5, 2), -- month
                SUBSTRING(@StrDate, 7, 2), -- day
                SUBSTRING(@StrDate, 9, 2), -- hour
                SUBSTRING(@StrDate, 11, 2), -- minute
                SUBSTRING(@StrDate, 13, 2), -- second
                0 -- millisecond
            ) As [Using DateTimeFromParst],
    
            CONVERT(DateTime, LEFT(@StrDate, 8), 112) + -- Date
            CONVERT(DateTime, STUFF(STUFF(RIGHT(@StrDate, 6), 5, 0, ':'), 3, 0, ':'), 114) -- Time
            As [Using convert and stuff]
    

    结果:

    Using DateTimeFromParst     Using convert and stuff
    2020-04-06 15:13:41         2020-04-06 15:13:41
    

    【讨论】:

      【解决方案4】:

      我建议使用try_convert()try_cast() 以防您的字符串无效,如果无效,它们将返回NULL 而不是引发错误。有关这些功能的更多详细信息,请参阅链接。

      declare @val varchar(20) 
      set @val = '20200416151341'
      
      select try_convert(datetime, 
                 stuff(stuff(stuff(stuff(@val, 9, 0, ' '), 10, 0, ''), 12, 0, ':'), 15, 0, ':')
                    );
      
      
      select try_cast(
                 stuff(stuff(stuff(stuff(@val, 9, 0, ' '), 10, 0, ''), 12, 0, ':'), 15, 0, ':')
                    as datetime);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-09-19
        • 2016-05-11
        • 1970-01-01
        • 1970-01-01
        • 2019-03-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多