СТАТЬЯ
04.10.01

предыдущая часть | содержание | следующая часть

Глава 7. Использование процедур и пакетов

Содержание части

Код автоматического первоначального исполнения

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

Чтобы определить код автоматического первоначального исполнения для пакета, включите блок BEGIN ... END в тело пакета. Следующее предложение создает тело пакета для пакета BANK_TRANSACTIONS, включая код автоматического первоначального исполнения для того, чтобы инициализировать новую личную переменную TELLER_ID, которая принимает значение текущего пользователя (кассира в банке):

CREATE PACKAGE BODY bank_transactions AS
  teller_name VARCHAR2;
  PROCEDURE do_journal_entry(acct NUMBER, kind CHAR) IS
    BEGIN ... END;
  PROCEDURE credit_account (acct NUMBER, credit NUMBER) IS
    BEGIN ... END;
  PROCEDURE debit_account (acct NUMBER, debit NUMBER) IS
    BEGIN ... END;
  PROCEDURE apply_transaction;
  PROCEDURE enter_transaction(acct NUMBER, kind CHAR,
                     amount NUMBER, teller_id VARCHAR2) IS
    BEGIN ... END;
BEGIN
  SELECT USER INTO teller_id FROM dual;
END bank_transactions;

Перекрытие имен пакетированных процедур

PL/SQL позволяет нескольким процедурам в одном и том же пакете иметь одинаковые имена. Эта возможность полезна в ситуациях, когда вы хотели бы, чтобы процедура могла принимать аргументы различных типов данных. Хорошим примером перекрытия имен пакетированных процедур служит процедура PUT_LINE в пакете DBMS_OUTPUT; см. приложение A.

Именование процедур, функций и пакетов

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

Недействительность пакетов и состояние пакета в сессии

Каждая сессия, обращающаяся к пакетированному конструкту, имеет свой собственный экземпляр (инстанциацию) соответствующего пакета, включая сохраняющееся состояние всех его общих и личных переменных, курсоров и констант. Все инстанциации пакетов, используемых сессией, могут быть потеряны, если во время работы сессии какой-либо из инстанциированных ею пакетов становится недействительным и перекомпилируется. Например, если сессия S инстанциирует пакеты P1 и P2, и P1 становится недействительным и перекомпилируется (скажем, как результат некоторого типа операции DDL), то сессия S теряет обе инстанциации пакетов P1 и P2. В таких ситуациях, при первой попытке сессии обратиться к любому конструкту инстанциации пакета, ставшего недействительным, эта сессия получит следующее сообщение об ошибке:

ORA-04068: existing state of packages has been discarded
           (существующее состояние пакетов было потеряно)

Замечание: При очередном вызове сессией такого пакета, этот пакет повторно инстанциируется для сессии, и ошибки не будет.

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

Допустимые предложения и ограничения для процедур и пакетов

Тело независимой процедуры или пакетированной процедуры может быть любым законным блоком PL/SQL, который может содержать любые предложения DML, включая SELECT (которое должно включать фразу INTO или быть предложением SELECT в определении курсора), SELECT ... FOR UPDATE, INSERT, UPDATE, DELETE или LOCK, а также любой код PL/SQL.

Процедура, которая включает предложения управления транзакциями COMMIT, ROLLBACK и SAVEPOINT, не может вызываться из триггера или из процедуры, участвующей в распределенной транзакции; в противном случае возвращается ошибка времени выполнения.

Обзор SESSION_ROLES не работает внутри хранимой процедуры. Хотя пользователям PL/SQL недоступны некоторые возможности ORACLE (например, предложение COMMIT в программной единице PL/SQL не может включать опцию FORCE), такие возможности предоставляются стандартными пакетированными процедурами. Эти процедуры описываются в приложении A этого документа.

Следующий перечень объясняет особенности использования типов данных LONG и LONG RAW внутри программных единиц PL/SQL:

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

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

Создание такого объекта без ошибок, т.е. успешная компиляция процедуры или пакета, требует следующих дополнительных привилегий:

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

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

Привилегия EXECUTE по процедуре дает пользователю право исполнять процедуру, принадлежащую другому пользователю. Привилегированные пользователи выполняют процедуру под доменом защиты владельца этой процедуры. Следовательно, такие пользователи никогда не обязаны иметь привилегии на объекты, адресуемые в процедуре. Это обстоятельство позволяет более упорядоченно и эффективно организовать стратегии защиты приложений и их применений. Более того, все процедуры и пакеты хранятся в словаре данных (т.е. в табличном пространстве SYSTEM). Никакие квоты не управляют количеством памяти, доступным пользователю, создающему процедуры и пакеты.

Обработка ошибок

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

Определенные пользователем сообщения об ошибках возвращаются с помощью процедуры RAISE_APPLICATION_ERROR:

RAISE_APPLICATION_ERROR(номер_ошибки, 'текст')

Этот вызов прекращает исполнение процедуры, откатывает все изменения, сделанные процедурой, и возвращает специфицированные пользователем номер ошибки и текст сообщения. НОМЕР ОШИБКИ должен быть целым в диапазоне от -20000 до -20999, а ТЕКСТ должен быть символьным выражением, не превышающим 2K байт (более длинные сообщения игнорируются). Код ошибки -20000 должен применяться как групповой номер для сообщений, когда важно отнести источник информации к пользователю, но уникальность номера ошибки не требуется.

