Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Разработка и сопровождение БД в среде MS SQL Se...doc
Скачиваний:
316
Добавлен:
14.11.2019
Размер:
1.71 Mб
Скачать

6.8.2. Функции пользователя

В SQL Server 2000 можно создавать функции трех классов:

  • Scalar – возвращают обычное скалярное значение, любого из типов данных, поддерживаемых SQL Server 2000, за исключением типов данных timestamp, text, ntext, image, table и cursor;

  • Inline – возвращают таблицу динамической структуры в виде значения типа данных table, создаваемую единственной командой тела функции SELECT;

  • Multistatement – возвращает обычную таблицу заданной структуры в виде значения типа данных table, при этом количество команд в теле функции не ограничивается.

Все рассмотренные типы функций могут содержать ни одного, один или более входных параметров одного из поддерживаемых SQL Server 2000 типов данных, за исключением типов данных timestamp, table и cursor. В теле функции (за исключением функций типа Inline) разрешается объявление локальных переменных, использование циклов, ветвлений и любых других программных конструкций. Также разрешается вызов других функций и хранимых процедур и создание внутри функций курсоров.

При использовании в функции команд INSERT, UPDATE и DELETE разрешается работать только с наборами данных, хранящихся в переменных типа table и созданными в теле функции. Помимо указанных ограничений при разработке функций следует учитывать, что они не могут возвращать данные непосредственно клиенту, как это может делать хранимая процедура. То есть не разрешается использование в теле функции команды PRINT, а также команды SELECT для непосредственного возвращения данных. Для получения информации о функции можно использовать хранимую процедуру sp_help "имя_ функции".

Функции Scalar. Создание функций этого типа выполняется с помощью команды CREATE FUNCTION, имеющей следующий синтаксис:

CREATE FUNCTION [ owner_name.] function_name

( [ { @parameter_name scalar_parameter_data_type

[ = default ] } [....n ] ] )

RETURNS scalar_return_data__type

[ WITH < function_option> [,...n] ]

[ AS ]

BEGIN

function_body

RETURN sealar_expression

END

Рассмотрим назначение и использование параметров команды.

[ ownername. ] function_name - c помощью этого параметра указывается имя, которое будет присвоено функции (function_name). Дополнительно можно указать и имя владельца (owner_name), которому будет принадлежать создаваемая функция. Это должно быть имя пользователя или роли, имеющихся в базе данных, в контексте которой создается функция. Если имя владельца опущено, то создаваемая функция будет принадлежать пользователю, выполняющему создание функции. При выборе имени функции следует учитывать, что имя должно быть уникальным в пределах владельца. Более того, не должно существовать объектов, принадлежащих тому же владельцу и имеющих аналогичное имя.

@parameter_name sealar_parameter_data_type [ = default ] -используется для определения входных параметров. Каждый параметр должен иметь имя, уникальное в пределах создаваемой функции, и начинаться с символа @. Имя параметра указывается с помощью аргумента @parameter_name. После имени параметра через пробел необходимо указать тип данных (seal ar_parameter_data_type), который будет иметь параметр. Допускается использование любого из поддерживаемых SQL Server 2000 типов данных, включая пользовательские, за исключением типов данных timestamp (rowversion), cursor и table. Дополнительно можно указать значение (default), которое будет автоматически присваиваться параметру, если пользователь явно не указал значение соответствующего параметра при вызове функции. Естественно, значение по умолчанию должно быть того же тина, что и сам параметр.

RETURNS sсalar_return_data_type - c помощью этой конструкции указывается, какой тип данных будет иметь возвращаемое функцией значение. Слово RETURNS является ключевым и должно присутствовать всегда.

WITH <function_option> [,.. .n] - с помощью ключевого слова WITH могут быть указаны дополнительные параметры, с которыми должна быть создана функция. Параметр указывается с помощью конструкции <function_opt1on>, которая имеет следующий синтаксис:

<function_option>::={ENCRYPTION|SCHEMABINDING}

Благодаря ключевому слову ENCRYPTION код команды CREATE FUNCTION, который был использован для создания функции, будет зашифрован, и никто не сможет просмотреть его. Эта возможность позволяет скрыть логику работы функции. Код команд, который используется для создания объектов базы данных, хранится в столбце text системной таблицы syscomments и без шифрования может быть просмотрен с помощью обычной команды SELECT.

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

AS - после этого ключевого слова следует определение собственно тела функции. В принципе, ключевое слово AS может быть опущено.

BEGIN...END - между этими ключевыми словами указывается набор команд (function_body), которые собственно и будут являться телом функции.

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

Функции Inline. Создание функций этого типа выполняется с помощью команды CREATE FUNCTION, имеющей следующий синтаксис:

CREATE FUNCTION [owner_name.] function_name

( [ {@parameter_name scalar_parameter_data_type

[= default] } [,...n ] ] )

RETURNS TABLE

[ WITH <function_option> [ ,...n ] ]

[AS]

RETURN [ ( ] select-stmt [ ) ]

