在TSQL中从Varchar到Datetime
如何转换存储的日期和时间值 20200406151341 截止日期时间值2020/04/06 15:31:41 YYYY/MM/DD HH:MM:SS.000?我无法找到合适的转换格式,到目前为止,唯一的方法是像下面这样解析VARCHAR在TSQL中从Varchar到Datetime,sql,sql-server,tsql,type-conversion,Sql,Sql Server,Tsql,Type Conversion,如何转换存储的日期和时间值 20200406151341 截止日期时间值2020/04/06 15:31:41 YYYY/MM/DD HH:MM:SS.000?我无法找到合适的转换格式,到目前为止,唯一的方法是像下面这样解析VARCHAR select dateadd(second, cast(substring('20200406151341',13,2) as int),dateadd(minute, cast(substring('20200406151341',11,2) as int)
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。我认为没有一种内置的简单方法可以做到这一点 你不必到几秒钟就可以做到这一点。您可以轻松地将前8个字符转换为日期。通过一些字符串操作,您可以将最后六个转换为时间,然后将时间添加为日期时间值: 您也可以使用算术而不是3个日期相加: 注意:这与您的版本一样使用从字符串到整数的隐式转换。您可以使用stuff:
让我们在组合中加入更多选项:
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
我建议在字符串无效的情况下使用or,如果无效,它们将返回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);
保留子字符串,但将它们放在一个文件夹中。我很惊讶上面转换的查询速度如此之快——在找到行之后,在最终选择中计算标量的速度非常快。最好的方法是使用datatime数据类型存储datetime值。如果您不能更改结构,那么我建议在表中创建一个计算列,或者使用视图,并准备好处理无法转换的值。这就是当模式没有被考虑太多的时候会发生的事情。谢谢你,这是一个好办法,我也喜欢算术版本
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
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);