Пакет – это программная единица, объединяющая логически связанные типы PL/SQL, идентификаторы и подпрограммы. При обращении к любому программному элементу пакета в память загружается весь пакет. Пакет остается в системной глобальной области (SGA) до тех пор, пока происходит обращение к пакетным объектам.
Пакет состоит из двух частей, которые хранятся в базе данных по отдельности:
· Спецификация – интерфейс для прикладных программ. В спецификации содержатся описания типов, переменных, констант, исключений, курсоров, а также подпрограмм, которые должны быть доступы для всех. Сами программные коды в спецификации не представляются.
· Тело – содержит программный код подпрограмм, описанных в спецификации, а также идентификаторы и подпрограммы, которые могут использоваться только внутри пакета.
· Модульность. Пакет позволяет объединить логически связанные программные конструкции в единый модуль.
· Облегченный дизайн. Вы можете создать и откомпилировать спецификацию пакета отдельно от тела, предоставив тем самым необходимый интерфейс для прикладной программы. Программная логика пакетных объектов (тело пакета) может быть создана и откомпилирована позже.
· Избирательный доступ к информации. Разработчик приложения может решать, какие программные конструкции должны быть скрыты от пользователя, а какие пакетные объекты необходимо сделать доступными. Скрытые объекты необходимо объявить в теле пакета, а общедоступные – в спецификации.
· Общие переменные сессии. Идентификаторы, объявленные в спецификации пакета, действуют в течение всей сессии, в которой они вызывались. Это позволяет сохранять значения, специфичные для сеанса связи с базой данных, и использовать их в различных программных единицах.
· Улучшение производительности. При обращении к любому общедоступному объекту пакета, в память загружается весь пакет. Таким образом, при последующих ссылках на объекты пакета не требуется дисковый ввод/вывод.
· Перезагрузка. Пакеты позволяют перезагружать процедуры и функции. Т.е. Вы можете создать несколько подпрограмм с одним и тем же именем, но разным списком формальных параметров, в одном пакете.
Программные конструкции, составляющие пакет, могут быть общедоступные (Public) или закрытые (Private):
· К общедоступным объектам пакета можно обращаться из любого прикладного средства СУБД, они объявляются в спецификации пакета и определяются в теле пакета
· Закрытые программные конструкции могут быть вызваны только из программных модулей, являющихся частью пакета. Закрытые пакетные объекты объявляются и определяются в теле пакета.
Все объекты, объявленные в спецификации пакета, имеют глобальную область видимости, т.е. во время текущего сеанса все программные конструкции PL/SQL, включая анонимные блоки, могут ссылаться на эти объекты. Объекты, объявленные в теле пакета, скрыты от внешнего окружения пакета, и, следовательно, могут быть вызваны только внутри пакета. Такие объекты имеют локальную область видимости.
CREATE [OR REPLACE] PACKAGE имя_пакета
[AUTHID CURRENT_USER]
IS
список_идентификаторов;
список_спецификаций_подпрограмм;
END [имя_пакета];
имя_пакета – имя пакета
AUTHID CURRENT_USER – указывает, что пакетные подпрограммы должны выполняться с привилегиями текущего пользователя
список_идентификаторов – объявление общих идентификаторов (типов, переменных, констант, курсоров, исключений)
список_спецификаций_подпрограмм – объявление общих подпрограмм пакета
Создадим, например, пакет, объединяющий общедоступную переменную для хранения значения комиссионных и процедуру, которая предназначена для присвоения нового значения этой переменной.
SQL> CREATE OR REPLACE PACKAGE comm_package IS
2 g_comm NUMBER := 10;
3 PROCEDURE reset_comm (v_comm IN NUMBER);
4 END comm_package;
5 /
Package created.
Пакет не может быть вложен в другой блок PL/SQL (именованный или анонимный) – объявление пакета обязательно должно быть на верхнем уровне вложенности. Поэтому, например, не допускается объявление пакета в декларативной секции анонимного блока PL/SQL.
SQL> DECLARE
2 PACKAGE l_package IS
3 g_comm NUMBER := 10;
4 PROCEDURE reset_comm (v_comm IN NUMBER);
5 END l_package;
6 BEGIN
7 DBMS_OUTPUT.put_line(l_package.g_comm);
8 END;
9 /
DECLARE
*
ERROR at line 1:
ORA-06550: line 2, column 4:
PLS-00232: nested packages not permitted
Несмотря на то, что в среде SQL*Plus нет возможности создать не хранимый пакет, прикладные пакеты могут быть созданы в других приложениях Oracle, имеющих соответствующие средства (Oracle Developer).
К объектам, объявленным в спецификации пакета Вы можете обращаться из хранимых и прикладных подпрограмм, триггеров приложений и базы данных, и из любых инструментальных средств Oracle.
Для ссылки на общедоступные пакетные конструкции необходимо использовать имя пакета в качестве префикса к имени соответствующего объекта пакета:
имя_пакета.имя_типа
имя_пакета.имя_идентификатора
имя_пакета.имя_процедуры
имя_пакета.имя_функции
Если Вы обращаетесь к общедоступным объектам пакета из тела пакета, в спецификации которого они объявлены, имя пакета можно не упоминать.
К идентификаторам и типам, объявленным в спецификации пакета, можно обращаться даже в том случае, если тело пакета не создано.
SQL> VARIABLE h_comm NUMBER
SQL> EXECUTE :h_comm := comm_package.g_comm
PL/SQL procedure successfully completed.
SQL> PRINT h_comm
H_COMM
---------
10
К общедоступным подпрограммам можно обращаться только после того, как будет создано тело пакета. Для любой подпрограммы, объявленной в спецификации пакета, должна существовать соответствующая реализация в теле пакета.
SQL> EXECUTE comm_package.reset_comm(100)
BEGIN comm_package.reset_comm(100); END;
*
ERROR at line 1:
ORA-04068: existing state of packages has been discarded
ORA-04067: not executed, package body "COMM_PACKAGE" does not exist
ORA-06508: PL/SQL: could not find program unit being called
ORA-06512: at line 1
В теле пакета содержится программный код подпрограмм, объявленных в спецификации пакета (общедоступных подпрограмм), а также подпрограммы, идентификаторы и типы данных, объявленные в теле пакета (закрытые объекты). Для любой подпрограммы, объявленной в спецификации пакета, должна существовать соответствующая реализация в теле пакета.
CREATE [OR REPLACE] PACKAGE BODY имя_пакета
IS
список_идентификаторов;
список_подпрограмм;
END [имя_пакета];
имя_пакета – имя пакета. Имя тела пакета обязательно должно совпадать с именем спецификации пакета
список_идентификаторов – объявление закрытых идентификаторов (типов, переменных, констант, курсоров, исключений)
список_подпрограмм – программные коды общедоступных подпрограмм, объявление закрытых подпрограмм пакета
Внимание! Порядок, в котором закрытые программные конструкции появляются в теле пакета, важен! Объекты должны быть описаны перед тем, как на них ссылаются другие пакетные объекты.
Создадим тело для пакета comm_package, объединяющего общедоступную переменную для хранения значения комиссионных и процедуру, которая предназначена для присвоения нового значения этой переменной. Предположим, что новое значение комиссионных не может превышать наибольшего значения комиссионных, назначенных существующим сотрудникам в таблице emp. Для проверки, не превышает ли новое значение комиссионных допустимого значения, создадим закрытую функцию valid_comm, причем, т.к. общедоступная процедура reset_comm будет обращаться к этой функции для проверки корректности входного параметра, описание функции valid_comm должно предшествовать описанию процедуры reset_comm.
SQL> CREATE OR REPLACE PACKAGE BODY comm_package
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.