PL/SQL позволяет в этих случаях объявлять ссылаемые подпрограммы перед их описанием. Т.е. Вы объявляете программную единицу перед подпрограммой, которая на нее ссылается, но описываете там, где Вам удобнее. Список формальных параметров должен присутствовать в обоих описаниях.
Например, попытка откомпилировать тела пакета, в котором процедура reset_comm описана перед функцией valid_comm, завершится ошибкой, т.к. процедура reset_comm ссылается на функцию valid_comm.
SQL> CREATE OR REPLACE PACKAGE BODY comm_package
2 IS
3 PROCEDURE reset_comm (v_comm IN NUMBER)
4 IS
5 v_valid BOOLEAN;
6 BEGIN
7 v_valid := valid_comm(v_comm);
8 IF v_valid = TRUE THEN g_comm := v_comm;
9 ELSE DBMS_OUTPUT.put_line('Invalid Commission');
10 END IF;
11 END reset_comm;
12
13 FUNCTION valid_comm (v_comm IN NUMBER)
14 RETURN BOOLEAN
15 IS
16 v_max_comm NUMBER;
17 BEGIN
18 SELECT MAX(comm) INTO v_max_comm FROM emp;
19 IF v_comm>v_max_comm THEN RETURN(FALSE);
20 ELSE RETURN(TRUE);
21 END IF;
22 END valid_comm;
23 END comm_package;
24 /
Warning: Package Body created with compilation errors.
Но если функцию valid_comm объявить перед описанием процедуры reset_comm, компиляция завершится без ошибок, несмотря на то, что описана функция после процедуры.
SQL> CREATE OR REPLACE PACKAGE BODY comm_package
2 IS
3 FUNCTION valid_comm (v_comm IN NUMBER) RETURN BOOLEAN;
4
5 PROCEDURE reset_comm (v_comm IN NUMBER)
6 IS
7 v_valid BOOLEAN;
8 BEGIN
9 v_valid := valid_comm(v_comm);
10 IF v_valid = TRUE THEN g_comm := v_comm;
11 ELSE DBMS_OUTPUT.put_line('Invalid Commission');
12 END IF;
13 END reset_comm;
14
15 FUNCTION valid_comm (v_comm IN NUMBER)
16 RETURN BOOLEAN
17 IS
18 v_max_comm NUMBER;
19 BEGIN
20 SELECT MAX(comm) INTO v_max_comm FROM emp;
21 IF v_comm>v_max_comm THEN RETURN(FALSE);
22 ELSE RETURN(TRUE);
23 END IF;
24 END valid_comm;
25 END comm_package;
26 /
Package body created.
В теле пакета может содержаться программа инициализации, выполняемая один раз при загрузке пакета в память. Программа инициализации используется для инициализации общедоступных или закрытых переменных, если для этого необходимы сложные вычисления, которые не могут быть выполнены при инициализации переменной по умолчанию, или требуется извлечь данные из базы данных. Программа инициализации представляет собой блок PL/SQL, начинающийся ключевым словом BEGIN и располагающийся в конце тела пакета после всех описаний.
CREATE [OR REPLACE] PACKAGE BODY имя_пакета
IS
список_идентификаторов_и_подпрограмм;
[BEGIN
программа_инициализации;]
END [имя_пакета];
Например, программу инициализации можно использовать, чтобы установить начальное значение общедоступной пакетной переменной, равное среднему значению комиссионных сотрудников из таблицы emp.
SQL> CREATE OR REPLACE PACKAGE BODY comm_package
2 IS
3 FUNCTION valid_comm (v_comm IN NUMBER)
4 RETURN BOOLEAN
5 IS
...
12 END valid_comm;
13
14 PROCEDURE reset_comm (v_comm IN NUMBER)
15 IS
16 v_valid BOOLEAN;
17 BEGIN
...
22 END reset_comm;
23
24 BEGIN
25 SELECT AVG(comm) INTO g_comm FROM emp;
26 END comm_package;
27 /
Package body created.
SQL> VARIABLE v_comm NUMBER
SQL> EXECUTE :v_comm := comm_package.g_comm
PL/SQL procedure successfully completed.
SQL> PRINT v_comm
V_COMM
---------
550
Для удаления пакетной спецификации и тела пакета используется команда DDL DROP PACKAGE, для удаления только тела пакета – DROP PACKAGE BODY.
DROP PACKAGE имя_пакета;
DROP PACKAGE BODY имя_пакета;
SQL> DROP PACKAGE comm_package;
Package dropped.
Старайтесь создавать наиболее общие пакеты, чтобы их можно было использовать во многих, как уже существующих, так и предполагаемых, приложениях. Не создавайте пакеты, дублирующие функциональность встроенных пакетов Oracle.
Создавайте спецификацию пакета перед его телом, т.к. спецификация предоставляет интерфейс к пакетным объектам для Ваших приложений. К тому же, тело пакета не может быть откомпилировано, если не откомпилирована соответствующая спецификация пакета.
Описывайте в спецификации пакета только те объекты, которые действительно должны быть доступны всем пользователям.
Описывайте в спецификации пакета как можно меньше объектов. Это уменьшит необходимость перекомпиляции пакета, т.к. внесение изменений в тело пакета не требует перекомпиляции зависимых объектов, в то время как изменение спецификации пакета требует перекомпиляции каждой хранимой программной единицы, которая ссылается на общедоступные объекты этого пакета.
Вы можете использовать хранимые и пакетные функции в SQL утверждениях, но они должны быть свободны от «побочных эффектов», которые могут препятствовать выполнению запроса или привести к неопределенному результату.
Если команда SQL выполняется из функции, которая была вызвана из предложения SQL, или из триггера базы данных, она может нарушить логическую целостность уже выполняемого утверждения SQL. Чтобы этого не произошло, сервер базы данных выполняет определенные проверки функции, вызванной из предложения SQL, и выдает ошибку в том случае, если функция не отвечает следующим ограничениям:
· Функция, вызываемая из запроса SQL или команды DML, не может выполнять команды управления транзакциями (COMMIT, ROLLBACK, SAVEPOINT) или SQL утверждения, управляющие сеансом (SET ROLE, ALTER SESSION) или системой (ALTER SYSTEM). Нельзя, также, выполнять утверждения DDL, т.к. они выполняют неявный COMMIT.
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.