Основная часть параметров, используемая при создании функции типа Inline, аналогична параметрам функций типа Scalar. Тем не менее, создание функций типа Inline имеет свою специфику. После ключевого слова RETURNS всегда должно указываться ключевое слово TABLE. Таким образом, функция Inline должна строго возвращать значение типа данных table. Как видно, структура возвращаемого значение типа table не указывается явно при описании собственно типа данных. Вместо этого сервер будет автоматически использовать для возвращаемого значения table структуру, возвращаемую запросом SELECT, который является единственной командой функции. Код этого запроса задается с помощью аргумента select-stmt. Как видно из синтаксиса команды, код запроса может быть дополнительно помещен в круглые скобки.

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

Функции Multi-statement. Создание функций этого типа выполняется с помощью команды CREATE FUNCTION, имеющей следующий синтаксис:

CREATE FUNCTION [owner_name.] function_name

( [ { @parameter_name scalar_parameter_data_type

[ = defauTt ] } [ ,...n ] ] )

RETURNS @return_variable TABLE < table_type_definition >

[WITH <function_option> [,...n ]]

[AS]

BEGIN

function_body

RETURN

END

Функции Multi-statement, как и функции Inline, возвращают значение типа table. Однако, в отличие от функций типа Inline, при создании функций Multi-statement необходимо явно задать структуру возвращаемого значения. Эта структура указывается непосредственно после ключевого слова TABLE и, таким образом, является частью определения возвращаемого типа данных. Для описания структуры используется конструкция <table_type_definition>, которая имеет следующий синтаксис:

<table_type_definition> :: =

( { <column_definition> | <table_constraint> } [ ….n ] )

Синтаксис конструкций <col umn_def inition> и <table_constraint> пол­ностью соответствует одноименным структурам, используемым при создании обычных таблиц с помощью команды CREATE TABLE. Набор данных, которые будут возвращены, должен формироваться с помощью команд INSERT, выполняемых в теле функции. В теле функции допускаются различные конструкции Transact-SQL, которые могут контролировать значения, размещаемые в наборе строк (row set). При работе с командой INSERT необходимо явно указать имя объекта, в который необходимо вставить строки. Поэтому в функциях Multi-statement, в отличие от функций Inline, необходимо присвоить какое-то имя значению table. Это имя и указывается с помощью параметра Return_variable.

Завершение работы функции, помимо ошибок выполнения, происходит в случае, когда в коде функции встречается ключевое слово RETURNS. В отличие от функций типа Scalar при использовании команды RETURNS не нужно указывать значение, которое должно быть возвращено. Сервер автоматически возвратит набор данных типа table, имя и структура которого была указана после ключевого слова RETURNS. Напомним, что в теле функции может быть указано более одной команды RETURNS.

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

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

  • предварительное удаление функции с помощью команды DROP FUNCTION и последующее создание обновленной функции с помощью команды CREATE FUNCTION;

  • сохранение под именем существующей функции нового кода с помощью команды ALTER FUNCTION.

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

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

Для изменения функций типа Scalar используется следующий синтаксис:

ALTER FUNCTION [owner_name.] function_name

( [ { @parameter_name scalar_parameter_data_type

[ = default ] } [ ,...n ] ] )

RETURNS scalar_return_data_type

[ WITH < function_option> [,...n] ]

[ AS ]

BEGIN

function_body

RETURN scalar_expression

END

Для изменения функций типа Inline используется следующий синтаксис:

ALTER FUNCTION [owner_name.] function_name

( [ { @parameter_name scalar_parameter_data_type

[ = default ] } [ ,...n ] ] )

RETURNS TABLE

[ WITH < function_option > [ ,...n ] ]

[ AS ]

RETURN [ ( ] select-stmt [ ) ]

Для изменения функций типа Multi-statement используется следующий синтаксис:

ALTER FUNCTION [owner_name.] function_name

( [ { @parameter_name scalar_parameter_data_type

[ = default ] } [ ,...n ] ] )

RETURNS @return_vanable TABLE < table_type_definition >

[WITH < function_option > [ ,…n ] ]

[AS ]

BEGIN

function_body

RETURN

END

Как видно, синтаксис команды ALTER FUNCTION напоминает синтаксис команды CREATE FUNCTION. Действительно, при внесении изменения в функцию пользователь должен указывать полностью весь код функции. В этом плане изменение функции с помощью команды ALTER FUNCTION мало чем отличается от удаления и последующего создания функции, так как объем работы в обоих случаях практически одинаков. Упростить изменение функции помогает системная хранимая процедура sp_helptext, позволяющая получить код Transact-SQL, с помощью которого создан тот или иной объект базы данных. Получить код функции можно только в том случае, если при ее создании не использовался параметр WITH ENCRYPTION. В противном случае из-за шифрования код просмотреть не удастся.

Когда функция становится ненужной, ее можно удалить. Для удаления функций используется команда DROP FUNCTION, имеющая следующий синтаксис:

DROP FUNCTION { [ owner_name. ] function_name } [ ,...n ]

Команда имеет одинаковый синтаксис для всех типов функций. Для удаления функции достаточно указать лишь ее имя. Дополнительно может быть указано еще и имя владельца функции. Это обязательно в случае, если необходимо удалить функцию, принадлежащую не текущему пользователю и не владельцу базы данных (пользователю dbo).

С помощью одной команды DROP FUNCTION можно удалить множество функций, перечислив их имена через запятую. Например, для удаления всех функций, созданных в предыдущих разделах, можно выполнить следующую команду:

DROP FUNCTION Func1, Func2. Func3