おそらく、主な理由は、テーブルとビューのように、テーブル値関数が結果セットを返すことです。これは、それらが使用できることを意味するFROM
(含む句JOIN
SおよびAPPLY
S、等)のSELECT
、UPDATE
およびDELETE
クエリ。ただし、これらのコンテキストでScalar UDFを使用することはできません。
第二に、EXECUTE
スカラーUDF も使用できます。この構文は、入力パラメーターにデフォルト値が指定されている場合に非常に便利です。たとえば、次のUDFを使用します。
CREATE FUNCTION dbo.OptionalParameterTest (@Param1 INT = 1, @Param2 INT = 2)
RETURNS INT
AS
BEGIN
RETURN @Param1 + @Param2;
END;
入力パラメータのいずれかを「オプション」として扱いたい場合DEFAULT
は、シグネチャが修正されるため、関数のように呼び出すときにキーワードを渡す必要があります。
DECLARE @Bob1 INT;
SET @Bob1 = dbo.OptionalParameterTest(100, DEFAULT);
SELECT @Bob1;
-- Returns: 102
一方、EXECUTE
関数を使用する場合は、ストアドプロシージャの場合と同様に、デフォルト値を持つパラメーターをオプションとして扱うことができます。パラメーター名を指定せずに、最初のn個のパラメーターを渡すことができます。
DECLARE @Bob2 INT;
EXEC @Bob2 = dbo.OptionalParameterTest 50;
SELECT @Bob2;
-- Returns: 52
ストアドプロシージャの場合と同様に、パラメータ名を指定して最初のパラメータをスキップすることもできます。
DECLARE @Bob3 INT;
EXEC @Bob3 = dbo.OptionalParameterTest @Param2 = 50;
SELECT @Bob3;
-- Returns: 51
更新
なぜEXEC
ストアドプロシージャのように構文を使用してスカラーUDFを呼び出したいのでしょうか?UDFがクエリに追加され、返された行のセットを操作できるため、UDFとして優れている場合がありますが、コードがストアドプロシージャにある場合は、カーソルに配置する必要があります。行のセットを反復処理します。しかし、その場合は、おそらく別のUDF内から単一の値でその関数を呼び出したいことがあります。単一の値に対してUDFを呼び出すには、次のいずれかを実行できます。
SELECT dbo.UDF('some value');
その場合、結果セットで戻り値を取得します(結果セットは機能しません)。または、次のように実行できます。
DECLARE @Dummy INT;
SET @Dummy = dbo.UDF('some value');
その場合、@Dummy
変数を宣言する必要があります。
ただし、EXEC
構文を使用すると、これらの煩わしさの両方を回避できます。
EXEC dbo.UDF 'some value';
また、スカラーUDFには実行プランがキャッシュされています。これは、実行計画のあるクエリがUDFにある場合、パラメータスニッフィングの問題が発生する可能性があることを意味します。EXEC
構文を使用することが適切なシナリオでは、WITH RECOMPILE
オプションを使用して、その実行用にコンパイルされたプランを無視することもできます。例えば:
セットアップ:
GO
CREATE FUNCTION dbo.TestUDF (@Something INT)
RETURNS INT
AS
BEGIN
DECLARE @Ret INT;
SELECT @Ret = COUNT(*)
FROM sys.indexes si
WHERE si.[index_id] = @Something;
RETURN @Ret;
END;
GO
テスト:
DECLARE @Val INT;
SET @Val = dbo.TestUDF(1);
SELECT @Val;
EXEC @Val = dbo.TestUDF 0 -- uses compiled value of (1)
SELECT @Val;
EXEC @Val = dbo.TestUDF 0 WITH RECOMPILE; -- uses compiled value of (0)
SELECT @Val;
EXEC @Val = dbo.TestUDF 3 -- uses compiled value of (1)
SELECT @Val;