chức năng nhận định dạng ngày nhập và ký tự (với đầu vào không chính xác)


9

Tôi cần phải viết một hàm để nhận một ký tự chuỗi và trả về định dạng ngày. Ví dụ đầu vào là 20120101 và tôi cần 2012-01-01 này. Vấn đề là có thể có một số đầu vào không chính xác như "2012ABCD" này. Trong trường hợp đó, tôi muốn hàm trả về một ngày cố định, chẳng hạn như 2020-01-01. Những gì tôi đã viết cho đến nay là:

Create Function ReturnDate
(@date varchar(8))

Returns date

  as

    begin
       declare @result date

          set @result = (select convert(date , @date,111))
                if(@@ROWCOUNT>0) return @result
                 else return '2020-01-01'
       return @result
    end

Điều này không hoạt động và tôi chỉ không biết cách xử lý phần thứ hai (khi đầu vào không chính xác).


1
Tôi có thể khuyên bạn nên đọc "Truy vấn dữ liệu bằng Transact-SQL" Nếu bạn sẽ thực hiện nhiều chương trình SQL, cuốn sách này sẽ dạy cho bạn những điều cơ bản về cách mã hóa những thứ như thế này. amazon.com/Exam-70-761-Querying-Data-Transact-Query-ebook/dp/ mẹo
Tony Hinkle

1
Bạn có muốn phân tích cú pháp nghiêm ngặt cho yyyymmddđịnh dạng?
Dan Guzman

Câu trả lời:


9

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 CATCHkhối và trả về ngày cố định trong CATCHkhố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 APPLYnế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
*/

6
Nhưng tôi sẽ chỉ sử dụng TRY_CONVERT trong truy vấn và loại bỏ toàn bộ ý tưởng sử dụng UDF vô hướng không hiệu quả cho việc này ...
Aaron Bertrand

2
Tôi không thực sự quan tâm đến các điểm đại diện, vì vậy tôi không nói là do mất như vậy, nhưng cộng đồng không được hưởng lợi từ việc hạ thấp một câu trả lời rõ ràng chính xác. Thay vì tải xuống, hãy viết câu trả lời, chỉnh sửa của tôi hoặc để lại nhận xét về những gì cần thay đổi. OP đã yêu cầu một chức năng và tôi nhận ra rằng đó có thể không phải là giải pháp tốt nhất, nhưng đó là giải pháp được yêu cầu.
Tony Hinkle

3
Tony: Tôi đã không bỏ phiếu, nhưng tôi chắc chắn đồng ý rằng ai đó không nên bỏ phiếu mà không đưa ra lý do trong một bình luận, hoặc bỏ phiếu cho một bình luận hiện có bao gồm cả lý lẽ của họ. Điều đó nói rằng: 1) không có FINALLYkhối trong T-SQL (tôi nghĩ ý bạn là vậy CATCH). 2) có lẽ bạn nên đề cập đến việc TRY_CONVERTbắt đầu vào năm 2012 (một số người bị mắc kẹt trước SQL Server 2012). 3) bạn đã xem TVF nội tuyến chưa? Những người không có vấn đề về hiệu suất tương tự như UDF vô hướng.
Solomon Rutzky

1
@TonyHinkle Cảm ơn bạn đã thực hiện các chỉnh sửa đó và để tham khảo câu trả lời SO của tôi :). Tuy nhiên, tôi không chắc có bao nhiêu độc giả sẽ có thể thực hiện bước nhảy vọt khi thấy logic UDF và đọc rằng một TVF nội tuyến sẽ tốt hơn, để thực hiện thành công iTVF. Vì vậy, tôi đã đi trước và thêm nó vào cuối câu trả lời của bạn.
Solomon Rutzky

1
@SolomonRutzky Cảm ơn. Tôi không thực sự là một nhà phát triển SQL vì vậy nó vẫn ở trên đầu tôi. Có lẽ tôi không nên trả lời như thế này, nhưng đó là một cơ hội học tập tuyệt vời.
Tony Hinkle
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.