Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

СУБД Oracle / Лекции / Лек_ORAC / LA / Особенности процедур и функций

.doc
Скачиваний:
38
Добавлен:
16.04.2013
Размер:
49.15 Кб
Скачать

Особенности работы с процедурами и функциями

В общем виде заголовок процедуры выглядит так:

CREATE [OR REPLACE] PROCEDURE имя_процедуры

[ ( список параметров ) ]

[AUTHID] {CURRENT_USER | DEFINER}]

[DETERMINISTIC]

а заголовок функции, в общем виде выглядит так:

CREATE [OR REPLACE] FUNCTION имя_функции

[ ( список формальных параметров ) ]

[AUTHID] {CURRENT_USER | DEFINER}]

[DETERMINISTIC]

[PARALLEL_ENABLE [(PARTITION in_parm BY

{ANY HASH|RANGE})] ]

[PIPELINED]

[AGGREGATE USING]

Пояснения ключевых слов:

OR REPLACE – повторно создать программный модуль сохранив ранее предоставленные привилегии на его выполнение.

AUTHID – как будет выполняться программа и как должны разрешаться ссылки на объекты: DEFINER – в соответствии с привилегиями владельца объекта, либо CURRENT_USER – в соответствии с привилегиями пользователя вызывающего программу. По умолчанию считается DEFINER.

Примечание. Анонимные блоки и программы выполняются в соответствии с привилегиями пользователя вызывающего программу (CURRENT_USER).

DETERMINISTIC – (детерминированная программа) для одних и тех же входных значений возвращает один и тот же результат. Например, функция INITCAP является детерминированной, а SYSDATE – нет.

PARALLEL_ENABLE – указывает оптимизатору, что функция безопасна для параллельного выполнения. Предложение PARTITION BY доступно только для функций, имеющих параметр in_parm типа REF CURSOR IN, оно сообщает оптимизатору как распределяются входные данные между параллельными процессами.

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

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

Список формальных параметров программы состоит из параметров разделённых запятыми. Синтаксис каждого параметра таков:

имя_параметра [{IN|OUT|IN OUT}] [NOCOPY] тип_данных

[{:= | DEFAULT} значение]

Тип данных может быть %TYPE, %ROWTYPE, NUMBER, DATE, либо текстовый, причём без ограничения по размеру.

По умолчанию параметр считается чисто входным IN.

Ключевое слово NOCOPY указывает, что параметр следует передавать по ссылке, а не по значению. Обычно параметры передаются по значению, при этом создаётся копия параметра и подпрограмма работает именно с копией данных. Однако, если параметр имеет большой объём, то его копирование может замедлить работу программы.

Ещё одной особенностью является то, что при возникновении исключения внутри подпрограммы, выходные параметры, передаваемые по значению (без NOCOPY) не будут изменены в вызывающей программе, а параметры, передаваемые по ссылке (с NOCOPY) будут иметь те значения, которые они получили к моменту возникновения исключения.

Ключевое слово DEFAULT (или :=) применяется только для входного параметра. Такой параметр можно не задавать при вызове программы, в этом случае неуказанный параметр получает значение заданное после ключевого слова DEFAULT (или :=).

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

  • Как отдельная исполняемая инструкция:

PUT_LINE('No Employees Found') ;

  • По стандарту ANSI SQL с ключевым словом CALL:

CALL PUT_LINE('No Employees Found') ;

  • По обычаю PL/SQL с ключевым словом EXECUTE:

EXECUTE PUT_LINE('No Employees Found') ;

В общем виде синтаксис вызова хранимой функции таков:

[имя_схемы.][имя_пакета.]имя_функции[@БД_связь]

[(список параметров)]

Обратите внимание на то, что при совпадении имени схемы и имени пакета может возникать путаница, например, если вы создадите пакет scott с процедурой list, а в схеме scott есть процедура с именем list, то вызов функции scott.list будет неоднозначным. Вывод: называйте свои пакеты не тривиально (например, с префиксами – в стандартном пакете Oracle это “DBMS_”).

Функция может вызываться в любом месте программы, где допустимо использование выражения того же типа, а именно:

  • В операторе присваивания:

sales04 := tot_sales(2004, ‘C’);

  • При задании значения по умолчанию:

DECLARE

sales03 NUMBER DEFAULT tot_sales(2003, ‘C’);

BEGIN

. . .

  • В логическом выражении:

IF tot_sales(2002, ‘C’) > 10000 THEN

. . .

  • В SQL-выражении:

SELECT first_name, surname

FROM sellers

WHERE tot_sales(2001, ‘C’) > 1000

  • Как аргумент в списке параметров другой программы:

SELECT RTRIM(TO_CHAR(SYSDATE, ‘MONTH’)) || ‘ ’

|| TO_CHAR(SYSDATE, ‘DDTH’) FROM DUAL;

В PL/SQL имеет два способа передачи фактических параметров: по позиции или по имени.

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

  • Именованная нотация. Значение аргумента связывается с параметром явно по имени с помощью указания “=>”. В этом случае аргументы можно указывать в любом порядке, а входные параметры, имеющие значения по умолчанию, можно опускать, не зависимо от их положения в списке.

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

Например, если объявлена процедура

CREATE OR REPLACE PROCEDURE hire_employee

(emp_id IN VARCAHAR2,

hire_date IN DATE := SYSDATE,

company_id IN NUMBER := 1

)

. . .

то о следующих вызовах можно сказать…

hire_employee(new_empno); -- правильно

hire_employee(new_empno,’12-Jan-99’); -- правильно

hire_employee(new_empno, ,2); -- НЕ правильно

-- Однако будет правильным такой вызов

hire_employee(new_empno, company_id=>2);

-- или такой вызов

hire_employee(company_id=>2, emp_id=>new_empno);

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

Например, в пакете DBMS определены следующие прототипы процедуры PUT_LINE обеспечивающие её перегрузку:

PUT_LINE(a VARCHAR2);

PUT_LINE(a NUMBER);

PUT_LINE(a DATE);

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

Реально перегрузка используется только в пакетах, хотя может быть и в любом блоке.

Локальная программа – это процедура или функция, определённая в разделе объявлений блока PL/SQL. Область видимости и область действия этой программы ограничена данным блоком.

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

Контрольные вопросы.

  1. В какой секции программы может быть вызвана процедура:

    1. header section

    2. declaration section

    3. execution section

    4. exception section

  2. В какой секции программы может быть вызвана функция:

    1. header section

    2. declaration section

    3. execution section

    4. exception section

  3. Укажите верные утверждения

    1. Если в каком-то месте можно поставить обращение к процедуре, то в этом же месте можно поставить обращение к функции.

    2. Если в каком-то месте можно поставить обращение к функции, то в этом же месте можно поставить обращение к процедуре.

    3. Ни то ни другое не верно.

  4. Ранее отмечалось, что правильными являются вызовы

hire_employee(new_empno, company_id=>2);

hire_employee(company_id=>2, emp_id=>new_empno);

будет ли правильным следующий вызов ?

hire_employee(company_id=>2, new_empno);

ДА/НЕТ

Тут вы можете оставить комментарий к выбранному абзацу или сообщить об ошибке.

Мы не исправляем ошибки в тексте (почему?), но будем благодарны, если вы все же напишите об ошибках.

Соседние файлы в папке LA