T-SQL-デフォルトのパラメーターを持つ関数


155

私はこのスクリプトを持っています:

CREATE FUNCTION dbo.CheckIfSFExists(@param1 INT, @param2 BIT = 1 )
RETURNS BIT
AS
BEGIN
    IF EXISTS ( bla bla bla )
        RETURN 1;
    RETURN 0;
END
GO

このように手順で使用したい:

IF dbo.CheckIfSFExists( 23 ) = 0
    SET @retValue = 'bla bla bla';

しかし、私はエラーが出ます:

プロシージャまたは関数dbo.CheckIfSFExistsに指定された引数の数が不十分です。

なぜ動作しないのですか?

回答:


227

あなたはそれをこのように呼ばなければなりません

SELECT dbo.CheckIfSFExists(23, default)

Technetから:

関数のパラメーターにデフォルト値がある場合、デフォルト値を取得するために関数を呼び出すときにキーワードDEFAULTを指定する必要があります。この動作は、パラメータを省略するとデフォルト値も含まれるストアドプロシージャで、デフォルト値を持つパラメータを使用する場合とは異なります。この動作の例外は、EXECUTEステートメントを使用してスカラー関数を呼び出す場合です。EXECUTEを使用する場合、DEFAULTキーワードは不要です。


80
これを見て私はイライラしています。私はdefaultここでコンセプトを活用していません...今、すべての場所を変更する必要があります。
LCJ 2014

8
@Lijo、それでも、各呼び出しで具体的なデフォルト値を複製しないという利点があります。
フレデリック

9
オーバーレイすることは許可されておらず、「デフォルト」は使用可能性を制限しているため、多くの場合、最良のアプローチは、追加のパラメーターを持つサフィックス(ここではCheckIfSFExistsEX)を使用して新しい拡張バージョンを作成し、元の関数を単に「デフォルト」パラメータを使用して拡張バージョンを呼び出す。このようにして、既存のすべてのコードが機能し、維持する場所は1つだけになります。
Eske Rahn 2018年

39

あなたはそれを3つの方法で呼び出すことができます-パラメータ付き、DEFAULT付き、そしてEXECUTE経由

SET NOCOUNT ON;

DECLARE
@Table  SYSNAME = 'YourTable',
@Schema SYSNAME = 'dbo',
@Rows   INT;

SELECT dbo.TableRowCount( @Table, @Schema )

SELECT dbo.TableRowCount( @Table, DEFAULT )

EXECUTE @Rows = dbo.TableRowCount @Table

SELECT @Rows

11
DEFAULTselectでキーワードが必要なのに、executeでは省略できるのはなぜですか?これはうんざりです:/うまくいけば、これはいつか修正されるでしょう。
Misiu

@Misiu、「修正」する必要があるものではありません。これは仕様によるものです。すべての引数を指定せずに関数を呼び出すことができるという「理想的な」目標に近づくために多くの代替案を読みましたが、それが必要な理由の明確な説明はありませんでした。コードは明確である必要があり、それを達成するための1つの戦略は、コーダーが常に「これとこの他の引数を持つ関数を呼び出しており、たまたまデフォルト値を持つことを知っていることを認識する必要があることです。忘れないでください。デフォルト値は変更される場合があります。」IMO、これは良い「悪いこと」です。
Gustavo Pinsard

16

ユーザー定義関数では、たとえデフォルト値がある場合でも、すべてのパラメーターを宣言する必要があります。

以下は正常に実行されます。

IF dbo.CheckIfSFExists( 23, default ) = 0
    SET @retValue = 'bla bla bla;

-1

この問題を回避する1つの方法は、出力パラメーターを持つストアード・プロシージャーを使用することです。

exec sp_mysprocname @returnvalue output、@firstparam = 1、@ secondparam = 2

ストアドプロシージャ自体に設定されているデフォルトにデフォルトで渡さない値。そして、出力変数から結果を取得できます。


1
クエリ内からストアドプロシージャを呼び出すことはできませんが、関数は呼び出すことができるため、関数をストアドプロシージャに変更することは、一般的に適切な解決策ではありません。
ブレード

確かに、ただし、コードのすべてのブロックをクエリ内から呼び出す必要はありません。sqlには関数のデフォルト値を処理する適切な方法がないことが示されています(defaultキーワードを使用することは、値を追加することとほとんど同じです)。これは良い一般的な解決策ではありませんが、特定のユースケースでうまく機能します。
Jereme Guenther 2017年

人々はこれをマークダウンし続けますが、私はそれに固執しています。クエリ内で呼び出されない再利用可能なコードのチャンクが必要であり、デフォルト値を持つ真のオプションパラメータの柔軟性が必要な場合でも、ストアドプロシージャは関数よりも優れています。
Jereme Guenther

1
ストアドプロシージャを使用することは、関数を使用する代わりにそれらを使用することを意味しません。つまり、ストアドプロシージャを関数のラッパーとして使用することを意味します。私はこのテクニックをよく使用します。デフォルトのキーワードは、現在procの内部に隠されています。このアイデアは大丈夫​​だと思います。また、必要に応じて、より複雑なデフォルトを作成することもできます。より純粋な状態のままにすることができる関数とは別にします。
Jブライアン価格
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.