ฟังก์ชั่นเพื่อรับอินพุตอักขระและรูปแบบวันที่ส่งคืน (ที่มีอินพุตไม่ถูกต้อง)


9

ฉันต้องเขียนฟังก์ชั่นเพื่อรับตัวอักษรสตริงและกลับรูปแบบวันที่ ตัวอย่างเช่นการป้อนข้อมูลคือ 20120101 และฉันต้องการสิ่งนี้ 2012-01-01 ปัญหาคืออาจมีอินพุตที่ไม่ถูกต้องเช่น "2012ABCD" นี้ ในกรณีนั้นฉันต้องการให้ฟังก์ชันส่งคืนวันที่ที่แน่นอนเช่น 2020-01-01 สิ่งที่ฉันเขียนจนถึงตอนนี้คือ:

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

ไม่ทำงานและฉันไม่รู้วิธีจัดการส่วนที่สอง (เมื่ออินพุตไม่ถูกต้อง)


1
ฉันอาจแนะนำให้คุณอ่าน "Querying Data with Transact-SQL" หากคุณจะทำการเขียนโปรแกรม SQL จำนวนมากหนังสือเล่มนี้จะสอนคุณเกี่ยวกับวิธีการเขียนโค้ดสิ่งนี้ amazon.com/Exam-70-761-Querying-Data-Transact-SQL-ebook/dp/ …
Tony Hinkle

1
คุณต้องการแยกวิเคราะห์อย่างเข้มงวดสำหรับyyyymmddรูปแบบ?
Dan Guzman

คำตอบ:


9

บน 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
*/

6
แต่ผมก็จะใช้ TRY_CONVERT ในการสอบถามและทิ้งความคิดทั้งหมดของการใช้ UDF เกลาไม่มีประสิทธิภาพนี้ ...
แอรอนเบอร์ทรานด์

2
ฉันไม่สนใจเกี่ยวกับประเด็นของตัวแทนดังนั้นฉันจึงไม่ได้พูดเพราะสูญเสียสิ่งเหล่านี้ แต่ชุมชนไม่ได้รับประโยชน์จากการลดลงของคำตอบที่ถูกต้องชัดเจน แทนการ downvoting เขียนคำตอบแก้ไขของฉันหรือแสดงความคิดเห็นในสิ่งที่จำเป็นต้องเปลี่ยน OP ขอฟังก์ชั่นและฉันรู้ว่าอาจไม่ใช่ทางออกที่ดีที่สุด แต่เป็นวิธีการแก้ปัญหาที่ถูกร้องขอ
Tony Hinkle

3
โทนี่: ฉันไม่ได้ลงคะแนน แต่ฉันเห็นด้วยอย่างแน่นอนว่าบางคนไม่ควรลงคะแนนโดยไม่ได้ให้เหตุผลในการแสดงความคิดเห็นหรือโหวตความคิดเห็นที่มีอยู่ซึ่งรวมถึงการให้เหตุผลของพวกเขา ที่กล่าวว่า: 1)ไม่มีFINALLYบล็อกใน T-SQL (ฉันคิดว่าคุณหมายถึงCATCH) 2)คุณควรพูดถึงว่าTRY_CONVERTเริ่มในปี 2012 (บางคนติดอยู่กับ pre-SQL Server 2012) 3)คุณได้พิจารณา Inline TVF หรือไม่ สิ่งเหล่านั้นไม่มีปัญหาด้านประสิทธิภาพเช่นเดียวกับ Scalar UDF
โซโลมอน Rutzky

1
@ TonyHinkle ขอบคุณสำหรับการแก้ไขเหล่านั้นและสำหรับการอ้างอิงถึงคำตอบ SO ของฉัน :) ถึงกระนั้นฉันก็ยังไม่แน่ใจว่าผู้อ่านจะสามารถก้าวกระโดดจากการมองเห็นตรรกะของ UDF และการอ่านที่ inline TVF จะดีขึ้นเพื่อนำ iTVF ไปใช้งานได้สำเร็จ ดังนั้นฉันจึงไปข้างหน้าและเพิ่มคำตอบของคุณ
โซโลมอน Rutzky

1
@SolomonRutzky ขอบคุณ ฉันไม่ใช่นักพัฒนา SQL จริง ๆ ดังนั้นจึงยังคงอยู่เหนือหัวของฉัน บางทีฉันไม่ควรตอบอะไรแบบนี้ แต่มันเป็นโอกาสการเรียนรู้ที่ยิ่งใหญ่
Tony Hinkle
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.