Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции О_о DataBase.doc
Скачиваний:
5
Добавлен:
01.05.2025
Размер:
8.68 Mб
Скачать
    1. Функции, определенные пользователем

Функции, определенные пользователем (UDF – User Defined Functions) расширяют возможности, предоставляемые встроенными функциями SQL, и их можно использовать везде, где могут использоваться встроенные функции. Функцию, определенную пользователем, можно создать как функцию с источником, реализация которой наследуется от какой-либо другой существующей функции, или как внешнюю функцию, которая написана на одном из языков программирования.

Функции с источником, определенные пользователем

Как указывалось выше, при определении особых типов данных система автоматически генерирует только функции преобразования исходного типа данных в новый тип и наоборот, а также функции сравнения. Никакие другие функции, в том числе арифметические или агрегатные для особых типов, создаваемых на основе числовых, не генерируются. Если возникает необходимость использовать подобные функции с операндами созданного особого типа, такие функции должны быть созданы пользователем и зарегистрированы на основе существующих аналогичных функций – функций-источников. Такая регистрация выполняется с помощью предложения CREATE FUNCTION, имеющего следующий синтаксис:

CREATE FUNCTION имя_функции ( список_параметров )

RETURNS тип_данных_результата

SOURCE имя_функции_источника ( тип_операнда, … )

Имя функции – определяет имя новой функции, которое может совпадать с именем какой-либо существующей функции, используемой в качестве источника.

Список параметров – задает имена и типы данных параметров функции, перечисленные через запятую. Количество параметров в списке должно соответствовать количеству операндов функции-источника, на основании которой создается данная функция.

Имя функции вместе с количеством и типами данных параметров должно быть уникальным. Длина, точность и масштаб, указываемые для соответствующих типов данных, во внимание не принимаются. Так, например, типы параметров VARCHAR(20) и VARCHAR(35) считаются одинаковыми. Поэтому при указании соответствующих типов данных значения длины, точности и масштаба можно не указывать, кодируя только пустые скобки. Так, вместо VARCHAR(20) можно указать VARCHAR(), а вместо DECIMAL(9,3) – DECIMAL().

RETURNS – определяет тип данных результата функции.

SOURCE – указывает, что создаваемая функция реализуется с помощью другой функции (функции-источника), уже известной менеджеру базы данных. Функцией-источником может быть любая встроенная функция, за некоторыми исключениями (например, COALESCE, NULLIF, VALUE), или ранее определенная пользователем скалярная функция. Конструкция SOURCE может быть указана только для скалярной или агрегатной функции; ее нельзя указывать для табличной функции. Конструкция SOURCE указывает на идентичность создаваемой функции с функцией-источником, т.е. там, где требуется выполнить создаваемую функцию, на самом деле, будет выполнена функция-источник.

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

В качестве имени функции (создаваемой и функции-источника) может быть указан знак операции, заключенный в двойные кавычки, например: "+". Это позволяет использовать знаки операций с операндами соответствующих типов.

Примеры:

Пусть был определен особый тип данных MPH на основе встроенного типа INTEGER:

CREATE DISTINCT TYPE MPH AS INTEGER WITH COMPARISON

Для созданного типа данных MPH сгенерированы необходимые функции преобразования INTEGER(MPH) и MPH(INTEGER).

Пример 1. Необходимо предоставить возможность использовать для особого типа данных MPH операцию сложения ("+"):

CREATE FUNCTION "+" (MPH, MPH)

RETURNS MPH

SOURCE "+" (INTEGER, INTEGER)

При использовании операции сложения для операндов типа MPH функция преобразования INTEGER(MPH) преобразует операнды к типу INTEGER, затем выполняется встроенная функция (операция) сложения, результат которой (типа INTEGER) с помощью функции преобразования MPH(INTEGER) преобразуется к типу MPH.

Пример 2. Необходимо предоставить возможность использовать для колонки типа MPH агрегатную функцию AVG(колонка):

CREATE FUNCTION AVG_MPH (MPH)

RETURNS MPH

SOURCE AVG (INTEGER)

Здесь также выполняются преобразования INTEGER(MPH) для операнда функции AVG и MPH(INTEGER) для результата.

В данном примере для функции использовано собственное имя – AVG_MPH. Можно, вместо этого, использовать и существующее имя функции – AVG:

CREATE FUNCTION AVG (MPH)

RETURNS MPH

SOURCE AVG (INTEGER)

Внешние функции, определенные пользователем

Внешние функции, определенные пользователем, могут быть скалярными или табличными и могут быть написаны с использованием разных языков программирования (Java, C, …). Мы ограничимся рассмотрением функций, написанных на языке SQL PL.

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

Табличная функция возвращает таблицу и может быть вызвана только из конструкции FROM предложения SELECT; при этом вызов табличной функции должен начинаться с ключевого слова TABLE с обязательным переименованием: TABLE (имя_функции (списак_аргументов)) AS корреляционное_имя

