karakter girişi ve dönüş tarihi biçimini alma işlevi (yanlış girişle)


9

Bir dize karakter almak ve tarih biçimini döndürmek için bir işlev yazmak gerekiyor. Örneğin giriş 20120101 ve ben bu 2012-01-01 gerekir. Sorun şu "2012ABCD" gibi bazı yanlış girişler olabilir. Bu durumda, işlevin 2020-01-01 gibi sabit bir tarih döndürmesini istiyorum. Şimdiye kadar yazdım:

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

Bu işe yaramaz ve sadece ikinci kısmı (giriş yanlış olduğunda) nasıl kullanacağımı bilmiyorum.


1
Ben "Transact-SQL ile veri sorgulama" okumanızı tavsiye ederim Eğer SQL programlama çok yapacak, bu kitap size böyle şeyler kodlamak için temelleri öğretecektir. amazon.com/Exam-70-761-Querying mevcuttur
Tony Hinkle

1
yyyymmddBiçim için katı ayrıştırma yapmak istiyor musunuz ?
Dan Guzman

Yanıtlar:


9

SQL Server 2012 ve sonraki sürümlerde girdinin dönüştürülebilir olup olmadığını kontrol etmek için TRY_CONVERT kullanabilirsiniz . Bu yapılamazsa, NULL değeri döndürülür, böylece dönüştürülen değeri veya sabit tarihi almak için bir COALESCE yapabilirsiniz.

begin
   declare @result date
   set @result = COALESCE(TRY_CONVERT(date, @date, 111), '2012-01-01')
   return @result
end

Ayrıca bir TRY CATCHblok kullanabilir ve blokta sabit tarihi döndürebilirsiniz CATCH, ancak en iyi uygulama TRY_CONVERT kullanmaktır, böylece SQL Server daha fazla zaman ve kaynak gerektirdiği için bir hatayı işlemek zorunda kalmaz.

Bu tür bir kod için bir işlev, sorguda aynı mantığı kullanmaktan daha fazla yüke neden olur, bu nedenle her saniye birçok kez çağrılırsa, bunun için bir işlev kullanarak önemli kaynakları çiğneyebilirsiniz. Bu, çok sayıda kod parçasından çağrılabilir, bu nedenle varsayılan tarihin değiştirilmesi gerektiğinde bir işlev yapma arzusu olduğunu anlıyorum - o zaman derlenmiş kod değişikliği yok ve sadece bu işlevi güncelleyin.

Bu kod çok çalıştırılacaksa, kullanıcı tanımlı bir işlevden daha iyi performans sağlayacak diğer seçenekleri göz önünde bulundurmalısınız. Seçeneklerinize genel bir bakış ve neden birini diğerine tercih edebileceğinizle ilgili daha fazla açıklama için lütfen Solomon'un cevabına bakın .

Örneğin, aşağıda, CROSS APPLYstatik bir değer sağlanmadığı takdirde kullanılması gereken , ancak skaler UDF'den çok daha iyi performans gösteren satır içi tablo değerli bir işlev olarak uygulanan aynı mantık gösterilmektedir :

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
Ama ben sadece sorguda TRY_CONVERT kullanın ve bunun için verimsiz bir skaler UDF kullanma fikrini atın ...
Aaron Bertrand

2
Temsil puanlarını gerçekten umursamıyorum, bu yüzden böyle bir kayıp nedeniyle söylemiyorum, ancak topluluk açıkça doğru bir cevabı küçümsemekten fayda görmüyor. Aşağı indirmek yerine, bir cevap yazın, benimkini düzenleyin veya neyin değiştirilmesi gerektiğine dair bir yorum bırakın. OP bir işlev istedi ve bunun en iyi çözüm olmayabileceğini fark ettim, ancak istenen çözüm bu.
Tony Hinkle

3
Tony: Ben aşağı oy vermedim, ama kesinlikle bir yorumda gerekçe sunmadan ya da gerekçelerini içeren mevcut bir yorumu yukarı oylamadan birinin aşağı oy kullanmaması gerektiğine katılıyorum. Dedi ki: 1)FINALLY T-SQL'de bir blok yok (demek istediğini düşünüyorum CATCH). 2) muhtemelen TRY_CONVERT2012'de başladığını belirtmelisiniz (bazı insanlar SQL Server 2012 öncesi sıkışmış). 3) Inline TVF'yi düşündünüz mü? Bunlar Skaler UDF'lerle aynı performans sorunlarına sahip değildir.
Solomon Rutzky

1
@TonyHinkle Bu düzenlemeleri yaptığınız ve SO cevabıma referans için teşekkürler :). Yine de, kaç okuyucunun UDF mantığını görmekten ve bir satır içi TVF'nin daha iyi olacağını okumaktan İTVF'yi başarıyla uygulamak için sıçrama yapabileceğinden emin değilim. Bu yüzden devam ettim ve cevabınızın sonuna ekledim.
Solomon Rutzky

1
@SolomonRutzky Teşekkürler. Gerçekten bir SQL geliştiricisi değilim, bu yüzden hala başımın üstünde. Belki böyle bir şeye cevap vermemeliyim, ama bu muazzam bir öğrenme fırsatı.
Tony Hinkle
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.