- •Создание пакетов
- •3 Procedure reset_comm
- •4 (V_comm in number);
- •5 End comm_package;
- •2 Function validate_comm
- •V_mgr in emp.Mgr%type,
- •V_empno number;
- •Index by binary integer;
- •2 Emp_table emp_package.Emp_table type;
- •Index by binary_integer;
- •Into g_comm
- •Interest real; -- общая переменная
- •Interest number
- •Into interest --процедуры
- •V_message varchar2(50);
- •V_proc_name || ‘ end;’;
- •V_cursor integer;
- •V_return integer;
- •V_ename emp.Ename%type;
- •V_sal emp.Sal%type;
- •V_column_value varchar(30) ;
- •Var v_out1 varchar2(10);
- •Var v_out2 number;
- •Контрольные вопросы.
V_mgr in emp.Mgr%type,
v_job IN emp.job%TYPE,
v_sal IN emp.sal%TYPE)
IS
v_comm emp.comm%TYPE ;
. . .
BEGIN
. . .
v_comm:=comm_package.g_соmm; -- обращение к
-- глобальной переменной
. . .
END hire_emp;
Пример пакетного курсора.
Спецификация пакета:
SQL> CREATE OR REPLACE PACKAGE pack_cur
2 IS
3 CURSOR c1 IS SELECT empno FROM emp
4 ORDER BY empno desc;
5 PROCEDURE proc1_3rows;
6 PROCEDURE proc4_6rows;
7 END pack_cur;
8 /
Тело пакета:
SQL> CREATE OR REPLACE PACKAGE BODY pack_cur
2 IS
3 v_empno NUMBER;
4 PROCEDURE proc1_3rows IS
5 BEGIN OPEN c1;
6 LOOP FETCH c1 INTO v_empno;
7 DBMS_OUTPUT.PUT_LINE('Id :'||(v_empno));
8 EXIT WHEN c1%ROWCOUNT >= 3;
9 END LOOP;
10 END proc1_3rows;
11 PROCEDURE proc4_6rows IS
12 BEGIN
13 LOOP FETCH c1 INTO v_empno;
14 DBMS_OUTPUT.PUT_LINE('Id :'||(v_empno));
15 EXIT WHEN c1%ROWCOUNT >= 6;
16 END LOOP;
17 CLOSE c1;
18 END proc4_6rows;
19 END pack_cur;
20 /
Пример вызовов пакетных курсоров
SQL> SET SERVEROUTPUT ON
SQL> EXECUTE pack1.proc1_3rows;
Id : 7934
Id : 7902
Id : 7900
SQL> EXECUTE pack1.proc4_6rows;
Id : 7876
Id : 7844
Id : 7839
Отметим, что в PL/SQLесть средство, приводящее к автоматическому закрытию пакетного курсора после выполнения каждой процедуры. Это средство – директиваPRAGMASERIALLY_REUSABLE.
Главное назначение этой директивы – экономия памяти на сервере базы данных при большом числе пользователей. Присутствие директивы в пакете приводит к тому, что данные пакета существуют только на время выполнения процедуры пакета, а затем память выделенная под них освобождается.
При использовании этой директивы спецификация и тело пакета начинались бы так:
CREATE OR REPLACE PACKAGE pack_cur IS -- спецификация
PRAGMA SERIALLY_REUSABLE;
CURSOR c1 IS SELECT empno FROM emp
. . .
-- тело пакета
CREATE OR REPLACE PACKAGE BODY pack_cur IS
PRAGMA SERIALLY_REUSABLE;
V_empno number;
. . .
Использование переменных типа Table и Record в пакете.
Создаём пакет:
CREATE OR REPLACE PACKAGE emp_package IS
TYPE emp_table_type IS TABLE OF emp%ROWTYPE
Index by binary integer;
PROCEDURE read_emp_table(emp_table OUT
emp_table_type);
END emp_package;
CREATE OR REPLACE PACKAGE BODY emp_package IS
PROCEDURE read_emp_table(emp_table OUT
emp_table_type)
IS
i BINARY INTEGER:=0;
BEGIN
FOR emp_record IN (SELECT * FROM emp) LOOP
emp_table(i):=emp_record;
i:=i+1;
END LOOP;
END;
END emp_package;
Вызов процедуры READ_EMP_TABLE из анонимного PL/SQL-блока с помощью SQL*Plus.
SQL> DECLARE
2 Emp_table emp_package.Emp_table type;
3 BEGIN
4 emp_package.read_emp_table(emp_table);
5 dbms_output.put_line('An example:'||
emp_table(4).ename);
6 END;
Удаление пакетов.
Полное удаление пакета (и спецификации и тела):
DROP PACKAGE имя_пакета;
Удаление только тела пакета:
DROP PACKAGE BODY имя_пакета;
Перегрузка пакетов
Позволяет использовать одно и то же имя для разных подпрограмм в пакете
Формальные параметры подпрограмм должны отличаться по количеству, порядку и семейству типов данных.
Перегружаемые подпрограммы могут помещаться в локальные подпрограммы и подпрограммы, входящие в пакеты.
Ограничения на перегрузку программ и функций:
Перегружать можно только локальные или пакетные программы.
Перегрузка двух программ невозможна, если их формальные параметры отличаются только именами или режимом параметров.
Перегрузка двух программ невозможна, если их формальные параметры отличаются только типами данных и эти различные типы принадлежат одному и тому же семейству типов данных.
Перегрузка двух программ невозможна, если их формальные параметры отличаются только подтипом данных и эти разные подтипы основаны на типах данных одного и того же семейства.
Перегрузка двух функций невозможна, если они отличаются только типом возвращаемых данных, даже если эти типы относятся к разным семействам.
Порядок разрешения вызова. Компилятор, прежде всего, пытается найти декларативную информацию, соответствующую данному вызову (т.е. объявление соответствующей программы). Сначала компилятор ищет эту информацию в локальной области видимости, а затем, если требуется, во внешних областях видимости. Поиск прекращается, когда компилятор находит одно или несколько объявлений программ, имя в которых совпадает с именем вызываемой программы. Если программы на одном и том же уровне видимости имеют одинаковые имена, компилятору требуется точное совпадение по количеству, порядку и типам данных между фактическими и формальными параметрами.
Пример перегружаемой программы.
Описание перегружаемой программы:
PROCEDURE initialize(tab OUT datetabtyp, n INTEGER) IS
BEGIN
FOR i in 1..n LOOP
tab(i) := SYSDATE;
END LOOP;
END initialize;
-- -- -- -- -- --
PROCEDURE initialize(tab OUT realtabtyp, n INTEGER) IS
BEGIN
FOR i in 1..n LOOP
tab(i) := 1000;
END LOOP;
END initialize;
Вызов перегружаемых вариантов программы
DECLARE
TYPE datetabtyp IS TABLE OF DATE