La mejor forma de convertir y validar una cadena de fecha

Tengo una sola variable char (8) formateada como ddmmyyyy en un procedimiento almacenado (la calidad y la validez de este valor son desconocidas y están fuera de mi control). ¿Cuál es la mejor manera más eficiente de mover el valor a una variable de fecha y hora y lanzar un error si no es una fecha válida?

DECLARE @Source char(8) DECLARE @Destination datetime SET @Source='07152009' --your solution here SELECT @Destination 

aquí está la mejor manera en que podría pensar:

 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 

EDITAR esto es lo que voy a hacer con …

 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 

En primer lugar, dado que está usando SQL Server 2005, debe poner su código que podría fallar en BEGIN TRY.....END TRY BEGIN CATCH....END CATCH blocks – try / catch blocks for T-SQL!

En segundo lugar, para la manipulación de todas las fechas, siempre usaría el formato ISO-8601, que funcionará independientemente del formato de fecha actual establecido en SQL Server.

El formato ISO-8601 es YYYYMMDD solo para las fechas, o YYYY-MM-DDTHH:MM:SS para la fecha y hora, así que escribiría su código como:

 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 

¡No confíe en ningún formato de fecha en particular! Envíame tu código y lo probaré en un sistema suizo-alemán. Casi garantizo que se romperá si asumes ciegamente “en-US” y por lo tanto “mm / dd / aaaa”. No es el mismo ajuste en todas partes. este planeta

Desafortunadamente, SQL Server tiene fechas de gestión bastante débiles. ¿Tal vez podría ser un punto de extensión en el que usar un ensamblado CLR dentro de SQL Server tendría sentido para aprovechar las funciones de manejo de fechas mucho más ricas en .NET?

Bagazo

PD: parece que el formato ISO-8601 que sabía YYYY-MM-DD no siempre funciona en SQL Server, al contrario de lo que parecen predicar los Libros en pantalla. Use AAAAMMDD o AAAA-MM-DDTHH: MM: SS en su lugar.
Gracias, gbn!

Puede garantizar el orden de fecha-mes-año usando SET DATEFORMAT. Esto significa que ISDATE analizará ’15 -07-2009 ‘como el 15 de julio de 2009

De lo contrario, su enfoque es lo suficientemente bueno dadas las limitaciones externas … pero también podría reordenarlo a ANSI / ISO.

Después de la respuesta de marc_s: “SET DATEFORMAT dmy” funciona para la mayoría de los entornos europeos …

DE ACUERDO:

 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