Преобразование строки Sql Server в дату

Я хочу преобразовать строку следующим образом:

'10/15/2008 10:06:32 PM'

в эквивалентное значение DATETIME в Sql Server.

в Oracle, я бы сказал так:

TO_DATE('10/15/2008 10:06:32 PM','MM/DD/YYYY HH:MI:SS AM')

этот вопрос подразумевает, что я должен разобрать строку в одну из стандартные форматы, а затем преобразовать с помощью одного из этих кодов. Это кажется нелепым для такой мирской операции. Есть ли более простой способ?

10 ответов


SQL Server (2005, 2000, 7.0) не имеет гибкого или даже не гибкого способа получения произвольно структурированного datetime в строковом формате и преобразования его в тип данных datetime.


попробуй такое

Cast('7/7/2011' as datetime)

и

Convert(varchar(30),'7/7/2011',102)

посмотреть приведение и преобразование (Transact-SQL) для получения более подробной информации.


запустите это через процессор запросов. Это форматы даты и/или времени так и один из них должен дать вам то, что вы ищете. Это не будет трудно адаптироваться:

Declare @d datetime
select @d = getdate()

select @d as OriginalDate,
convert(varchar,@d,100) as ConvertedDate,
100 as FormatValue,
'mon dd yyyy hh:miAM (or PM)' as OutputFormat
union all
select @d,convert(varchar,@d,101),101,'mm/dd/yy'
union all
select @d,convert(varchar,@d,102),102,'yy.mm.dd'
union all
select @d,convert(varchar,@d,103),103,'dd/mm/yy'
union all
select @d,convert(varchar,@d,104),104,'dd.mm.yy'
union all
select @d,convert(varchar,@d,105),105,'dd-mm-yy'
union all
select @d,convert(varchar,@d,106),106,'dd mon yy'
union all
select @d,convert(varchar,@d,107),107,'Mon dd, yy'
union all
select @d,convert(varchar,@d,108),108,'hh:mm:ss'
union all
select @d,convert(varchar,@d,109),109,'mon dd yyyy hh:mi:ss:mmmAM (or PM)'
union all
select @d,convert(varchar,@d,110),110,'mm-dd-yy'
union all
select @d,convert(varchar,@d,111),111,'yy/mm/dd'
union all
select @d,convert(varchar,@d,12),12,'yymmdd'
union all
select @d,convert(varchar,@d,112),112,'yyyymmdd'
union all
select @d,convert(varchar,@d,113),113,'dd mon yyyy hh:mm:ss:mmm(24h)'
union all
select @d,convert(varchar,@d,114),114,'hh:mi:ss:mmm(24h)'
union all
select @d,convert(varchar,@d,120),120,'yyyy-mm-dd hh:mi:ss(24h)'
union all
select @d,convert(varchar,@d,121),121,'yyyy-mm-dd hh:mi:ss.mmm(24h)'
union all
select @d,convert(varchar,@d,126),126,'yyyy-mm-dd Thh:mm:ss:mmm(no spaces)'

в SQL Server Denali вы сможете сделать что-то, что приближается к тому, что вы ищете. Но вы все равно не можете просто передать произвольно определенную дурацкую строку даты и ожидать, что SQL Server будет соответствовать. Вот один пример использования того, что вы опубликовали в своем собственном ответе. Функция FORMAT () также может принимать локали в качестве необязательного аргумента - она основана на формате .Net, поэтому большинство, если не все форматы токенов, которые вы ожидаете увидеть, будут там.

DECLARE @d DATETIME = '2008-10-13 18:45:19';

-- returns Oct-13/2008 18:45:19:
SELECT FORMAT(@d, N'MMM-dd/yyyy HH:mm:ss');

-- returns NULL if the conversion fails:
SELECT TRY_PARSE(FORMAT(@d, N'MMM-dd/yyyy HH:mm:ss') AS DATETIME);

-- returns an error if the conversion fails:
SELECT PARSE(FORMAT(@d, N'MMM-dd/yyyy HH:mm:ss') AS DATETIME);

I настоятельно рекомендуем вам взять на себя больше контроля и санировать ваши входные данные даты. Дни, позволяющие людям вводить даты, используя любой формат, который они хотят в поле формы freetext, уже должны быть позади нас. Если кто-то входит в 8/9/2011, это август 9th или сентябрь 8th? Если вы заставите их выбрать дату в элементе управления календарем, приложение сможет управлять форматом. Независимо от того, насколько вы пытаетесь предсказать поведение своих пользователей, они всегда найдут более глупый способ ввести дату, которую вы не планировали для.

до Денали, хотя, я думаю, что @Ovidiu имеет лучший совет до сих пор... это может быть довольно тривиальная, реализуя свои функции CLR. Затем вы можете написать case / switch для столько дурацких нестандартных форматов, сколько хотите.


обновление для @dhergert:

SELECT TRY_PARSE('10/15/2008 10:06:32 PM' AS DATETIME USING 'en-us');
SELECT TRY_PARSE('15/10/2008 10:06:32 PM' AS DATETIME USING 'en-gb');

результаты:

2008-10-15 22:06:32.000
2008-10-15 22:06:32.000

вам все равно нужно сначала получить другую важную информацию. Вы не можете использовать собственный T-SQL для определения 6/9/2012 - это 9-е Июня или 6 сентября.


для этой проблемы лучшим решением, которое я использую, является функция CLR в Sql Server 2005, которая использует один из DateTime.Функция Parse или ParseExact возвращает значение DateTime с указанным форматом.


почему бы не попробовать

select convert(date,'10/15/2011 00:00:00',104) as [MM/dd/YYYY]

форматы даты можно найти в помощник SQL Server > форматы даты SQL Server


этой страница имеет некоторые ссылки для всех указанных преобразований datetime, доступных для функции CONVERT. Если ваши значения не попадают в один из приемлемых шаблонов, то я думаю, что лучше всего пойти по пути синтаксического анализа.


лично если вы имеете дело с произвольными или полностью выключенными форматами стены, при условии, что вы знаете, что они опережают время или будут, то просто используйте regexp, чтобы вытащить разделы даты, которую вы хотите, и сформировать действительный компонент даты/времени.


Если вы хотите, чтобы SQL Server попытался выяснить это, просто используйте CAST CAST ('whatever' как datetime) Однако это вообще плохая идея. Есть проблемы с международными датами, которые могут возникнуть. Таким образом, как вы обнаружили, чтобы избежать этих проблем, вы хотите использовать канонический формат ODBC даты. То есть формат № 120, 20-это формат всего лишь двухзначных лет. Я не думаю, что SQL Server имеет встроенную функцию, которая позволяет вам предоставлять пользовательский формат. Вы можете написать свой собственный и может даже найти, если поискать в интернете.


используйте этот:

SELECT convert(datetime, '2018-10-25 20:44:11.500', 121) -- yyyy-mm-dd hh:mm:ss.mmm

и обратитесь к таблице в разделе официальная документация для преобразования кодов.