Пакеты в PL/SQL: предназначение и применение на практике

ПАКЕТЫ PL/SQL - ПРИМЕНЕНИЕПакет PL/SQL представляет собой сгруппированный по определенным правилам именованный набор элементов кода PL/SQL. Он обеспечивает логическую структуру для организации программ и других элементов PL/SQL: курсоров, типов данных и переменных. Пакеты обладают очень важными функциональными возможностями, включая возможность сокрытия логики и данных, а также определения глобальных данных, существующих в течение сеанса.


Оглавление статьи[Показать]


 

Для чего нужны пакеты в PL/SQL?

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

Прежде чем приступать к рассмотрению преимуществ пакетов и описанию синтак­сиса их определения, необходимо сделать одно важное замечание. Всегда стройте приложение на основе пакетов; избегайте отдельных процедур и функций. Даже если вам сейчас кажется, что для реализации определенной возможности доста­точно одной процедуры или функции, в будущем к ней почти наверняка добавятся еще несколько. Когда вы поймете, что их лучше объединить в пакет, придется ис­кать все вызовы процедур и функций и добавлять к ним префикс с именем пакета. Используйте пакеты с самого начала, избавьте себя от будущих проблем!

 

Демонстрация возможностей пакетов PL/SQL

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

PROCEDURE process_employee (
   employee_id_in IN employees.employee_id%TYPE)
IS
   l_fullname VARCHAR2(100);
BEGIN
   SELECT last_name || ',' || first_name 
   INTO l_fullname 
   FROM employees
   WHERE employee_id = employee_id_in;
END;

Однако этот вроде бы тривиальный код обладает рядом скрытых недостатков:

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

PACKAGE employee_pkg
AS
   SUBTYPE fullname_t IS	VARCHAR2 (200);

   FUNCTION fullname (
      last_in employees.last_name%TYPE,
      first_in employees.first_name%TYPE)
      RETURN fullname_t;

   FUNCTION fullname (
      employee_id_in IN employees.employee_id%TYPE)
      RETURN fullname_t;
END employee_pkg;

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

Строки Описание
3 Объявление нового типа данных fullname_t. В этой версии его максимальная длина составляет 200 символов, но впоследствии ее будет легко изменить
5-8 Объявление функции fullname, которая строит полное имя по фамилии и имени. Обратите
внимание: способ построения полного имени в спецификации пакета не указан
10-13 Объявление второй функции с тем же именем fullname; новая версия получает первичный
ключ таблицы и возвращает соответствующее ему полное имя. Это типичный пример перегрузки, о которой говорилось в этой статье


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

DECLARE
   l_name employee_pkg.fullname_t; 
   employee_id_in employees.employee_id%TYPE := 1;
BEGIN
   l_name := employee_pkg.fullname (employee_id_in);
END;

Переменная l_name объявляется с новым типом данных, а для присваивания ей нужного значения вызывается соответствующая функция этого же пакета. Таким образом, формула построения полного имени и SQL-запрос вынесены из кода приложения в специальный «контейнер» для всей функциональности, относящейся к обработке данных о сотруд­никах. Код стал проще и лаконичнее. Если потребуется изменить формулу построения полного имени или увеличить размер его типа данных, достаточно внести соответству­ющие изменения в спецификацию или тело пакета и перекомпилировать его код.

Реализация employee_pkg выглядит так:

PACKAGE BODY employee_pkg
AS
   FUNCTION fullname (
      last_in employee.last_name%TYPE,
      first_in employee.first_name%TYPE
   )
      RETURN fullname_t
   IS
   BEGIN
      RETURN last_in || ', ' || first_in;
   END;

   FUNCTION fullname (employee_id_in IN employee.employee_id%TYPE)
      RETURN fullname_t
   IS
      retval fullname_t;
   BEGIN
      SELECT fullname (last_name, first_name) INTO retval
      FROM employee
      WHERE employee_id = employee_id_in;

      RETURN retval;
   EXCEPTION
      WHEN NO_DATA_FOUND THEN RETURN NULL;

      WHEN TOO_MANY_ROWS THEN errpkg.record_and_stop;
   END;
END employee_pkg;

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

 

Строки Описание
3-11 Функция-«обертка» для определения формата полного имени «ФАМИЛИЯ, ИМЯ»
13-27 Типичный запрос на выборку одной строки, выполняемый с помощью неявного курсора
18 Вызов функции fullname, возвращающей комбинацию двух компонентов имени

 

Если теперь пользователь потребует изменить формат представления полного имени, нам не придется искать по всему приложению все вхождения || ', ' || — для установки нового формата достаточно модифицировать в пакете employee_pkg функцию fullname.

 

Основные концепции пакетов

Прежде чем переходить к подробному изучению синтаксиса и структуры пакетов, сле­дует изучить некоторые концепции пакетов:

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

На ранних стадиях развития программы в теле пакета также могут реализоваться в виде «заглушек» с минимальным объемом кода, необходимым для компиляции пакета. Этот прием позволяет сосредоточиться на интерфейсах программы и их взаимных связях.

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

Именно пакеты обеспечивают поддержку структур данных с сеансовым постоянством в языке PL/SQL.

 

Графическое представление приватности

Различия между общедоступными и приватными элементами пакета дают разработчикам PL/SQL беспрецедентные средства управления структурами данных и программами. Грэди Буч предложил визуальное средство описания этих аспектов пакета (которое было вполне естественно названо диаграммой Буча).

Взгляните на рис. 1. Обратите внимание на надписи «Внутренняя часть» и «Внешняя часть». Первая часть содержит тело пакета (внутренняя реализация пакета), а вторая — все программы, написанные вами и не являющиеся частью пакета (внешние программы).

 

Диаграмма Буча с общедоступными и приватными элементами пакета

Рис. 1. Диаграмма Буча с общедоступными и приватными элементами пакета

 

Несколько выводов, следующих из диаграммы Буча:

 

Вас заинтересует / Intresting for you:

Встроенные методы коллекций PL...
Встроенные методы коллекций PL... 14837 просмотров sepia Tue, 29 Oct 2019, 09:54:01
Управление приложениями PL/SQL...
Управление приложениями PL/SQL... 4651 просмотров Stas Belkov Thu, 16 Jul 2020, 06:20:48
Символьные функции и аргументы...
Символьные функции и аргументы... 18586 просмотров Анатолий Wed, 23 May 2018, 18:54:01
Тип данных RAW в PL/SQL
Тип данных RAW в PL/SQL 12331 просмотров Doctor Thu, 12 Jul 2018, 08:41:33
Печать
Войдите чтобы комментировать

 аватар
ответил в теме #10639 1 год 8 мес. назад
Где применять (везде) ясно.
Как их писать - нет.
Спасибо.
OraCool аватар
OraCool ответил в теме #9509 4 года 6 мес. назад
Myk, да! Спасибо за проделанную работу!)
Кроме своей уникальной возможности сохранения состояния во время сеанса, па­кеты PL/SQL обладают преимуществами из области производительности. Большая часть логики приложения должна размещаться в телах пакетов.
Myk аватар
Myk ответил в теме #9259 5 года 6 мес. назад
Примеры хороши! Даже новичок разберется теперь как писать package и где лучше применять!