Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Плещёв БД 2013-03-15.doc
Скачиваний:
0
Добавлен:
10.01.2020
Размер:
12.65 Mб
Скачать

5.4.6. Процедуры и функции

Процедура/функция (подпрограмма) объявляется в конце раздела Declare любого блока PL/SQL и имеет сле­ду­ющую структуру:

Procedure/Function <имя> [(<объявление параметра>, ...)] [Return <тип>]

{As | Is}

[<объявления локальных объектов>]

Begin

<операторы обработки>

Return [<возвращаемое значение функции> --завершение работы]

[Exeption

<операторы обработки исключительных ситуаций, включая Return>]

End [<имя процедуры/функции>];

Параметр объявляется в виде:

<имя параметра> [in | out | in out] <тип параметра>[:=<значение>]

В типе параметра размерность не указывается.

Допускается позиционная и именованная запись фактических пара­мет­ров (<имя формального параметра>=<значение параметра>) одновре­мен­­­но (позиционные параметры располагаются в начале списка параметров).

Пример создания функции возвращающей сумму продаж товаров.

Create or replace function Sumprod () return number as

Sump number := 0.0;

Begin Select sum(stoim) into Sump from prodaga_tovarov; return Sump; End;

Для того чтобы подпрограммы хранились в базе данных и были об­ще­доступными в виде хранимых процедур или функций, они должны быть созданы SQL‑операторами:

Create[or replace] procedure/function [<схема>.]<имя процедуры/функции>

<параметры и тело процедуры/функции>

or replace ‑ указывает замещение старого текста подпрограммы.

Вызов хранимых подпрограмм

Одна хранимая подпрограмма может вызывать другую. Обращения к хранимым функциям могут появляться в про­це­дур­ных предложениях, но не в предложениях SQL.

Приложение предкомпилятора или приложение OCI может вы­зывать хранимые подпрограммы из анонимных блоков PL/SQL.

Пример вызова процедур create_dept из предкомпилятора.

exec sql execute

begin create_dept(:name, :location); end;

end-exec;

Фактические параметры :name и :location - это хост-переменные (пе­­ре­менные, объявленные во внешней среде, например в языках програм­мирования).

Пример вызова процедуры create_dept из пакет emp_actions.

exec sql execute

begin emp_actions.create_dept(:name, :location); end;

end-exec;

Пример вариантов вызова процедуры create_dept из SQL*Plus.

sql> execute create_dept('marketing', 'new york');

sql> begin create_dept('marketing', 'new york'); end;

Пример создания процедуры вывода в таблицу сум­мы продаж това­ров и налога на добавленную стоимость за текущий день.

Create or replace

Procedure z_ prodaga_tovarov (stoimost_tovara in number, nds in number :=0.2) as

Begin Insert into prodaga_tovarov

values (sysdate, stoimost_tovara , nds * stoimost_tovara);

End;

Для уничтожения подпрограммы используется SQL‑оператор:

Drop procedure/function [<схема>.]<имя процедуры/функции>

Перезагружаемыми подпрограммами называются подпрограммы с одинаковыми именами, но с различными параметрами. Oracle автома­ти­чес­ки вызывает нужную подпрограмму по набору фактических параметров (ар­гументов).

Для вызова встроенной подпрограммы, при наличии одноименной подпрограммы пользователя, эта подпрограмма уточняется именем пакета standard (x:=standard.sign(x)).

Рекурсивная подпрограмма содержит вызов этой же подпрограммы. Каждый рекурсивный вызов создает новый набор всех элементов под­прог­раммы (параметры, переменные, курсоры, исключения и др.).

Пример рекурсивной подпрограммы вычисления факториала числа n: n!=n*(n-1)!

Function factorial (n integer) Return integer is

Begin if n=1 then return 1; else return n* factorial (n-1); endif; end factorial;

Пример процедуры, которая устанавливает новый оклад сотруднику.

procedure izmenit_oklad (tabn number, novii_oklad real) is

oklad_otsutstvuet exception; --исключение (п. 5.4.9)

begin

if novii_oklad is null then raise oklad_otsutstvuet;--генерация исключения (п. 5.4.9)

else update oklad set oklad = novii_oklad where tn=tabn;

end if;

exception --обработка исключений (п. 5.4.9)

when no_data_found then --отстутствует строка в запросе

insert into sotr_audit values ('Отсутствует сотрудник с таб. N ', tabn);

when oklad_otsutstvuet then --отсутствует значение нового оклада

insert into sotr_audit values (‘Оклад отсутствует для сотр. c таб. N ’,tabn);

end izmenit_oklad;

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

function oklad_ok (oklad real, koddolg real) return boolean is

min_oklad real; max_oklad real;

begin select minoklad, maxoklad into min_oklad, max_oklad from dolgnosti

where kd=koddolg; return (oklad >= min_oklad) and (oklad <= max_oklad);

end oklad _ok;

Пакетированные подпрограммы

Упреждающие объявления также позволяют вам группировать ло­­­ги­чес­ки связанные подпрограммы в пакет. Спецификации под­прог­рамм идут в спецификацию пакета, а тела подпрограмм - в тело паке­та, где они не видимы приложениям. Пакеты скрывают детали реализа­ции. Вы можете определять в теле пакета подпрограммы, не объявляя их спе­цификаций в спецификации пакета. Однако такие подпрограммы мож­но вызывать только изнутри пакета.

Пример

package emp_actions is -- спецификация пакета

procedure hire_employee (empno number, ename char, ...);

procedure fire_employee (emp_id number);

end emp_actions;

package body emp_actions is -- тело пакета

procedure hire_employee (empno number, ename char, ...) is

begin insert into emp values (empno, ename, ...); end hire_employee;

procedure fire_employee (emp_id number) is

begin delete from emp where empno = emp_id; end fire_employee;

end emp_actions;