Возвращающие табличное значение определяемые пользователем функции

Определяемые пользователем функции, возвращающие тип данных table, могут быть полноценной альтернативой представлениям. Возвращающая табличное значение функция, определяемая пользователем, может быть использована там, где в запросах Transact-SQL разрешены выражения представлений. В то время как представления ограничены одной инструкцией SELECT, определяемые пользователем функции могут содержать дополнительные инструкции, обеспечивающие более сложную логику.

Возвращающая табличное значение функция, определяемая пользователем, также может заменять хранимые процедуры, возвращающие один результирующий набор. На таблицу, возвращаемую определяемой пользователем функцией, можно ссылаться в предложении FROM инструкции Transact-SQL, в котором нельзя ссылаться на хранимые процедуры, возвращающие результирующие наборы.

CREATE FUNCTION function_name

( [ { @parameter_name [ AS ] parameter_data_type

[ = default ] }

[ ,...n ]

]

)

RETURNS @return_variable TABLE < table_type_definition >

[ WITH [ ENCRYPTION ] [ SCHEMABINDING ] [ EXECUTE AS Clause ]]

[ AS ]

BEGIN

function_body

RETURN

END

<table_type_definition>:: =

(

{ <column_definition> <column_constraint>

| <computed_column_definition> }

[ <table_constraint> ] [ ,...n ]

)

function_name

Имя пользовательской функции. Скобки после имени функции обязательны даже при отсутствии параметров

@parameter_name

Параметр пользовательской функции. Может быть объявлен один или несколько параметров.

Для функций допускается не более 1 024 параметров. При выполнении функции значение каждого из объявленных параметров должно быть указано пользователем, если для этого параметра не определено значение по умолчанию.

Имя параметра всегда должно начинаться со знака @. Параметры локальны в пределах функции, то есть в разных функциях могут быть использованы одинаковые имена параметров. Аргументы могут использоваться только вместо констант. Они не могут использоваться вместо имен таблиц, имен столбцов или имен других объектов базы данных.

Parameter_data_type

Тип данных параметра. Для параметров функций Transact-SQL допустимы любые типы данных за исключением типа данных timestamp, нескалярные типы cursor и table также не могут быть указаны в качестве типов данных параметров.

[ = default ]

Значение параметра по умолчанию. Если определено значение default, функция выполняется даже в том случае, если для данного параметра значение не указано.

Если параметр функции имеет значение по умолчанию, то для него должно быть указано ключевое слово DEFAULT для получения функцией значения по умолчанию. Применение ключевого слова DEFAULT следует отличать от использования аргументов со значениями по умолчанию в хранимых процедурах, когда не указанный аргумент неявно принимает значение по умолчанию.

<table_type_definition>

Определение табличного типа, включающее определение столбцов и ограничений целостности.

ENCRYPTION

Указывает, что компонент Database Engine преобразует исходный текст инструкции CREATE FUNCTION в скрытый формат. Пользователи, не имеющие доступа к системным таблицам или файлам баз данных, не смогут получить скрытый текст.

SCHEMABINDING

Указывает, что функция привязана к объектам базы данных, которые содержат ссылки на нее. Если аргумент SCHEMABINDING указан, нельзя изменить базовые объекты таким способом, который может повлиять на определение функции. Сначала нужно изменить или удалить само определение функции, чтобы удалить зависимости от объекта, который требуется изменить.

Привязка функции к объектам, на которые она ссылается, удаляется только в следующих случаях:

· При удалении функции.

· При изменении функции инструкцией ALTER, если не указан параметр SCHEMABINDING.

EXECUTE AS

Определяет контекст безопасности, в котором должна быть выполнена функция, т.е. какую учетную запись компонент Database Engine использует при проверке разрешений на объекты, на которые ссылается функция. Это повышает гибкость и безопасность управления разрешениями на цепочки владения между пользовательскими функциями и объектами, на которые они ссылаются.

Пользователям необходимо будет предоставлять только разрешения на саму функцию, без выдачи явных разрешений на объекты, на которые она ссылается. Только пользователь, от имени которого выполняется модуль, должен будет иметь разрешения на объекты, к которым этот модуль обращается.

Допустимые значения EXECUTE AS { CALLER | SELF | OWNER | 'user_name' }.

Function_body

Указывает серию инструкций Transact-SQL, которая в совокупности не вызывает побочных эффектов вроде изменения содержимого таблиц и формирует возвращаемое значение функции.

Для функций, возвращающих табличное значение из нескольких инструкций, аргумент function_body представляет собой серию инструкций Transact-SQL, заполняющих возвращаемую переменную @return_variable.

TABLE

Указывает, что возвращаемым значением функции, возвращающей табличное значение, является таблица. Функциям, возвращающим табличное значение, могут передаваться только константы и локальные переменные.

В функциях, возвращающих табличное значение из нескольких инструкций, переменной @return_variable является переменная TABLE, используемая для сохранения данных и накопления строк, которые будут возвращены в качестве значения функции.

Ни одна из инструкций Transact-SQL в возвращающей табличное значение функции не может возвращать результирующий набор непосредственно пользователю. Единственные данные, которые функция может вернуть пользователю, это таблица, состоящая из строк, вставленных в переменную TABLE, возврат происходит при выполнении инструкции RETURN.

Пример:

В следующем примере создается функция ufnGetUserInfo. В этой функции именем локальной возвращаемой переменной является @retUserInfo. Инструкции в теле функции вставляют строки в эту переменную для создания табличных результатов, возвращаемых этой функцией.

CREATE FUNCTION ufnGetUserInfo (@LoginName nvarchar(50))

RETURNS @retUserInfo TABLE

(

UserID int PRIMARY KEY NOT NULL,

FirstName nvarchar(50) NULL,

JobTitle nvarchar(2);

)

AS

BEGIN

DECLARE

@UserID nvarchar(50),

@FirstName nvarchar(50),

@JobTitle nvarchar(2);

SELECT

@UserID = UserID,

@FirstName = FirstName

FROM User

WHERE LoginName = @LoginName;

IF @UserID IS NOT NULL

BEGIN

SELECT @JobTitle =

CASE

-- Check for employee

WHEN EXISTS(SELECT * FROM Person.Person AS p

WHERE p.UserID = @UserID AND p.PersonType = 'EM')

THEN (SELECT JobTitle

FROM Employee AS e

WHERE e.UserID = @UserID)

-- Check for vendor

WHEN EXISTS(SELECT * FROM Person.Person AS p

WHERE p.UserID = @UserID AND p.PersonType = 'PT')

THEN (SELECT JobTitle

FROM Partner AS pt

WHERE pt.UserID = @UserID)

ELSE NULL

END;

END;

IF @UserID IS NOT NULL

BEGIN

INSERT @retUserInfo

SELECT @UserID, @FirstName, @JobTitle;

END;

RETURN;

END;

SELECT UserID, FirstName, JobTitle

FROM ufnGetUserInfo('admin');

Наши рекомендации