Możesz utworzyć wbudowaną funkcję z wartościami tabeli (ITVF) w SQL Server przy użyciu CREATE FUNCTION
języka T-SQL składnia.
Składnia
Oto oficjalna składnia wbudowanych plików TVF.
CREATE [ OR ALTER ] FUNCTION [ schema_name. ] function_name ( [ { @parameter_name [ AS ] [ type_schema_name. ] parameter_data_type [ = default ] [ READONLY ] } [ ,...n ] ] ) RETURNS TABLE [ WITH <function_option> [ ,...n ] ] [ AS ] RETURN [ ( ] select_stmt [ ) ] [ ; ]
Przykład 1 – Podstawowy ITVF
Oto przykład podstawowej wbudowanej funkcji z wartościami tabelarycznymi.
CREATE FUNCTION dbo.udf_CatsByName_ITVF( @CatName varchar(70) ) RETURNS TABLE AS RETURN ( SELECT CatId, CatName, Phone FROM dbo.Cats WHERE CatName = @CatName ); GO
W takim przypadku funkcja wymaga podania imienia kota jako argumentu. Następnie używa tego argumentu w zapytaniu, aby zwrócić odpowiednie dane.
Przykład 2 – Dodaj powiązanie schematu
Zwykle dobrym pomysłem jest powiązanie schematu funkcji za pomocą SCHEMABINDING
argument.
W ten sposób zapewnisz, że tabel bazowych nie będzie można zmienić w sposób, który wpłynąłby na twoją funkcję.
Bez powiązania schematu bazowe tabele mogą być modyfikowane, a nawet usuwane. Może to spowodować uszkodzenie funkcji.
Oto ta sama funkcja, ale tym razem z powiązaniem schematu:
CREATE FUNCTION dbo.udf_CatsByName_ITVF( @CatName varchar(70) ) RETURNS TABLE WITH SCHEMABINDING AS RETURN ( SELECT CatId, CatName, Phone FROM dbo.Cats WHERE CatName = @CatName ); GO
Zauważ, że użyłem dwuczęściowej nazwy podczas odwoływania się do tabeli w moim zapytaniu (użyłem dbo.Cats
podczas odwoływania się do tabeli, zamiast po prostu Cats
). Jest to wymagane do powiązania obiektu ze schematem. Jeśli spróbujesz schematycznie powiązać obiekt bez użycia dwuczęściowych nazw, otrzymasz błąd.
Teraz, gdy powiązałem schemat z moją funkcją, jeśli spróbuję usunąć tabelę, do której odwołuje się jej definicja, otrzymuję błąd:
DROP TABLE Cats;
Wynik:
Msg 3729, Level 16, State 1, Line 1 Cannot DROP TABLE 'cats' because it is being referenced by object 'udf_CatsByName_ITVF'.
A tak przy okazji, oto co się stanie, jeśli spróbuję utworzyć funkcję bez używania dwuczęściowego nazewnictwa:
CREATE FUNCTION dbo.udf_CatsByName_ITVF( @CatName varchar(70) ) RETURNS TABLE WITH SCHEMABINDING AS RETURN ( SELECT CatId, CatName, Phone FROM Cats WHERE CatName = @CatName ); GO
Wynik:
Msg 4512, Level 16, State 3, Procedure udf_CatsByName_ITVF, Line 7 Cannot schema bind table valued function 'dbo.udf_CatsByName_ITVF' because name 'Cats' is invalid for schema binding. Names must be in two-part format and an object cannot reference itself.
Przykład 3 – Dodaj szyfrowanie
Możesz także zaszyfrować swoje funkcje za pomocą ENCRYPTION
argument.
Oto przykład szyfrowania funkcji:
CREATE FUNCTION dbo.udf_CatsByName_ITVF( @CatName varchar(70) ) RETURNS TABLE WITH SCHEMABINDING, ENCRYPTION AS RETURN ( SELECT CatId, CatName, Phone FROM dbo.Cats WHERE CatName = @CatName ); GO
Teraz nie mogę wyświetlić definicji funkcji.
SELECT definition FROM sys.sql_modules WHERE object_id = OBJECT_ID('udf_CatsByName_ITVF');
Wynik:
+--------------+ | definition | |--------------| | NULL | +--------------+
Otrzymuję również komunikat o błędzie podczas próby skryptowania definicji funkcji za pomocą Azure Data Studio:
No script was returned when scripting as Create on object UserDefinedFunction
Należy zauważyć, że tekst zaszyfrowanej funkcji jest nadal dostępny dla uprzywilejowanych użytkowników, którzy mogą uzyskiwać dostęp do tabel systemowych przez port DAC lub bezpośrednio uzyskiwać dostęp do plików bazy danych. Ponadto użytkownicy, którzy mogą podłączyć debugger do procesu serwera, mogą pobrać oryginalną procedurę z pamięci w czasie wykonywania.