Чому функції, що мають значення для скалярного значення, потребують виконання дозволу, а не вибору?


15

Мене цікавить, чому для функції скалярної цінності я повинен дозволити користувачеві виконувати, а не просто вибирати?

тим часом функції, що оцінюються в таблиці, спрацьовують добре лише з дозволом або db_datareaderчленством.

щоб бути більш зрозумілим ось мій приклад: мені потрібен користувач, який читав лише дозвіл на базу даних. тому я створив користувача, який називається, testUserі даю йому db_datareaderчленство. тоді я створив функцію оцінювання таблиці, яку називають fn_InlineTable. І все чудово. testUserпрацює цей SQL цілий день

select * from dbo.fn_InlineTable

тоді мені потрібна скалярна функція, тому я створив скалярну функцію під назвою fn_ScalarTest. testUserне може запустити цей SQL

Select dbo.fn_ScalarTest(1) 

Цілком зрозуміло: це тому, що я не дав "testUser" дозволу на виконання fn_ScalarTest.

Моє запитання: на основі цього посилання /programming/6150888/insert-update-delete-with-function-in-sql-server , що говорить, що FUNCTIONне можна використовувати для виконання дій, що змінюють стан бази даних . То чому б не дозволити використовувати скалярну функцію з тим самим дозволом "SELECT", а не виконувати дозвіл ??

Сподіваюся, моє питання має сенс. Дякую.

Відповіді:


15

Швидше за все, основною причиною є те, що функції, націлені на таблицю, повертають набір результатів, як і таблиці та представлення. Це означає , що вони можуть бути використані в FROMпункті ( в тому числі JOINз і APPLYз, і так далі) з SELECT, UPDATEі DELETEзапитів. Однак ви не можете використовувати Скалярну СДС в жодному з цих контекстів.

По-друге, ви також EXECUTEможете скалярний АДС. Цей синтаксис є досить зручним, коли для вхідних параметрів у вас є значення за замовчуванням. Візьмемо, наприклад, наступну УДС:

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 є запити, які мають плани виконання. Для сценаріїв, де доцільно використовувати 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;

4

Я думаю, що різниця в дозволах полягає в тому, що ви можете фактично викликати скалярні функції, визначені користувачем, за допомогою 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. Сьогодні це, мабуть, просто тримається за багаж сумісності.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.