· процедуры
· функции
· типы
· курсоры
После их размещения, на них можно ссылаться из других блоков PL/SQL. По этому в них можно описывать глобальные переменные для PL/SQL. Давайте рассмотрим как описывается модуль. Каждый модуль состоит из двух частей описания (заголовка) и тела. Заголовок модуля определяется так:
CREATE OR REPLACE PACKAGE имя_модуля {IS AS}
описание_процедуры |
описание_функции |
объявление_переменной |
определение_типа |
объявление_исключительной_ситуации |
объявление_курсора |
END [имя_модуля];
Тело модуля определяется так:
CREATE OR REPLACE PACKAGE BODY имя_модуля {IS AS}
код_инициализации_процедуры |
код_инициализации_функции |
END [имя_модуля];
По большому счету тело модуля не является обязательной частью. Если заголовок модуля содержит описание, скажем нескольких переменных, типов и курсоров, то создавать тело модуля нет необходимости. Такой способ целесообразен при объявлении глобальных переменных, поскольку все объекты модуля видимы вне его пределов.
Возьмем на заметку следующее:
· Элементы модуля могут указываться в любом порядке. Однако, как и в разделе объявлений, объект должен быть объявлен до того как на него будут произведены ссылки. Например, если частью условия WHERE курсора является некоторая переменная, то она должна быть объявлена до объявления курсора.
· Присутствие элементов всех видов совсем не обязательно! Например, модуль может состоять только из объявлений процедур и функций, без объявления курсоров или типов.
· Объявление процедур и функций должны быть предварительными. В этом отличие модуля от раздела объявлений блока, где могут находиться как предварительные объявления, так и реальный код процедур и функций. Программный код процедур и функций модуля содержится в тексте этого модуля.
В следующий раз поучимся создавать то, что мы с вами рассмотрели.
Шаг 97 - PL/SQL - Учимся создавать пакеты и работать с ними
Теоретически, наверное, почти понятно, что такое пакет (модуль) слово за практическим исполнением. Давайте создадим простой пакет, в котором содержится три функции и одна процедура, так для полноты картины. :) А, затем немного поработает со всем этим. Я создам простые ничего особо не значащие функции. Если у вас возникнет желание усложнить это дело и написать какой-нибудь полезный пакет, я только приветствую! Но, когда вы будете набирать телефон компании Oracle в честолюбивой попытке продать написанное вами, не забудьте меня при получении гонорара! :) Вот наши функции в чистом виде:
-- PROCEDURE Out_Screen -- ****************************************
CREATE OR REPLACE PROCEDURE Out_Screen(TOSC IN VARCHAR2)
IS
BEGIN
DBMS_OUTPUT. enable;
DBMS_OUTPUT. put_line(TOSC);
END Out_Screen;
/
-- FUNCTION Min_Two_Num -- ****************************************
CREATE OR REPLACE FUNCTION Min_Two_Num(A IN NUMBER, B IN NUMBER) RETURN NUMBER
IS
BEGIN
RETURN (A - B);
END Min_Two_Num;
/
-- FUNCTION Add_Two_Num -- ****************************************
CREATE OR REPLACE FUNCTION Add_Two_Num(A IN NUMBER, B IN NUMBER) RETURN NUMBER
IS
BEGIN
RETURN (A + B);
END Add_Two_Num;
/
-- FUNCTION FACTORIAL -- ****************************************
CREATE OR REPLACE FUNCTION FACTORIAL(NUM IN NUMBER) RETURN NUMBER
IS
BEGIN
IF (NUM <=1) THEN
RETURN (NUM);
ELSE
RETURN (NUM * FACTORIAL(NUM-1));
END IF;
END FACTORIAL;
/
Первая изображает что-то вроде print, вторая складывает два числа. Третья отнимает два числа. А четвертая вам уже знакома, та самая рекурсия для расчета факториала числа. Давайте, поместим это все в "пакет" и заставим работать. Создаем описание заголовка пакета test_pkg:
-- НАШ ПЕРВЫЙ ПАКЕТ ---------------------------------------------
CREATE OR REPLACE PACKAGE test_pkg IS
PROCEDURE Out_Screen(TOSC IN VARCHAR2);
FUNCTION Add_Two_Num(A IN NUMBER, B IN NUMBER) RETURN NUMBER;
FUNCTION Min_Two_Num(A IN NUMBER, B IN NUMBER) RETURN NUMBER;
FUNCTION FACTORIAL(NUM IN NUMBER) RETURN NUMBER;
END test_pkg;
/
Компилируем и ждем результат:
SQL> -- НАШ ПЕРВЫЙ ПАКЕТ ---------------------------------------------
SQL> CREATE OR REPLACE PACKAGE test_pkg IS
2
3 PROCEDURE Out_Screen(TOSC IN VARCHAR2);
4
5 FUNCTION Add_Two_Num(A IN NUMBER, B IN NUMBER) RETURN NUMBER;
6
7 FUNCTION Min_Two_Num(A IN NUMBER, B IN NUMBER) RETURN NUMBER;
8
9 FUNCTION FACTORIAL(NUM IN NUMBER) RETURN NUMBER;
10
11 END test_pkg;
12 /
Пакет создан.
Результат положительный, идем дальше. Создадим само тело нашего пакета:
-- PACKAGE BODY test_pkg -- **************
CREATE OR REPLACE PACKAGE BODY test_pkg IS
-- PROCEDURE Out_Screen -- ***************
PROCEDURE Out_Screen(TOSC IN VARCHAR2)
IS
BEGIN
DBMS_OUTPUT. enable;
DBMS_OUTPUT. put_line(TOSC);
END Out_Screen;
-- FUNCTION Min_Two_Num -- ***************
FUNCTION Min_Two_Num(A IN NUMBER, B IN NUMBER) RETURN NUMBER
IS
BEGIN
RETURN (A - B);
END Min_Two_Num;
-- FUNCTION Add_Two_Num -- ***************
FUNCTION Add_Two_Num(A IN NUMBER, B IN NUMBER) RETURN NUMBER
IS
BEGIN
RETURN (A + B);
END Add_Two_Num;
-- FUNCTION FACTORIAL -- *****************
FUNCTION FACTORIAL(NUM IN NUMBER) RETURN NUMBER
IS
BEGIN
IF (NUM <=1) THEN
RETURN (NUM);
ELSE
RETURN (NUM * FACTORIAL(NUM-1));
END IF;
END FACTORIAL;
END test_pkg;
/
Ждем результата компиляции:
SQL> -- PACKAGE BODY test_pkg -- **************
SQL> CREATE OR REPLACE PACKAGE BODY test_pkg IS
2
3 -- PROCEDURE Out_Screen -- ****************************************
4 PROCEDURE Out_Screen(TOSC IN VARCHAR2)
5 IS
6
7 BEGIN
8
9 DBMS_OUTPUT. enable;
10 DBMS_OUTPUT. put_line(TOSC);
11
12 END Out_Screen;
13
14 -- FUNCTION Min_Two_Num -- ****************************************
15 FUNCTION Min_Two_Num(A IN NUMBER, B IN NUMBER) RETURN NUMBER
16 IS
17
18 BEGIN
19
20 RETURN (A - B);
21
22 END Min_Two_Num;
23
24 -- FUNCTION Add_Two_Num -- ****************************************
25 FUNCTION Add_Two_Num(A IN NUMBER, B IN NUMBER) RETURN NUMBER
26 IS
27
28 BEGIN
29
30 RETURN (A + B);
31
32 END Add_Two_Num;
33
34 -- FUNCTION FACTORIAL -- ****************************************
35 FUNCTION FACTORIAL(NUM IN NUMBER) RETURN NUMBER
36 IS
37
38 BEGIN
39
40 IF (NUM <=1) THEN
41 RETURN (NUM);
42 ELSE
43 RETURN (NUM * FACTORIAL(NUM-1));
44
45 END IF;
46
47 END FACTORIAL;
48
49 END test_pkg;
50 /
Тело пакета создано.
SQL>
Ух ты и снова успешно! Итак, наш с вами пакет создан, он имеет тело и готов к работе. Как уже надеюсь, ясно обратится к обьекту в пакете возможно применив точечную нотацию. Вот так:
BEGIN
test_pkg. Out_Screen('HELLO!!!');
END;
Здесь test_pkg - имя нашего пакета, Out_Screen имя объекта в пакете и его параметры если таковые есть. Осталось попробовать работу нашего пакета на деле. Запишем такой анонимный блок:
SET SERVEROUTPUT ON
DECLARE
BEGIN
test_pkg. Out_Screen(TO_CHAR(test_pkg. Min_Two_Num(10,4)));
test_pkg. Out_Screen(TO_CHAR(test_pkg. Add_Two_Num(5,2)));
test_pkg. Out_Screen(TO_CHAR(test_pkg. Add_Two_Num(test_pkg. FACTORIAL(5),4)));
END;
/
После компиляции:
SQL> SET SERVEROUTPUT ON
SQL>
SQL> DECLARE
2
3 BEGIN
4
5 test_pkg. Out_Screen(TO_CHAR(test_pkg. Min_Two_Num(10,4)));
6 test_pkg. Out_Screen(TO_CHAR(test_pkg. Add_Two_Num(5,2)));
7 test_pkg. Out_Screen(TO_CHAR(test_pkg. Add_Two_Num(test_pkg. FACTORIAL(5),4)));
8
9 END;
10 /
6
7
124
Процедура PL/SQL успешно завершена.
Пакет работает и весьма успешно. Кстати заметили, что код стал более читаемый хотя на первый взгляд не совсем понятно, что как работает. Так, вот пакет это еще одно средство для скрытия кода реализации. То есть функции есть, их параметры есть, а как это работает не видно! Хотя содержимое тела пакета, при необходимости можно увидеть. Вызов процедур и функций может так же иметь именное или позиционное представление параметров. Внутри тела модуля можно ссылаться на объекты указанные в заголовке без указания имени модуля. При первом вызове модуль конкретизируется (instantiated) - он считывается с диска в память, а затем запускается его p-код. В этот момент для всех переменных, описанных в модуле, выделяется память. Таким образом два сеанса выполняющие подпрограммы одного и того же модуля будут использовать различные области памяти. Вот кратко, что касается создания пакетов. Но это еще не все. :)
Шаг 98 - PL/SQL - Пакеты - Изменение, удаление
Теперь возьмем ситуацию, когда нам нужно добавить в пакет функцию умножающую два числа. Определенную вот так:
-- FUNCTION Mul_Two_Num --
CREATE OR REPLACE FUNCTION Mul_Two_Num(A IN NUMBER, B IN NUMBER) RETURN NUMBER
IS
BEGIN
RETURN (A * B);
END Mul_Two_Num;
Как это сделать? Достаточно просто сначала добавить ее описание в заголовке модуля:
-- НАШ ПЕРВЫЙ ПАКЕТ --
CREATE OR REPLACE PACKAGE test_pkg IS
PROCEDURE Out_Screen(TOSC IN VARCHAR2);
FUNCTION Add_Two_Num(A IN NUMBER, B IN NUMBER) RETURN NUMBER;
FUNCTION Min_Two_Num(A IN NUMBER, B IN NUMBER) RETURN NUMBER;
FUNCTION Mul_Two_Num(A IN NUMBER, B IN NUMBER) RETURN NUMBER;
FUNCTION FACTORIAL(NUM IN NUMBER) RETURN NUMBER;
END test_pkg;
/
Компилируем и ждем результат:
SQL> CREATE OR REPLACE PACKAGE test_pkg IS
2
3 PROCEDURE Out_Screen(TOSC IN VARCHAR2);
4
5 FUNCTION Add_Two_Num(A IN NUMBER, B IN NUMBER) RETURN NUMBER;
6
7 FUNCTION Min_Two_Num(A IN NUMBER, B IN NUMBER) RETURN NUMBER;
8
9 FUNCTION Mul_Two_Num(A IN NUMBER, B IN NUMBER) RETURN NUMBER;
10
11 FUNCTION FACTORIAL(NUM IN NUMBER) RETURN NUMBER;
12
13 END test_pkg;
14 /
Пакет создан.
Теперь давайте посмотрим, что же происходит с телом пакета. Дадим вот такой запрос к представлению USER_OBJECTS:
SELECT OBJECT_NAME, OBJECT_TYPE, STATUS
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 |


