Можете да създадете функция с таблична стойност с множество изрази (MSTVF) в SQL Server, като използвате T-SQL CREATE FUNCTION
синтаксис.
Синтаксис
Ето официалния синтаксис за TVF с множество изявления.
CREATE [ OR ALTER ] FUNCTION [ schema_name. ] function_name ( [ { @parameter_name [ AS ] [ type_schema_name. ] parameter_data_type [ = default ] [READONLY] } [ ,...n ] ] ) RETURNS @return_variable TABLE <table_type_definition> [ WITH[ ,...n ] ] [ AS ] BEGIN function_body RETURN END [ ; ]
Пример 1 – Основен MSTVF
Ето пример за функция с таблична стойност с множество изрази.
CREATE FUNCTION dbo.udf_PetsByName_MSTVF( @PetName varchar(70)) RETURNS @pets TABLE ( PetId varchar(20), PetName varchar(70) ) AS BEGIN INSERT INTO @pets SELECT CONCAT('Cat', ' ', CatId), CatName FROM dbo.Cats WHERE CatName = @PetName; INSERT INTO @pets SELECT CONCAT('Dog', ' ', DogId), DogName FROM dbo.Dogs WHERE DogName = @PetName; IF @@ROWCOUNT = 0 BEGIN INSERT INTO @pets VALUES ( '', 'There are no pets of that name.' ) END RETURN; END; GO
Структурата на таблицата за връщане се дефинира в началото, когато посоча @pets
променлива. Резултатите от заявката се вмъкват в @pets
променлива.
В този случай функцията изисква да се подаде име на домашен любимец като аргумент. След това използва този аргумент в заявките, за да върне съответните данни. Да бъдеш мулти -функция със стойност на таблица, мога да включа множество изрази в дефиницията на функцията.
Пример 2 – Добавете обвързване на схема
Обикновено е добра идея да обвържете функциите си по схема, като използвате SCHEMABINDING
аргумент.
Това ще гарантира, че основните таблици не могат да бъдат променяни по начин, който би засегнал вашата функция.
Без обвързване на схемата, основните таблици могат да бъдат модифицирани или дори изтрити. Правейки това може да наруши функцията.
Ето същата функция, но този път с обвързване на схема:
CREATE FUNCTION dbo.udf_PetsByName_MSTVF( @PetName varchar(70)) RETURNS @pets TABLE ( PetId varchar(20), PetName varchar(70) ) WITH SCHEMABINDING AS BEGIN INSERT INTO @pets SELECT CONCAT('Cat', ' ', CatId), CatName FROM dbo.Cats WHERE CatName = @PetName; INSERT INTO @pets SELECT CONCAT('Dog', ' ', DogId), DogName FROM dbo.Dogs WHERE DogName = @PetName; IF @@ROWCOUNT = 0 BEGIN INSERT INTO @pets VALUES ( '', 'There are no pets of that name.' ) END RETURN; END; GO
Забележете, че използвах имена от две части, когато препращах към таблиците в моята заявка (използвах dbo.Cats
и dbo.Dogs
при препратка към таблицата, вместо само Cats
или Dogs
). Правенето на това е изискване за свързване на обект със схема. Ако се опитате да обвържете обект със схема, без да използвате имена от две части, ще получите грешка.
Сега, след като схемата обвърза функцията си, ако се опитам да пусна таблицата, посочена в нейната дефиниция, получавам грешка:
DROP TABLE Dogs;
Резултат:
Msg 3729, Level 16, State 1, Line 1 Cannot DROP TABLE 'Dogs' because it is being referenced by object 'udf_PetsByName_MSTVF'.
Между другото, ето какво се случва, ако се опитам да създам функцията, без да използвам именуване от две части:
CREATE FUNCTION dbo.udf_PetsByName_MSTVF( @PetName varchar(70)) RETURNS @pets TABLE ( PetId varchar(20), PetName varchar(70) ) WITH SCHEMABINDING AS BEGIN INSERT INTO @pets SELECT CONCAT('Cat', ' ', CatId), CatName FROM Cats WHERE CatName = @PetName; INSERT INTO @pets SELECT CONCAT('Dog', ' ', DogId), DogName FROM Dogs WHERE DogName = @PetName; IF @@ROWCOUNT = 0 BEGIN INSERT INTO @pets VALUES ( '', 'There are no pets of that name.' ) END RETURN; END; GO
Резултат:
Msg 4512, Level 16, State 3, Procedure udf_PetsByName_MSTVF, Line 10 Cannot schema bind table valued function 'dbo.udf_PetsByName_MSTVF' because name 'Cats' is invalid for schema binding. Names must be in two-part format and an object cannot reference itself.
Пример 3 – Добавяне на криптиране
Можете също да шифровате функциите си с помощта на ENCRYPTION
аргумент.
Ето пример за криптиране на функцията:
CREATE FUNCTION dbo.udf_PetsByName_MSTVF( @PetName varchar(70)) RETURNS @pets TABLE ( PetId varchar(20), PetName varchar(70) ) WITH SCHEMABINDING, ENCRYPTION AS BEGIN INSERT INTO @pets SELECT CONCAT('Cat', ' ', CatId), CatName FROM dbo.Cats WHERE CatName = @PetName; INSERT INTO @pets SELECT CONCAT('Dog', ' ', DogId), DogName FROM dbo.Dogs WHERE DogName = @PetName; IF @@ROWCOUNT = 0 BEGIN INSERT INTO @pets VALUES ( '', 'There are no pets of that name.' ) END RETURN; END; GO
Сега не мога да видя дефиницията на функцията.
SELECT definition FROM sys.sql_modules WHERE object_id = OBJECT_ID('udf_PetsByName_MSTVF');
Резултат:
+--------------+ | definition | |--------------| | NULL | +--------------+
Също така получавам съобщение за грешка, когато се опитвам да напиша дефиницията на функцията чрез Azure Data Studio:
No script was returned when scripting as Create on object UserDefinedFunction
Имайте предвид, че текстът на криптирана функция все още е достъпен за привилегировани потребители, които могат да имат достъп до системните таблици през DAC порта или директно да имат достъп до файловете на базата данни. Освен това потребителите, които могат да прикачат дебъгер към сървърния процес, могат да извличат оригиналната процедура от паметта по време на изпълнение.