En SQL Server 2012 y versiones posteriores, puede usar TRY_CONVERT para verificar si la entrada se puede convertir. Si no puede, se devuelve un valor NULL para que pueda hacer una COALESCE para obtener el valor convertido o la fecha fija.
begin
declare @result date
set @result = COALESCE(TRY_CONVERT(date, @date, 111), '2012-01-01')
return @result
end
También puede usar un TRY CATCH
bloque y devolver la fecha fija en el CATCH
bloque, pero es una buena práctica usar TRY_CONVERT para que SQL Server no tenga que manejar un error, ya que requiere más tiempo y recursos.
Una función para este tipo de código generará más sobrecarga que simplemente usar la misma lógica en la consulta, por lo tanto, si se llama muchas veces por segundo, puede absorber un recurso significativo al usar una función para ello. Entiendo que esto se puede invocar desde numerosas piezas de código, por lo que existe el deseo de que sea una función en caso de que la fecha predeterminada deba cambiarse; entonces no se trata de cambios en el código compilado y solo actualice esta función.
Si este código se va a ejecutar mucho, debe considerar otras opciones que proporcionarán un mejor rendimiento que una función definida por el usuario. Consulte la respuesta de Salomón para obtener una descripción general de sus opciones y una explicación más detallada de por qué podría elegir una sobre la otra.
Por ejemplo, a continuación se muestra la misma lógica implementada como una función en línea con valores de tabla, que debe usarse CROSS APPLY
si no se proporciona un valor estático, pero funciona mucho mejor que un UDF escalar:
USE [tempdb];
GO
CREATE
OR ALTER -- comment out if using pre-SQL Server 2016 SP1
FUNCTION dbo.ReturnDate (@Date VARCHAR(8))
RETURNS TABLE
AS RETURN
SELECT ISNULL(TRY_CONVERT(DATE, @Date, 111), '2020-01-01') AS [TheDate];
GO
SELECT *
FROM (VALUES (1, '20120101'), (2, '2012ABCD')) tab(ID, Input)
CROSS APPLY dbo.ReturnDate(tab.[Input]) dt
/*
ID Input TheDate
1 20120101 2012-01-01
2 2012ABCD 2020-01-01
*/