Perché le funzioni con valori scalari devono eseguire l'autorizzazione anziché selezionare?


15

Mi chiedo perché, per la funzione a valore scalare, che devo concedere all'utente di eseguire piuttosto che solo una selezione?

nel frattempo le funzioni con valori di tabella funzionano bene solo con l'autorizzazione o l' db_datareaderappartenenza selezionata .

per essere più chiari qui è il mio esempio: ho bisogno di un utente che abbia letto solo l'autorizzazione per il database. così ho creato un utente chiamato testUsere gli ho dato l' db_datareaderappartenenza. quindi ho creato una funzione con valori di tabella chiamata fn_InlineTable. E tutto è fantastico. testUseresegue questo SQL tutto il giorno

select * from dbo.fn_InlineTable

quindi ho bisogno di una funzione scalare, quindi ho creato una funzione scalare chiamata fn_ScalarTest. testUserimpossibile eseguire questo SQL

Select dbo.fn_ScalarTest(1) 

Ben comprensibile: è perché non ho dato il permesso "testUser" di eseguire fn_ScalarTest.

La mia domanda è: sulla base di questo link /programming/6150888/insert-update-delete-with-function-in-sql-server , che dice che FUNCTIONnon può essere utilizzato per eseguire azioni che modificano lo stato del database . Quindi perché non lasciare che una funzione scalare venga utilizzata con la stessa autorizzazione "SELEZIONA" anziché eseguire l'autorizzazione ??

Spero che la mia domanda abbia un senso. Grazie.

Risposte:


15

Molto probabilmente il motivo principale è che le funzioni con valori di tabella restituiscono un set di risultati, proprio come le tabelle e le viste. Questo significa che possono essere utilizzati nella FROMclausola (tra cui JOINs e APPLYs, ecc) di SELECT, UPDATEe DELETEle query. Tuttavia, non è possibile utilizzare un UDF scalare in nessuno di questi contesti.

Secondariamente, puoi anche EXECUTEun UDF scalare. Questa sintassi è abbastanza utile quando si hanno valori predefiniti specificati per i parametri di input. Prendi il seguente UDF, per esempio:

CREATE FUNCTION dbo.OptionalParameterTest (@Param1 INT = 1, @Param2 INT = 2)
RETURNS INT
AS
BEGIN
    RETURN @Param1 + @Param2;
END;

Se vuoi considerare uno qualsiasi dei parametri di input come "opzionale", devi comunque passare la DEFAULTparola chiave quando la chiami come una funzione poiché la firma è fissa:

DECLARE @Bob1 INT;

SET @Bob1 = dbo.OptionalParameterTest(100, DEFAULT);

SELECT @Bob1;
-- Returns: 102

D'altra parte, se si EXECUTEdispone della funzione, è possibile considerare qualsiasi parametro con un valore predefinito come veramente facoltativo, proprio come è possibile con Stored Procedures. È possibile passare i primi n parametri senza specificare i nomi dei parametri:

DECLARE @Bob2 INT;

EXEC @Bob2 = dbo.OptionalParameterTest 50;

SELECT @Bob2;
-- Returns: 52

Puoi anche saltare il primo parametro specificando nuovamente i nomi dei parametri, proprio come con Stored Procedures:

DECLARE @Bob3 INT;

EXEC @Bob3 = dbo.OptionalParameterTest @Param2 = 50;

SELECT @Bob3;
-- Returns: 51

AGGIORNARE

Perché potresti voler usare la EXECsintassi per chiamare un UDF scalare proprio come una Stored Procedure? Occasionalmente ci sono UDF che sono fantastici da avere come UDF poiché possono essere aggiunti a una query e operare sull'insieme di righe restituite, mentre se il codice fosse in una Stored Procedure allora dovrebbe essere posizionato in un cursore per iterare su una serie di righe. Ma poi ci sono volte che vuoi chiamare quella funzione su un singolo valore, possibilmente da un altro UDF. La chiamata di un UDF per un singolo valore può essere eseguita come:

SELECT dbo.UDF('some value');

nel qual caso si ottiene un valore di ritorno in un set di risultati (un set di risultati non funzionerà). O potrebbe essere fatto come segue:

DECLARE @Dummy INT;

SET @Dummy = dbo.UDF('some value');

nel qual caso è necessario dichiarare la @Dummyvariabile;

TUTTAVIA, con la EXECsintassi, puoi evitare entrambi questi fastidi:

EXEC dbo.UDF 'some value';

Inoltre, gli UDF scalari hanno i loro piani di esecuzione memorizzati nella cache. Ciò significa che è possibile imbattersi in problemi di sniffing dei parametri se nell'UDF sono presenti query con piani di esecuzione. Per gli scenari in cui è possibile utilizzare la EXECsintassi, è anche possibile utilizzare l' WITH RECOMPILEopzione per ignorare il valore compilato dei piani per tale esecuzione . Per esempio:

IMPOSTARE:

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

TEST:

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

Penso che la differenza nelle autorizzazioni sia perché puoi effettivamente invocare funzioni definite dall'utente con valori scalari con EXEC proprio come le procedure memorizzate (che non avevo realizzato fino a quando non ho scavato nella documentazione online di SQL Server 2000, dove hanno introdotto funzioni definite dall'utente) , tuttavia non è possibile selezionarli effettivamente come origine tabella. Per esempio:

DECLARE @date datetime
EXEC @date = dbo.first_day_of_month '8/14/2015'
SELECT @date

In questo caso, dbo.first_day_of_month è una funzione definita dall'utente. Non so perché invocherai mai una funzione in quel modo, ma speculerei sul fatto che richiedessero l'autorizzazione EXECUTE anziché SELECT per mantenere la coerenza. Oggi è probabilmente trattenuto solo come bagaglio di compatibilità.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.