文字入力を受け取り、日付形式を返す関数(入力が正しくない場合)


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

これは機能せず、2番目の部分(入力が正しくない場合)の処理方法がわかりません。


1
「Transact-SQLを使用したデータのクエリ」をお読みになることをお勧めします。多くのSQLプログラミングを行う場合は、この本でこのようなコーディング方法の基本を説明します。 amazon.com/Exam-70-761-Querying-Data-Transact-SQL-ebook/dp/...
トニー・ヒンクル

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を使用するという考え全体を破棄します...
Aaron Bertrand

2
私は担当者の点については本当に気にしないので、そのようなことの喪失のためにそれを言っているわけではありませんが、コミュニティは明らかに正しい答えに反対票を投じることから利益を得ていません。反対票を投じるのではなく、回答を書いたり、鉱山を編集したり、変更が必要なものについてコメントを残したりできます。OPが機能を求めましたが、それが最善の解決策ではないかもしれませんが、それは要求された解決策です。
トニー・ヒンクル

3
トニー:私は反対票を投じませんでしたが、コメントに論拠を提供したり、彼らの論拠を含む既存のコメントを賛成投票したりせずに誰かが反対票を投じてはならないことに確かに同意します。それは言った:1)FINALLY T-SQLにブロックはありません(私はあなたが意図したと思いますCATCH)。2)あなたはおそらくTRY_CONVERT2012年に始まったことに言及する必要があります(一部の人々はSQL Server 2012以前に行き詰まっています)。3)インラインTVFを検討しましたか?これらには、スカラーUDFと同じパフォーマンスの問題はありません。
ソロモンルツキー

1
@TonyHinkleこれらの編集を行ってくれて、私のSOの回答を参照してくれてありがとう:) それでも、iTVFを正常に実装するために、UDFロジックを見て、インラインTVFの方が優れていることを読んで、いくつの読者が飛躍できるかはわかりません。それで、私は先に進み、それをあなたの答えの最後に追加しました。
ソロモンルツキー

1
@SolomonRutzkyありがとう。私は実際にはSQL開発者ではないので、それはまだ私の頭の先にあります。たぶん、こんなことは答えない方がいいかもしれませんが、ものすごい学習機会です。
トニー・ヒンクル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.