в Stored Program Editor редактируется актуальная версия кода, которая находится в словаре-справочнике данных базы данных Oracle;
есть стандартные для современных IDE подсветка синтаксиса и автодополнение кода, что очень удобно;
нажатием клавиш Ctrl+S или соответствующей кнопки интерфейса можно быстро отправить код программы на компиляцию.
Пакеты
Объединенные общим функциональным назначением процедуры и функции принято оформлять в виде пакета PL/SQL. Можно считать, что пакетэто аналог библиотеки программ. Прием оформления родственных программ в библиотеки хорошо известен из практики разработки программного обеспечения. В информационной системе с развитой серверной бизнес-логикой могут быть тысячи процедур и функций на языке PL/SQL. Чтобы они не лежали в базе данных тысячами объектов, правильно объединить их по функциональному признаку в пакеты, дав им названия, соответствующие области применения. Например, в базе данных могут быть такие пакеты:
pk_clients (пакет для работы с клиентскими данными);
pk_stocks (пакет для работы со складами);
pk_orders (пакет для обработки заказов);
Для каждого пакета следует назначить ответственного за него программиста, который будет сопровождать пакет и развивать его функциональность. Часть кода, реализующего общесистемную логику, например, унифицированную обработку ошибок и ведение журналов изменения данных, можно выделить в отдельную группу пакетов ядра прикладной системы (kernel packages), назначив ответственными за них самых опытных программистов.
Спецификация и тело пакета
Пакет PL/SQL состоит из двух объектов базы данных: спецификации пакета (PACKAGE) и тела пакета (PACKAGE BODY). Команда создания спецификации пакета имеет следующий синтаксис:
CREATE [OR REPLACE] PACKAGE [имя_схемы.]имя_пакета {IS | AS}
спецификация пакета
END;
Команда создания тела пакета имеет следующий синтаксис:
CREATE [OR REPLACE] PACKAGE BODY [имя_схемы.]имя_пакета {IS | AS}
[спецификация локальных элементов пакета]
блоки PL/SQL реализации процедур и функций, объявленных в спецификации
блоки PL/SQL локальных процедур и функций
[BEGIN секция инициализации пакета]
END;
В спецификации пакета находится описание следующих программных элементов, доступных из других программ PL/SQL (то есть элементов, видимых извне):
пользовательские типы данных;
пользовательские исключения;
процедуры и функции;
переменные;
константы;
курсоры.
Эти программные элементы называются глобальными пакетными переменными, глобальными пакетными курсорами и т. п.
Для процедур и функций в спецификации пакета присутствуют только заголовкиназвания процедур и функций и описания их параметров. В спецификации пакета нет блоков PL/SQL, реализующих логику процедур и функций, вся она находится в теле пакета. Можно считать, что спецификация пакета является интерфейсной частьюаналогом заголовочных файлов (header files), имеющихся, например, в языке программирования C++.
В теле пакета могут быть объявлены все те же виды программных элементов, что и в спецификации пакета с той лишь разницей, что они не будут доступны из других программ PL/SQL (не видны извне тела пакета). Эти элементы называются локальными пакетными переменными, локальными пакетными процедурами и т. п.
Локальные программные элементы предназначены исключительно для использования только процедурами и функциями самого пакета. Тем самым в PL/SQL реализовано сокрытие, то есть принцип проектирования программного обеспечения, заключающийся в разграничении доступа различных программ к внутренним компонентам друг друга. Подчеркнем, разграничивается доступ именно к внутренним компонентам.
Покажем области видимости объявленных в пакетах переменных и программ:
CREATE OR REPLACE PACKAGE pkg1 AS
g_var1глобальная пакетная переменная
видна и в теле пакета и снаружи (причем может изменяться снаружи)
g_var1 INTEGER;
глобальная пакетная процедура, видна и в теле пакета и снаружи
PROCEDURE proc1;
END;
CREATE OR REPLACE PACKAGE BODY pkg1 AS
локальная переменная, видна внутри тела пакета, снаружи не видна
l_var2 DATE;
локальная функция, видна внутри тела пакета, снаружи не видна
FUNCTION function1 RETURN VARCHAR2 IS
BEGIN
RETURN TO_CHAR(SYSDATE,'DD.MM.YYYY HH24:MI:SS');
END;
реализация в теле логики процедуры proc1, объявленной в спецификации
PROCEDURE proc1 IS
l_p_var3локальная переменная процедуры proc1
видна только внутри процедуры proc1
l_p_var3 VARCHAR2(2000);
BEGIN
l_p_var3 := function1||' '||to_char(l_var2)||to_char(g_var1);
END;
END;
Достоинства использования пакетов
Сформулируем достоинства использования пакетов PL/SQL при разработке серверной бизнес-логики:
упрощение сопровождения и расширения программ PL/SQL, так как пакеты обеспечивают инкапсуляцию кода и позволяют группировать логически связанные процедуры и функции;
разграничение доступа различных пакетов к внутренним компонентам друг друга;
сохранение данных сессии пользователя в глобальных пакетных переменных, в том числе повышение производительности приложений за счет кэширования постоянно использующихся в программах PL/SQL данных, например, справочников (данные кэшируются в коллекциях-глобальных переменных пакетов);
исключение жестко кодируемых литералов (hard-coded literals).
Хороший стиль программирования на PL/SQL предусматривает даже для небольших проектов наличие спецификаций пакетов, в которых объявлены
все пользовательские типы данных;
все константы и переменные, которые инициализируются жестко кодируемыми литералами, в том числе магическими числами;
все SQL-запросы в виде объявлений явных курсоров;
все пользовательские исключения.
Настоятельно рекомендуется все объявления программных элементов такого рода всех программ PL/SQL, реализующих серверную бизнес-логику системы, собрать в одной или нескольких спецификациях пакетов, а не «размазывать» объявления типов, исключений, констант и т. п. по всему коду или переписывать одну и ту же команду SELECT INTO в нескольких местах. Иногда даже создают отдельные спецификации пакетов только для объявлений типов, переменных, исключений и курсоров без объявлений процедур и функций. Для таких спецификаций изначально не планируется создавать тела пакетов.
Ни в коем случае не следует расставлять по всему исходному коду PL/SQL жестко кодируемые литералы. Например, если в коде в сорока местах для вычисления сумм «чистыми» использовать выражения вида ()*0.87, то когда ставка подоходного налога перестанет быть равной 13%, надо будет найти все сорок мест и заменить 0.87 на новое значение. А самое интересное начнется, если почти везде по коду поменять значение литерала на новое, а где-то забыть и оставить старое. Чтобы не заниматься всем этим, правильно один раз объявить в спецификации пакета константу
g_c_tax_percent INTEGER := 13;
и во всем коде в дальнейшем использовать только ее. Если потребуется внести изменения, то новое число нужно будет указать только в одном местев значении константы.
Отношения между спецификацией и телом пакета
Отношения между спецификацией и телом пакета описываются следующим образом:
сначала создается спецификация пакета, затем его тело;
тело пакета не может существовать без спецификации и даже не создастся DDL-командой CREATE PACKAGE BODY с выдачей сообщения об ошибке;
спецификация пакета без тела существовать может, на объявленные в ней глобальные пакетные процедуры и функции можно ссылаться из других программ PL/SQL (ошибка обращения к такому бестелесному пакету возникнет только на этапе выполнения);
при перекомпиляции спецификации пакета автоматически перекомпилируется его тело, при перекомпиляции тела пакета его спецификация не перекомпилируется;
при удалении спецификации пакета автоматически удаляется его тело, при удалении тела пакета с его спецификацией ничего не происходит.
Эти отношения между спецификацией и телом пакета имеют следующие положительные аспекты, которые особенно полезны при большом объеме кода на PL/SQL в крупных проектах:
возможность создания на этапе прототипирования «заглушек» пакетов без тел, реализация объявленных в их спецификациях процедур и функций будет осуществлена позже;