Внешние функции, определенные пользователем, регистрируются в системе также с помощью предложения CREATE FUNCTION, имеющего следующий синтаксис:

CREATE FUNCTION имя_функции ( список_параметров )

RETURNS тип_возвращаемого_результата

LANGUAGE SQL

[ [ NOT ] DETERMINISTIC ]

[ [ NO ] EXTERNAL ACTION ]

[ уровень_доступа_к_SQL_данным ]

[ CALLED ON NULL INPUT ]

тело_функции

Здесь имя функции – определяет имя новой функции, которое может совпадать с именем какой-либо существующей функции, используемой в качестве источника; список параметров – задает имена и типы данных параметров функции, перечисленные через запятую. Имя функции вместе с количеством и типами данных параметров должно быть уникальным (длина, точность и масштаб, указываемые для соответствующих типов данных, во внимание не принимаются).

RETURNS – определяет тип возвращаемого функцией результата. Тип возвращаемого результата, в зависимости от типа функции (скалярная или табличная), представляется по-разному.

Результатом скалярной функции является одно значение, поэтому для скалярной функции RETURNS указывает тип результата и имеет следующий вид: RETURNS тип_данных.

Результатом табличной функции является таблица, поэтому для табличной функции RETURNS представляет структуру таблицы и имеет следующий вид:

RETURNS TABLE ( список_колонок )

Список колонок состоит из перечисленных через запятую имен и типов данных колонок. Все имена колонок должны быть разными.

LANGUAGE SQL – подчеркивает, что тело функции написано на языке SQL PL.

DETERMINISTIC или NOT DETERMINISTIC: DETERMINISTIC – указывает, что функция возвращает один и тот же результат для одних и тех же значений аргументов; NOT DETERMINISTIC – указывает, что для одних и тех же значений аргументов функция может возвратить разные результаты. Примером NOT DETERMINISTIC функции является функция, возвращающая случайное значение. Должно быть указано NOT DETERMINISTIC, если в теле функции используются какие-либо специальные регистры или вызов другой NOT DETERMINISTIC функции. Если данная конструкция опущена при определении функции, по умолчанию принимается NOT DETERMINISTIC.

EXTERNAL DATA или NO EXTERNAL DATA – указывает, выполняет (EXTERNAL DATA) или не выполняет (NO EXTERNAL DATA) функция некоторые действия, которые изменяют состояние внешнего, по отношению к базе данных, объекта (внешние действия). Если данная конструкция не указана, по умолчанию принимается EXTERNAL DATA.

Уровень доступа к данным SQL – указывает, какой тип предложений SQL используется в теле функции. Может быть задан один из трех уровней доступа:

CONTAINS SQL – указывает, что в теле функции не могут быть использованы предложения SQL, которые читают (SELECT) и/или изменяют (INSERT, DELETE, UPDATE) данные;

READS SQL DATA – значение, принимаемое по умолчанию; указывает, что в теле функции не могут быть использованы предложения SQL, изменяющие данные;

MODIFIES SQL DATA – допускается только для табличных функций; указывает, что в теле функции могут быть использованы предложения SQL, модифицирующие данные в таблицах. Допускаются все предложения SQL, которые могут быть включены в динамическое составное предложение. Табличная SQL функция, модифицирующая данные, позволяет объединить модификацию данных и возврат некоторого результирующего множества записей.

CALLED ON NULL INPUT – указывает, что функция вызывается и в том случае, если какие-либо из аргументов имеют NULL значение. Функция также может возвращать NULL значение. Если не указано, по умолчанию принимается такое же поведение функции.

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

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

Примечания:

  • если тело SQL функции содержит ссылки на какие-либо специальные регистры, представляющие дату и время, все ссылки возвращают одно и то же значение. Это же значение возвращают и ссылки на специальные регистры даты и/или времени, использованные в предложении, в котором вызывается данная функция;

  • в теле SQL функции не может быть прямой или косвенный рекурсивный вызов этой же функции.

Ограничения на доступ к таблице:

  • если функция определена как READS SQL DATA, она не может обращаться к таблице, модифицируемой предложением SQL, в котором данная функция вызывается. Например, если функция BONUS() определена как READS SQL DATA, и выполняется следующее предложение SQL:

UPDATE EMPLOYEE SET SALARY = SALARY + BONUS(EMPNO)

Тогда никакие предложения SQL, включенные в функцию BONUS, не могут читать данные из таблицы EMPLOYEE;

  • если функция определена как MODIFIES SQL DATA, чтение из таблиц, модифицируемых данной функцией (и в определении функции, и в предложении, вызывающем функцию), не допускается;

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

Примеры:

Пример 1. Определить скалярную функцию, которая возвращает значение тангенса для некоторого угла, используя существующие функции вычисления синуса и косинуса.

