Пакет как программная единица, объединяющая логически связанные типы PL/SQL, идентификаторы и подпрограммы

Пакет как программная единица, объединяющая логически связанные типы PL/SQL, идентификаторы и подпрограммы

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

Пакет состоит из двух частей, которые хранятся в базе данных по отдельности:

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

· Тело – содержит программный код подпрограмм, описанных в спецификации, а также идентификаторы и подпрограммы, которые могут использоваться только внутри пакета.

Свойства пакетов

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

· Облегченный дизайн. Вы можете создать и откомпилировать спецификацию пакета отдельно от тела, предоставив тем самым необходимый интерфейс для прикладной программы. Программная логика пакетных объектов (тело пакета) может быть создана и откомпилирована позже.

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

· Общие переменные сессии. Идентификаторы, объявленные в спецификации пакета, действуют в течение всей сессии, в которой они вызывались. Это позволяет сохранять значения, специфичные для сеанса связи с базой данных, и использовать их в различных программных единицах.

· Улучшение производительности. При обращении к любому общедоступному объекту пакета, в память загружается весь пакет. Таким образом, при последующих ссылках на объекты пакета не требуется дисковый ввод/вывод.

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

Программные конструкции, составляющие пакет, могут быть общедоступные (Public) или закрытые (Private):

· К общедоступным объектам пакета можно обращаться из любого прикладного средства СУБД, они объявляются в спецификации пакета и определяются в теле пакета

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

Все объекты, объявленные в спецификации пакета, имеют глобальную область видимости, т.е. во время текущего сеанса все программные конструкции PL/SQL, включая анонимные блоки, могут ссылаться на эти объекты. Объекты, объявленные в теле пакета, скрыты от внешнего окружения пакета, и, следовательно, могут быть вызваны только внутри пакета. Такие объекты имеют локальную область видимости.

Создание спецификации пакета

CREATE [OR REPLACE] PACKAGE имя_пакета

[AUTHID CURRENT_USER]

список_идентификаторов;

список_спецификаций_подпрограмм;

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;

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

2 PACKAGE l_package IS

3 g_comm NUMBER := 10;

4 PROCEDURE reset_comm (v_comm IN NUMBER);

5 END l_package;

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

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

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 имя_пакета

список_идентификаторов;

список_подпрограмм;

END [имя_пакета];

имя_пакета – имя пакета. Имя тела пакета обязательно должно совпадать с именем спецификации пакета

список_идентификаторов – объявление закрытых идентификаторов (типов, переменных, констант, курсоров, исключений)

список_подпрограмм – программные коды общедоступных подпрограмм, объявление закрытых подпрограмм пакета

Внимание! Порядок, в котором закрытые программные конструкции появляются в теле пакета, важен! Объекты должны быть описаны перед тем, как на них ссылаются другие пакетные объекты.

Создадим тело для пакета comm_package, объединяющего общедоступную переменную для хранения значения комиссионных и процедуру, которая предназначена для присвоения нового значения этой переменной. Предположим, что новое значение комиссионных не может превышать наибольшего значения комиссионных, назначенных существующим сотрудникам в таблице emp. Для проверки, не превышает ли новое значение комиссионных допустимого значения, создадим закрытую функцию valid_comm, причем, т.к. общедоступная процедура reset_comm будет обращаться к этой функции для проверки корректности входного параметра, описание функции valid_comm должно предшествовать описанию процедуры reset_comm.

📎📎📎📎📎📎📎📎📎📎