In SQL Server è possibile creare una funzione scalare definita dall'utente utilizzando CREATE FUNCTION
dichiarazione. Una funzione scalare definita dall'utente, altrimenti nota come UDF scalare, è una funzione definita dall'utente che restituisce un singolo valore.
Questo articolo contiene esempi di creazione di alcune UDF scalari T-SQL di base.
Sintassi
Per prima cosa, diamo un'occhiata alla sintassi per la creazione di UDF scalari.
La sintassi per le UDF scalari T-SQL è la seguente:
CREATE [ OR ALTER ] FUNCTION [ schema_name. ] function_name ( [ { @parameter_name [ AS ][ type_schema_name. ] parameter_data_type [ = default ] [ READONLY ] } [ ,...n ] ] ) RETURNS return_data_type [ WITH <function_option> [ ,...n ] ] [ AS ] BEGIN function_body RETURN scalar_expression END [ ; ]
E la sintassi per le UDF scalari CLR:
CREATE [ OR ALTER ] FUNCTION [ schema_name. ] function_name ( { @parameter_name [AS] [ type_schema_name. ] parameter_data_type [ = default ] } [ ,...n ] ) RETURNS { return_data_type } [ WITH <clr_function_option> [ ,...n ] ] [ AS ] EXTERNAL NAME[ ; ]
Le parti in <function_option>
per le funzioni T-SQL e <clr_function_option>
per le funzioni CLR consentono di specificare le opzioni per l'UDF. Le opzioni delle funzioni includono l'aggiunta di crittografia, associazione dello schema, un EXECUTE AS
clausola, oltre a specificare cosa fare quando un valore NULL viene passato come argomento.
Un elenco completo di argomenti e opzioni di funzione è disponibile sul sito Web di Microsoft.
La documentazione Microsoft contiene molti dettagli, quindi i seguenti esempi hanno lo scopo di fornire una rapida panoramica di alcuni concetti e opzioni comuni durante la creazione di UDF scalari.
Esempio 1 – UDF scalare di base
Ecco un esempio del codice utilizzato per creare una UDF scalare T-SQL di base.
CREATE FUNCTION dbo.ufn_discountPrice( @price DECIMAL(12,2), @discount DECIMAL(12,2) ) RETURNS DECIMAL (12,2) AS BEGIN RETURN @price * (1 - @discount); END;
Questa UDF scalare accetta due parametri; @price
e @discount
. Questi vengono passati alla funzione come argomenti ogni volta che la funzione viene invocata. La funzione prende il valore di quegli argomenti, esegue un calcolo utilizzando quei valori, quindi restituisce il valore risultante. In questo caso viene restituito il prezzo scontato.
Esempio 2 – Richiamare l'UDF
Una volta che l'UDF è stato creato, può essere invocato all'interno del codice T-SQL ogni volta che ne hai bisogno.
Ecco un esempio di richiamo dell'UDF:
SELECT dbo.ufn_discountPrice(100, .2) AS Result;
Risultato
+----------+ | Result | |----------| | 80.00 | +----------+
Esempio 3 – Interrogazione di una tabella
Le UDF scalari possono anche fare cose come le tabelle di database di query.
Eccone uno che restituisce il numero di album presenti nel database per un determinato artista.
CREATE FUNCTION dbo.ufn_CountAlbums (@ArtistId int) RETURNS smallint AS BEGIN DECLARE @AlbumCount int; SELECT @AlbumCount = COUNT(AlbumId) FROM Albums WHERE ArtistId = @ArtistId; RETURN @AlbumCount; END;
Questa è una funzione scalare perché restituisce un singolo valore. Se volessimo restituire un elenco di album, dovremmo utilizzare una funzione con valori di tabella, perché le funzioni con valori di tabella restituiscono i risultati come un insieme di righe.
Esempio 4 – Associazione di schemi
Quando crei una funzione definita dall'utente che dipende da altri oggetti nel database, in genere è una buona idea associare a uno schema l'UDF. L'associazione dello schema dell'UDF garantisce che non sia possibile apportare modifiche agli oggetti sottostanti che potrebbero potenzialmente influire sulla funzione.
Ad esempio, non saresti in grado di eliminare una tabella utilizzata da un'UDF associata a uno schema nella sua definizione.
Per associare allo schema un UDF, usa WITH SCHEMABINDING
nella sua definizione. È inoltre necessario utilizzare nomi in due parti per tutti gli oggetti a cui si fa riferimento nell'UDF.
Ecco l'esempio precedente riscritto in modo che sia legato allo schema:
CREATE FUNCTION dbo.ufn_CountAlbums (@ArtistId int) RETURNS smallint WITH SCHEMABINDING AS BEGIN DECLARE @AlbumCount int; SELECT @AlbumCount = COUNT(AlbumId) FROM dbo.Albums WHERE ArtistId = @ArtistId; RETURN @AlbumCount; END;
Quindi, ho cambiato due cose rispetto al primo esempio. Ho aggiunto WITH SCHEMABINDING
e ho cambiato Albums
a dbo.Albums
.
Ora, se qualcuno tenta di eliminare quella tabella o di apportare altre modifiche, riceverà un errore.
Esempio 5 – Crittografia
Puoi anche usare WITH ENCRYPTION
per crittografare la funzione.
CREATE FUNCTION dbo.ufn_CountAlbums (@ArtistId int) RETURNS smallint WITH ENCRYPTION AS BEGIN DECLARE @AlbumCount int; SELECT @AlbumCount = COUNT(AlbumId) FROM dbo.Albums WHERE ArtistId = @ArtistId; RETURN @AlbumCount; END;
Esempio 6 – Input NULL
Quando si richiama la funzione, se uno qualsiasi degli argomenti è NULL, il corpo della funzione viene comunque eseguito. Cioè, a meno che tu non abbia dichiarato esplicitamente RETURNS NULL ON NULL INPUT
nella definizione della funzione.
Specificando tale opzione restituirà NULL se uno qualsiasi degli argomenti è NULL.
CREATE FUNCTION dbo.ufn_CountAlbums (@ArtistId int) RETURNS smallint WITH RETURNS NULL ON NULL INPUT AS BEGIN DECLARE @AlbumCount int; SELECT @AlbumCount = COUNT(AlbumId) FROM dbo.Albums WHERE ArtistId = @ArtistId; RETURN @AlbumCount; END;
Quando invoco la funzione usando NULL come argomento:
SELECT dbo.ufn_CountAlbums(NULL) AS Result;
Ottengo un risultato diverso, a seconda di ciò che ho specificato per questa opzione.
Ecco il risultato quando la funzione utilizza l'impostazione predefinita (CALLED ON NULL INPUT
):
+----------+ | Result | |----------| | 0 | +----------+
Ed ecco il risultato quando usa RETURNS NULL ON NULL INPUT
:
+----------+ | Result | |----------| | NULL | +----------+
Esempio 7 – Opzioni multiple
Puoi separare più opzioni con una virgola.
Ecco un esempio che aggiunge sia la crittografia che il binding dello schema alla funzione:
CREATE FUNCTION dbo.ufn_CountAlbums (@ArtistId int) RETURNS smallint WITH ENCRYPTION, SCHEMABINDING AS BEGIN DECLARE @AlbumCount int; SELECT @AlbumCount = COUNT(AlbumId) FROM dbo.Albums WHERE ArtistId = @ArtistId; RETURN @AlbumCount; END;
Esempio 8 – Modifica di una funzione
Puoi modificare una UDF scalare sostituendo CREATE
con ALTER
.
ALTER FUNCTION dbo.ufn_CountAlbums (@ArtistId int) RETURNS smallint WITH SCHEMABINDING AS BEGIN DECLARE @AlbumCount int; SELECT @AlbumCount = COUNT(AlbumId) FROM dbo.Albums WHERE ArtistId = @ArtistId; RETURN @AlbumCount; END;