W SQL Server można utworzyć skalarną funkcję zdefiniowaną przez użytkownika za pomocą CREATE FUNCTION
oświadczenie. Skalarna funkcja zdefiniowana przez użytkownika, znana również jako skalarna funkcja UDF, to funkcja zdefiniowana przez użytkownika, która zwraca pojedynczą wartość.
Ten artykuł zawiera przykłady tworzenia podstawowych skalarnych UDF w języku T-SQL.
Składnia
Najpierw spójrzmy na składnię tworzenia skalarnych UDF.
Składnia skalarnych UDF w języku T-SQL wygląda następująco:
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 [ ; ]
I składnia skalarnych UDF 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[ ; ]
Części w <function_option>
dla funkcji T-SQL i <clr_function_option>
dla funkcji CLR umożliwiają określenie opcji dla UDF. Opcje funkcji obejmują dodanie szyfrowania, powiązanie schematu, EXECUTE AS
klauzula, a także określenie, co zrobić, gdy jako argument zostanie przekazana wartość NULL.
Pełną listę argumentów i opcji funkcji można znaleźć na stronie Microsoft.
Dokumentacja firmy Microsoft zawiera wiele szczegółów, więc poniższe przykłady mają na celu zapewnienie szybkiego przeglądu niektórych typowych koncepcji i opcji podczas tworzenia skalarnych funkcji UDF.
Przykład 1 – Podstawowy skalarny UDF
Oto przykład kodu użytego do stworzenia podstawowego skalarnego UDF w języku T-SQL.
CREATE FUNCTION dbo.ufn_discountPrice( @price DECIMAL(12,2), @discount DECIMAL(12,2) ) RETURNS DECIMAL (12,2) AS BEGIN RETURN @price * (1 - @discount); END;
Ten skalarny UDF akceptuje dwa parametry; @price
i @discount
. Są one przekazywane do funkcji jako argumenty przy każdym wywołaniu funkcji. Funkcja pobiera wartość tych argumentów, wykonuje obliczenia przy użyciu tych wartości, a następnie zwraca wynikową wartość. W takim przypadku zwracana jest obniżona cena.
Przykład 2 – Wywołaj UDF
Po utworzeniu UDF można go wywołać w kodzie T-SQL w dowolnym momencie.
Oto przykład wywoływania UDF:
SELECT dbo.ufn_discountPrice(100, .2) AS Result;
Wynik
+----------+ | Result | |----------| | 80.00 | +----------+
Przykład 3 – Zapytanie do tabeli
Skalarne UDF mogą również robić takie rzeczy jak tabele bazy danych zapytań.
Oto taki, który zwraca liczbę albumów znajdujących się w bazie danych dla danego artysty.
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;
Jest to funkcja skalarna, ponieważ zwraca pojedynczą wartość. Gdybyśmy chcieli zwrócić listę albumów, musielibyśmy użyć funkcji z wartościami w tabeli, ponieważ funkcje z wartościami w tabeli zwracają jej wyniki jako zestaw wierszy.
Przykład 4 – Powiązanie schematu
Podczas tworzenia funkcji zdefiniowanej przez użytkownika, która zależy od innych obiektów w bazie danych, zwykle dobrym pomysłem jest powiązanie schematu UDF. Schemat powiązania UDF zapewnia, że nie można wprowadzać żadnych zmian w bazowych obiektach, które mogłyby potencjalnie wpłynąć na funkcję.
Na przykład nie byłoby możliwości usunięcia tabeli, której w definicji używa powiązany ze schematem UDF.
Aby schematycznie powiązać UDF, użyj WITH SCHEMABINDING
w swojej definicji. Musisz również użyć dwuczęściowych nazw dla wszystkich obiektów, do których odwołuje się UDF.
Oto poprzedni przykład przepisany tak, że jest powiązany ze schematem:
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;
Zmieniłem więc dwie rzeczy z pierwszego przykładu. Dodałem WITH SCHEMABINDING
i zmieniłem Albums
do dbo.Albums
.
Teraz, jeśli ktoś spróbuje usunąć tę tabelę lub wprowadzić w niej inne zmiany, otrzyma błąd.
Przykład 5 – Szyfrowanie
Możesz także użyć WITH ENCRYPTION
aby zaszyfrować funkcję.
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;
Przykład 6 – Wejście NULL
Podczas wywoływania funkcji, jeśli którykolwiek z argumentów ma wartość NULL, ciało funkcji jest nadal wykonywane. To znaczy, chyba że wyraźnie określiłeś RETURNS NULL ON NULL INPUT
w definicji funkcji.
Określenie tej opcji zwróci NULL, jeśli którykolwiek z argumentów ma wartość 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;
Kiedy wywołuję funkcję używając NULL jako argumentu:
SELECT dbo.ufn_CountAlbums(NULL) AS Result;
Otrzymuję inny wynik, w zależności od tego, co określiłem dla tej opcji.
Oto wynik, gdy funkcja używa ustawienia domyślnego (CALLED ON NULL INPUT
):
+----------+ | Result | |----------| | 0 | +----------+
A oto wynik, gdy używa RETURNS NULL ON NULL INPUT
:
+----------+ | Result | |----------| | NULL | +----------+
Przykład 7 – Wiele opcji
Możesz oddzielić wiele opcji przecinkiem.
Oto przykład, który dodaje do funkcji zarówno szyfrowanie, jak i powiązanie schematu:
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;
Przykład 8 – Zmień funkcję
Możesz zmienić skalarny UDF, zastępując CREATE
z 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;