Можете да създадете функция с таблична стойност с множество изрази (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 порта или директно да имат достъп до файловете на базата данни. Освен това потребителите, които могат да прикачат дебъгер към сървърния процес, могат да извличат оригиналната процедура от паметта по време на изпълнение.