berfungsi untuk menerima input karakter dan format tanggal kembali (dengan input yang salah)

9

Saya perlu menulis fungsi untuk menerima karakter string dan mengembalikan format tanggal. Misalnya inputnya adalah 20120101 dan saya perlu 2012-01-01 ini. Masalahnya adalah bahwa mungkin ada beberapa input yang salah seperti "2012ABCD" ini. Dalam hal ini, saya ingin fungsi mengembalikan tanggal tetap seperti 2020-01-01. Apa yang saya tulis sejauh ini adalah:

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

Ini tidak berfungsi dan saya tidak tahu bagaimana menangani bagian kedua (ketika input salah).

Pantea Tourang
sumber
1
Saya mungkin menyarankan Anda membaca "Meminta Data dengan Transact-SQL" Jika Anda akan melakukan banyak pemrograman SQL, buku ini akan mengajarkan Anda dasar-dasar cara membuat kode seperti ini. amazon.com/Exam-70-761-Querying-Data-Transact-SQL-ebook/dp/…
Tony Hinkle
1
Apakah Anda ingin parsing ketat untuk yyyymmddformat?
Dan Guzman

Jawaban:

9

Pada SQL Server 2012 dan yang lebih baru Anda dapat menggunakan TRY_CONVERT untuk memeriksa untuk melihat apakah input dapat dikonversi. Jika tidak, nilai NULL dikembalikan sehingga Anda dapat melakukan COALESCE untuk mendapatkan nilai yang dikonversi atau tanggal tetap.

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

Anda juga bisa menggunakan TRY CATCHblok dan mengembalikan tanggal tetap di CATCHblok, tetapi praktik terbaik untuk menggunakan TRY_CONVERT sehingga SQL Server tidak harus menangani kesalahan karena membutuhkan lebih banyak waktu dan sumber daya.

Suatu fungsi untuk jenis kode ini akan menimbulkan lebih banyak overhead daripada hanya menggunakan logika yang sama dalam kueri, jadi jika itu dipanggil berkali-kali setiap detik Anda mungkin mengunyah sumber daya yang signifikan dengan menggunakan fungsi untuknya. Saya mengerti bahwa ini dapat dipanggil dari berbagai bagian kode sehingga ada keinginan untuk menjadikannya fungsi jika tanggal default perlu diubah - maka tidak ada perubahan kode yang dikompilasi dan perbarui saja fungsi ini.

Jika kode ini akan banyak berjalan, Anda harus mempertimbangkan opsi lain yang akan memberikan kinerja yang lebih baik daripada fungsi yang ditentukan pengguna. Silakan lihat jawaban Solomon untuk ikhtisar opsi Anda dan penjelasan lebih lanjut mengapa Anda memilih satu di atas yang lain.

Sebagai contoh, berikut ini menunjukkan logika yang sama diimplementasikan sebagai fungsi bernilai tabel inline, yang perlu digunakan CROSS APPLYjika tidak disertakan dengan nilai statis, tetapi berkinerja jauh lebih baik daripada skalar 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
*/
Tony Hinkle
sumber
6
Tapi saya hanya akan menggunakan TRY_CONVERT dalam kueri dan membuang seluruh gagasan untuk menggunakan skalar UDF yang tidak efisien untuk ini ...
Aaron Bertrand
2
Saya tidak terlalu peduli dengan poin rep, jadi saya tidak mengatakannya karena kehilangan hal seperti itu, tetapi masyarakat tidak mendapat manfaat dari downvoting jawaban yang jelas benar. Alih-alih downvoting, tulis jawaban, edit milikku, atau tinggalkan komentar tentang apa yang perlu diubah. OP meminta fungsi, dan saya menyadari itu mungkin bukan solusi terbaik, tetapi itu adalah solusi yang diminta.
Tony Hinkle
3
Tony: Saya tidak memilih, tapi saya setuju bahwa seseorang tidak boleh memilih tanpa memberikan alasan dalam komentar, atau memberikan suara pada komentar yang ada yang menyertakan alasan mereka. Yang mengatakan: 1) tidak ada FINALLYblok di T-SQL (saya pikir Anda maksud CATCH). 2) Anda mungkin harus menyebutkan bahwa TRY_CONVERTdimulai pada 2012 (beberapa orang terjebak pra-SQL Server 2012). 3) sudahkah Anda dianggap sebagai TVF sebaris? Mereka tidak memiliki masalah kinerja yang sama dengan UDF Skalar.
Solomon Rutzky
1
@TonyHinkle Terima kasih telah mengeditnya, dan untuk referensi jawaban SO saya :). Namun, saya tidak yakin berapa banyak pembaca akan dapat melakukan lompatan dari melihat logika UDF dan membaca bahwa TVF sebaris akan lebih baik, untuk berhasil menerapkan iTVF. Jadi, saya melanjutkan dan menambahkannya di akhir jawaban Anda.
Solomon Rutzky
1
@SolomonRutzky Terima kasih. Saya bukan benar-benar pengembang SQL sehingga masih di atas kepala saya. Mungkin saya seharusnya tidak menjawab sesuatu seperti ini, tetapi ini adalah kesempatan belajar yang luar biasa.
Tony Hinkle