На SQL Server 2012 та пізніших версіях ви можете використовувати TRY_CONVERT, щоб перевірити, чи можна перетворити вхід. Якщо це не вдається, повертається значення NULL, тож ви можете зробити COALESCE, щоб отримати перетворене значення або фіксовану дату.
begin
declare @result date
set @result = COALESCE(TRY_CONVERT(date, @date, 111), '2012-01-01')
return @result
end
Ви також можете використовувати TRY CATCH
блок і повернути фіксовану дату в CATCH
блоці, але найкраще використовувати TRY_CONVERT, щоб SQL Server не мав обробляти помилку, оскільки для цього потрібно більше часу та ресурсів.
Функція для цього типу коду матиме більше накладних витрат, ніж просто використання однієї і тієї ж логіки у запиті, тому, якщо вона викликається багато разів щосекунди, ви можете жувати значний ресурс, використовуючи функцію для цього. Я розумію, що це може бути викликано з численних фрагментів коду, тому є бажання зробити його функцією у випадку, якщо дату за замовчуванням потрібно змінити - тоді це не змінений код, а просто оновіть цю функцію.
Якщо цей код буде запускатися багато, слід розглянути інші варіанти, які забезпечать кращу продуктивність, ніж визначена користувачем функція. Будь ласка, дивіться відповідь Соломона для огляду ваших варіантів та подальшого пояснення, чому ви можете вибрати один над іншим.
Наприклад, нижче показано таку ж логіку, що реалізована як функція вбудованої таблиці, яка має бути використана, CROSS APPLY
якщо вона не надається статичним значенням, але працює набагато краще, ніж скалярний UDF:
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
*/