Процедура RAISE_APPLICATION_ERROR часто используется в обработчиках исключений или в логике кода PL/SQL. Например, следующий обработчик исключений выбирает строку для ассоциированного определенного пользователем сообщения об ошибке, а затем вызывает процедуру RAISE_APPLICATION_ERROR:

...
WHEN NO_DATA_FOUND THEN SELECT error_string INTO message FROM error_table, V$NLS_PARAMETERS V WHERE error_number = -20101 AND LANG = v.value AND v.name = "NLS_LANGUAGE"; raise_application_error(-20101, message);
...

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

Объявление исключений и программы обработки исключений

Определяемые пользователем исключения явно определяются и возбуждаются в блоке PL/SQL, чтобы управлять обработкой ошибок, специфичных для приложения. Когда исключение ВОЗБУЖДАЕТСЯ (сигнализируется), нормальное исполнение блока PL/SQL прекращается, и вызывается программа, называемая обработчиком исключения. Для обработки любого внутреннего или определенного пользователем исключения может быть написан специальный обработчик исключений.

Код приложения может проверять на условие, требующее специальных действий, с помощью предложения IF. Если существует условие ошибки, доступны две возможности:

Рис.7-1. Исключения и определенные пользователем ошибки

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

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

ОБЪЯВЛЯЙТЕ обработчик пользовательских исключений в теле процедуры или пакета (для личных исключений) или в спецификации пакета (для общих исключений). ОПРЕДЕЛЯЙТЕ обработчик исключений в теле процедуры (независимой или пакетированной).

Необрабатываемые исключения

В программных единицах PL/SQL в базе данных, необрабатываемое условие определенной пользователем или внутренней ошибки, которое не перехватывается соответствующим обработчиком исключений, вызывает неявный откат этой программной единицы. Если программная единица включает предложение COMMIT до той точки, в которой встретилось необрабатываемое исключение, то неявный откат программной единицы может быть выполнен лишь до места предыдущего commit.

Кроме того, необрабатываемые исключения в программе PL/SQL, хранящейся в базе данных, распространяются назад в приложение клиента, вызвавшее эту программную единицу. В этом приложении откату будет подвергнут лишь вызов программной единицы (а не все приложение), так как этот вызов был послан к базе данных как предложение SQL. Если вы сталкиваетесь с тем, что хранимая программная единица PL/SQL возвращает вам необработанное исключение, то такую программную единицу необходимо найти и исправить. Ваше приложение может также перехватывать необработанные исключения от хранимых программных единиц и обрабатывать такие ошибки. Для информации о том, как обрабатывать исключения при вызовах удаленных процедур, обратитесь к странице 11-5.

Идентификация ошибок компиляции для процедур и пакетов

Если при создании, замещении и компиляции процедуры или пакета имеют место ошибки программирования (такие как незаконный синтаксис или некорректные полномочия защиты), то возвращается ошибка, специфичная для инструмента, которым вы пользуетесь. SQL*DBA возвращает следующее сообщение, если при компиляции процедуры или пакета встретились ошибки компиляции:

DBA-00072: Warning: объект created with compilation errors
           (Предупр: объект создан с ошибками компиляции)

где "объект" - имя только что созданной процедуры или пакета.

Чтобы выдать все ошибки, ассоциированные с последней созданной процедурой или пакетом, используйте команду SQL*DBA SHOW ERRORS. Например, предположим, вы хотите с помощью SQL*DBA создать простую процедуру, которая удаляет записи из таблицы EMP:

CREATE PROCEDURE fire_emp(emp_id NUMBER) AS
  BEGIN
    DELETE FROM emp WHER empno = emp_id;
  END
/

Заметьте, что это предложение CREATE PROCEDURE имеет две ошибки: пропущена буква 'E' в слове WHERE в предложении DELETE, и после слова END отсутствует точка с запятой.

После выполнения предложения CREATE PROCEDURE и получения сообщения об ошибке, предложение SHOW ERRORS возвратило бы следующие строки:

SHOW ERRORS;
ERRORS FOR PROCEDURE FIRE_EMP;
LINE/COL ERROR
-------------- -------------------------------------------------
3/24 PL/SQL-00103: Encountered the symbol "EMPNO" when ...
5/0 PL/SQL-00103: Encountered the symbol "END" when ...

2 rows selected.

Заметьте, что команда SHOW ERRORS сообщает для каждой ошибки номер строки и номер колонки, где встретилась эта ошибка.

Альтернативно, при использовании любого инструмента или приложения вы можете опрашивать следующие обзора словаря данных, чтобы идентифицировать ошибки:

Текст ошибок, ассоциированных с компиляцией процедуры, обновляется при замене (REPLACE) процедуры, и удаляется при удалении (DROP) процедуры.

Оригинальный исходный код можно извлечь из словаря данных с помощью следующих обзоров: ALL_SOURCE, USER_SOURCE и DBA_SOURCE. Обратитесь к приложению D для дополнительной информации об этих обзорах словаря данных.

предыдущая часть | содержание | следующая часть

Дополнительную информацию Вы можете получить в компании Interface Ltd.

Обсудить на форуме Oracle
Отправить ссылку на страницу по e-mail


Interface Ltd.
Тel/Fax: +7(095) 105-0049 (многоканальный)
Отправить E-Mail
http://www.interface.ru
Ваши замечания и предложения отправляйте автору
По техническим вопросам обращайтесь к вебмастеру
Документ опубликован: 04.10.01