Лучший способ конвертировать и проверять строку даты
У меня есть одна переменная 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 ответа
Прежде всего, поскольку вы используете SQL Server 2005, вы должны поместить свой код, который может потерпеть неудачу в BEGIN TRY.....END TRY BEGIN CATCH....END CATCH
blocks - пробовать / ловить блоки для 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" и, следовательно, "mm/dd/yyyy" - это не везде одинаковая настройка эта планета.
К сожалению, SQL Server довольно слабо обрабатывает даты - может быть, это может быть точкой расширения, где было бы целесообразно использовать сборку CLR внутри SQL Server, чтобы использовать гораздо более богатые функции обработки дат в.NET?
Марк
PS: кажется, что формат ISO-8601, который я знал, YYYY-MM-DD не всегда работает в SQL Server - вопреки тому, что, похоже, проповедует Books Online. Вместо этого используйте ГГГГММДД или ГГГГ-ММ-ДДТЧ: ММ: СС.
Спасибо, ГБН!
Вы можете гарантировать дату-месяц-год, используя SET DATEFORMAT. Это означает, что ISDATE проанализирует "15-07-2009" как 15 июля 2009
В противном случае ваш подход достаточно хорош, учитывая внешние ограничения... но вы также можете изменить порядок в ANSI/ISO.
После ответа marc_s: "SET DATEFORMAT dmy" работает для большинства европейских настроек...
ХОРОШО:
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