スカラー値関数の場合、ユーザーに選択だけでなく実行を許可する必要があるのはなぜでしょうか。
一方、テーブル値関数は、select権限またはdb_datareader
メンバーシップのみで問題なく機能します。
より明確にするために、ここに私の例を示します。データベースへの読み取り専用権限を持つユーザーが必要です。 testUser
というユーザーを作成し、db_datareader
のメンバーシップを付与しました。次に、fn_InlineTable
というテーブル値関数を作成しました。そして、すべてが素晴らしいです。 testUser
は、このSQLを終日実行します
select * from dbo.fn_InlineTable
次に、スカラー関数が必要なので、fn_ScalarTest
というスカラー関数を作成しました。 testUser
はこのSQLを実行できません
Select dbo.fn_ScalarTest(1)
当然のことながら、これはfn_ScalarTest
を実行するための「testUser」権限を付与していないためです。
私の質問は次のとおりです:このリンクに基づいて https://stackoverflow.com/questions/6150888/insert-update-delete-with-function-in-sql-server 、それはFUNCTION
を使用して、データベースの状態を変更するアクションを実行することはできません。それでは、スカラー関数を実行権限ではなく、同じ「SELECT」権限で使用してはどうでしょうか?
私の質問が理にかなっているといいのですが。ありがとうございました。
最も可能性の高い主な理由は、テーブル値関数が、テーブルやビューと同様に結果セットを返すことです。これは、FROM
、JOIN
、およびAPPLY
句(SELECT
sおよびUPDATE
sなどを含む)で使用できることを意味します。 DELETE
クエリ。ただし、これらのコンテキストではスカラーUDFを使用できません。
次に、スカラーUDFをEXECUTE
することもできます。この構文は、入力パラメーターにデフォルト値が指定されている場合に非常に便利です。たとえば、次の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内から、単一の値でその関数を呼び出したいことがあります。単一の値の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;
アクセス許可の違いは、ストアドプロシージャと同じように、EXECを使用してスカラー値のユーザー定義関数を実際に呼び出すことができるためだと思います(SQL Server 2000 Books Onlineを掘り下げてユーザー定義関数を紹介するまでは、これに気付きませんでした)。ただし、実際にはそれらからテーブルソースとして選択することはできません。例えば:
DECLARE @date datetime
EXEC @date = dbo.first_day_of_month '8/14/2015'
SELECT @date
この場合、dbo.first_day_of_monthはユーザー定義関数です。なぜ関数をそのように呼び出すのかはわかりませんが、一貫性を維持するために、SELECTではなくEXECUTE権限が必要だったと思います。現在、互換性のある荷物として保持されているだけです。