Varchar для Datetime в TSQL - PullRequest
       8

Varchar для Datetime в TSQL

1 голос
/ 06 апреля 2020

Как преобразовать значение даты и времени, хранящееся в виде

20200406151341

, в значение DATETIME 2020/04/06 15:31:41 (ГГГГ / ММ / ДД ЧЧ: ММ: СС.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. Использует ли сервер MS SQL какой-либо кэш, поэтому необходимо выполнять преобразование только один раз в строке?

Я использую MS SQL Server 2016.

Ответы [ 4 ]

1 голос
/ 06 апреля 2020

Вы можете использовать stuff():

select convert(datetime, 
               stuff(stuff(stuff(stuff(col, 9, 0, ' '), 10, 0, ''), 12, 0, ':'), 15, 0, ':'
              )
1 голос
/ 06 апреля 2020

Я не думаю, что есть встроенный, простой способ сделать это.

Вам не нужно go до second с, чтобы сделать это. Вы можете легко конвертировать первые 8 символов в дату. С помощью некоторых манипуляций со строками вы можете преобразовать последние шесть в время, а затем добавить время (как datetime значения):

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

Вы также можете использовать арифмети c вместо 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)

Примечание. При этом используется неявное преобразование строки в целое число (как и в вашей версии).

0 голосов
/ 07 апреля 2020

Я предлагаю использовать 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);
0 голосов
/ 06 апреля 2020

Давайте добавим еще пару опций к миксу:

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
...