лучший способ конвертировать и проверять строку даты - PullRequest
11 голосов
/ 16 июля 2009

У меня есть одна переменная char (8), отформатированная в виде хранимой процедуры как ddmmyyyy (качество и достоверность этого значения неизвестны и находятся вне моего контроля). Каков наилучший и наиболее эффективный способ переместить значение в переменную datetime и выдать ошибку, если она недопустима для datetime.

DECLARE @Source       char(8)
DECLARE @Destination  datetime

SET @Source='07152009'

--your solution here


SELECT @Destination

вот лучший способ, которым я мог придумать:

DECLARE @Source             char(8)
DECLARE @Temp               varchar(10)
DECLARE @Destination        datetime

set @Source='07152009'
SET @Temp=LEFT(@Source,2)+'/'+SUBSTRING(@Source,3,2)+'/'+RIGHT(@Source,4)

IF ISDATE(@Temp)!=1
BEGIN
    RAISERROR('ERROR, invalid date',16,1)
END
SET @Destination=@Temp

SELECT @Source AS Source, @Temp AS  Temp, @Destination AS Destination

РЕДАКТИРОВАТЬ вот что я собираюсь пойти с ...

DECLARE @Source             char(8)
DECLARE @Destination        datetime

set @Source='07152009'
BEGIN TRY
    SET @Destination=CONVERT(datetime,RIGHT(@Source,4)        -- YYYY
                                      +LEFT(@Source,2)        -- MM
                                      +SUBSTRING(@Source,3,2) -- DD
                             )
END TRY
BEGIN CATCH
    PRINT 'ERROR!!!' --I'll add a little more logic here and abort processing
END CATCH

SELECT @Source AS Source, @Destination AS Destination

Ответы [ 2 ]

12 голосов
/ 16 июля 2009

Прежде всего, поскольку вы используете SQL Server 2005, вы должны поместить свой код, который может потерпеть неудачу, в блоки BEGIN TRY.....END TRY BEGIN CATCH....END CATCH - попробуйте / перехватите блоки для T-SQL!

Во-вторых, для всех манипуляций с датами я бы всегда использовал формат ISO-8601 , который будет работать независимо от того, какой текущий формат даты установлен в SQL Server.

Формат ISO-8601: YYYYMMDD только для дат или YYYY-MM-DDTHH:MM:SS для даты и времени - поэтому я написал бы ваш код следующим образом:

BEGIN TRY
  SET @Source='07152009'
  SET @Temp = RIGHT(@Source, 4) +             -- YYYY
              LEFT(@Source, 2) +              -- MM
              SUBSTRING(@Source, 3, 2)        -- DD

  IF ISDATE(@Temp)!=1
  BEGIN
      RAISERROR('ERROR, invalid date',16,1)
  END

  SET @Destination = CAST(@Temp AS DATETIME)
END TRY
BEGIN CATCH
      -- handle error if something bombs out
END CATCH

Не полагайтесь на установленный формат даты! Отправьте мне свой код, и я попробую его на швейцарско-немецкой системе - я почти гарантирую, что он сломается, если вы слепо примете «en-US» и, следовательно, «мм / дд / гггг» - это не одинаковые настройки повсюду на этой планете.

К сожалению, SQL Server довольно слабо обрабатывает даты - может быть, это может быть точкой расширения, где использование CLR-сборки внутри SQL Server имеет смысл, чтобы использовать гораздо более богатые функции обработки дат в .NET ??

Марк

PS: кажется, что формат ISO-8601, который я знал, YYYY-MM-DD не всегда работает в SQL Server - вопреки тому, что, похоже, проповедует Books Online. Вместо этого используйте ГГГГММДД или ГГГГ-ММ-ДДТЧ: ММ: СС.
Спасибо, ГБН!

6 голосов
/ 16 июля 2009

Вы можете гарантировать порядок даты-месяца-года, используя SET DATEFORMAT. Это означает, что ISDATE будет анализировать '15 -07-2009 'как 15 июля 2009

В противном случае ваш подход достаточно хорош, учитывая внешние ограничения ... но вы также можете изменить порядок в ANSI / ISO.

После ответа marc_s: "SET DATEFORMAT dmy" работает для большинства европейских настроек ...

OK:

SET LANGUAGE british
SELECT ISDATE('2009-07-15') --this is ansi says marc_s. It gives "zero"
SELECT ISDATE('2009-07-15T11:22:33') --this really is ANSI and gives true


SET LANGUAGE german
SELECT ISDATE('2009-07-15') --false
SELECT ISDATE('2009-07-15T11:22:33') --true
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...