Trên SQL Server 2012 trở lên, bạn có thể sử dụng TRY_CONVERT để kiểm tra xem liệu đầu vào có thể được chuyển đổi hay không. Nếu không thể, giá trị NULL được trả về, do đó bạn có thể thực hiện COALESCE để nhận giá trị được chuyển đổi hoặc ngày cố định.
begin
declare @result date
set @result = COALESCE(TRY_CONVERT(date, @date, 111), '2012-01-01')
return @result
end
Bạn cũng có thể sử dụng một TRY CATCH
khối và trả về ngày cố định trong CATCH
khối, nhưng cách tốt nhất là sử dụng TRY_CONVERT để SQL Server không phải xử lý lỗi vì cần nhiều thời gian và tài nguyên hơn.
Một hàm cho loại mã này sẽ phải chịu nhiều chi phí hơn là chỉ sử dụng cùng một logic trong truy vấn, vì vậy nếu nó được gọi nhiều lần mỗi giây, bạn có thể nhai tài nguyên quan trọng bằng cách sử dụng một hàm cho nó. Tôi hiểu rằng điều này có thể được gọi từ nhiều đoạn mã vì vậy mong muốn biến nó thành một hàm trong trường hợp ngày mặc định cần phải thay đổi - sau đó nó không thay đổi mã được biên dịch và chỉ cập nhật chức năng này.
Nếu mã này sẽ được chạy nhiều, bạn nên xem xét các tùy chọn khác sẽ cung cấp hiệu suất tốt hơn so với chức năng do người dùng xác định. Vui lòng xem câu trả lời của Solomon để biết tổng quan về các lựa chọn của bạn và giải thích thêm về lý do tại sao bạn có thể chọn cái này hơn cái kia.
Ví dụ, phần sau đây cho thấy logic tương tự được triển khai như một hàm có giá trị bảng nội tuyến, cần được sử dụng CROSS APPLY
nếu không được cung cấp với giá trị tĩnh, nhưng hoạt động tốt hơn nhiều so với UDF vô hướng:
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
*/