Шаг 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-код. В этот момент для всех переменных, описанных в модуле, выделяется память. Таким образом два сеанса выполняющие подпрограммы одного и того же модуля будут использовать различные области памяти. Вот кратко, что касается создания пакетов. Но это еще не все. :)


Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Летучий Сергей - 17.02.2004