CREATE FUNCTION TAN (X DOUBLE)

RETURNS DOUBLE

LANGUAGE SQL

CONTAINS SQL

NO EXTERNAL ACTION

DETERMINISTIC

RETURN SIN(X)/COS(X)

Пример 2. Определить скалярную функцию, которая переписывает символы некоторой заданной строки в обратном порядке.

CREATE FUNCTION REVERSE(Instr VARCHAR(4000))

RETURNS VARCHAR(4000)

DETERMINISTIC

NO EXTERNAL ACTION

CONTAINS SQL

BEGIN ATOMIC

DECLARE Revstr, Reststr VARCHAR(4000) DEFAULT '';

DECLARE Len INT;

IF Instr IS NULL

THEN RETURN NULL;

END IF;

SET (Reststr, Len) = (Instr, LENGTH(Instr));

WHILE Len > 0 DO

SET (Revstr, Reststr, Len) = (SUBSTR(Reststr, 1, 1) || Revstr,

SUBSTR(Reststr, 2, Len - 1), Len - 1);

END WHILE;

RETURN Revstr;

END

Пример 3. Определить табличную функцию, которая возвращает список сотрудников некоторого отдела, заданного его номером.

CREATE FUNCTION DEPTEMPLOYEES (DeptNo CHAR(3))

RETURNS TABLE (EmpNo CHAR(6), LastName VARCHAR(15), FirstName VARCHAR(12))

LANGUAGE SQL

READS SQL DATA

NO EXTERNAL ACTION

DETERMINISTIC

RETURN SELECT EmpNo, LastName, FirstName

FROM EMPLOYEE

WHERE EMPLOYEE.WorkDept = DEPTEMPLOYEES.DeptNo

Пример 4. Изменить табличную функцию из примера 3, добавив в нее регистрацию (в таблице AUDIT) всех обращений к этой функции.

CREATE FUNCTION DEPTEMPLOYEES (DeptNo CHAR(3))

RETURNS TABLE (EmpNo CHAR(6), LastName VARCHAR(15), FirstName VARCHAR(12))

LANGUAGE SQL

MODIFIES SQL DATA

NO EXTERNAL ACTION

DETERMINISTIC

BEGIN ATOMIC

INSERT INTO AUDIT VALUES (USER,

'Table: EMPLOYEE Prd: DEPTNO = ' || DeptNo);

RETURN SELECT EmpNo, LastName, FirstName

FROM EMPLOYEE

WHERE EMPLOYEE.WorkDept = DEPTEMPLOYEES.DeptNo;

END

Пример 5. Определить табличную функцию, которая изменяет количество некоторого элемента, заданного своим номером (ItemNo), в таблице оборудования (INVENTORY), на некоторую заданную величину (Amount). Функция должна вернуть обновленные данные для указанного элемента.

CREATE FUNCTION UPDATEINV(ItemNo VARCHAR(20), Amount INTEGER)

RETURNS TABLE (ProductName VARCHAR(20), Quantity INTEGER)

LANGUAGE SQL

MODIFIES SQL DATA

BEGIN ATOMIC

UPDATE INVENTORY AS I

SET Quantity = Quantity + Amount WHERE I.ItemID = ItemNo;

RETURN SELECT I.ItemName, I.Quantity

FROM INVENTORY AS I WHERE I.ItemID = ItemNo;

END

Приведенную в примере функцию можно вызвать следующим образом:

SELECT ProductName, Quantity

FROM TABLE(UPDATEINV('ISBN-0-8021-3424-6', 5)) AS T

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

SELECT NEWITEM.Id, TF.ProductName, TF.Quantity

FROM (VALUES ('ISBN-0-8021-3424-6', 2),

('ISBN-0-8021-4612-1', 5)) AS NEWITEM(Id, Quantity),

TABLE(UPDATEINV(NEWITEM.Id, NEWITEM.Quantity)) AS TF

В данном примере в конструкции FROM предложения SELECT использована конструкция VALUES для генерации временной таблицы (NEWITEM), строки которой должны быть модифицированы функцией

UPDATEINV. Так как колонки таблицы NEWITEM указываются в качестве аргументов функции

UPDATEINV, имена колонок должны быть уточнены именем таблицы. Кроме того, вызов табличной функции указывается последним в конструкции FROM.

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

PRICELIST.

WITH NEWINV(ItemNo, Quantity) AS

(

SELECT Id, TF.Quantity

FROM (VALUES ('ISBN-0-8021-3424-6', 5),

('ISBN-0-8021-4612-1', 10)) AS NEWITEM(Id, Q),

TABLE(UPDATEINV(NEWITEM.Id, NEWITEM.Q)) AS TF

)

SELECT ItemNo, Quantity, UnitPrice,

(Quantity * UnitPrice) AS TotalInvValue

FROM NEWINV, PRICELIST

WHERE ItemNo = PRICELIST.ItemID