Pakiety Pakiety są logicznymi zbiorami obiektów takich jak podprogramy, typy, zmienne, kursory, wyjątki. Pakiet składa się ze: specyfikacji (interfejsu) i ciała (implementacji). W specyfikacji mieszczą się deklaracje typów, zmiennych, stałych, kursorów, wyjątków i podprogramów. W ciele mieści się implementacja specyfikacji. Specyfikacja i ciało pakietu są oddzielnie przechowywane w słowniku danych.
Pakiety umożliwiają: 1. przechowywanie powiązanych ze sobą obiektów w jednym miejscu, 2. grupowanie logicznej funkcjonalności, 3. łatwe projektowanie aplikacji: kodowanie i kompilacja oddzielnie specyfikacji i ciała, 4. ukrywanie informacji: tylko deklaracje w specyfikacji są jawne i dostępne dla aplikacji, prywatne deklaracje w ciele pakietu są ukryte, kod jest ukryty w ciele pakietu.
Zalety pakietów: zwiększenie wydajności (przy pierwszym odwołaniu do pakietu cała jego zawartość jest ładowana do pamięci), dodatkowa funkcjonalność udostępniają zmienne globalne, umożliwiają przeciążanie procedur i funkcji, ukrycie informacji użytkownikowi jest udostępniana tylko specyfikacja pakietu (interfejs), natomiast implementacja procedur i funkcji jest niewidoczna,
Pakiety Specyfikacja pakietu Ciało pakietu Deklaracja zmiennych Deklaracja procedury lub funkcji itd. Deklaracja zmiennych Definicja procedury lub funkcji itd. publiczne prywatne
Specyfikacja pakietu Specyfikacja pakietu - cechy Inaczej nagłówek pakietu. Jest to interfejs do aplikacji. Zawiera informacje o zawartości pakietu, ale bez kodu podprogramów. Może zawierać deklarację publicznych typów, zmiennych, stałych, wyjątków, kursorów. W specyfikacji pakietu obowiązują te same zasady, co w sekcji deklaracji bloku anonimowego.
Definiowanie specyfikacji pakietu Specyfikacja: CREATE OR REPLACE PACKAGE nazwa_pakietu IS deklaracje typów, stałych, zmiennych, kursorów i wyjątków dostępnych na zewnątrz pakietu deklaracje funkcji i procedur np. CREATE OR REPLACE PACKAGE kraj IS TYPE KrajTyp IS RECORD ( kraj_id CHAR(2), kraj_nazwa VARCHAR2(40), rejon_id INT); CURSOR kraje(r_id INT) RETURN KrajTyp; ile INT; PROCEDURE dodajkraj(k_id IN CHAR, nazwa VARCHAR2, rejon_id INT DEFAULT 1); PROCEDURE wypiszkraj(r_id INT DEFAULT 1);
Specyfikacja pakietu - uwagi W specyfikacji można inicjalizować zmienne, inaczej dostają one wartość NULL. Wszystkie konstrukcje zadeklarowane w specyfikacji pakietu są publicznie dostępne dla wszystkich użytkowników, którzy mają prawo do pakietu. Kolejność deklaracji w pakiecie jest dowolna, ale elementy, które są używane w kodzie, muszą być zadeklarowane wcześniej. Deklaracja w części specyfikacyjnej to tzw. deklaracja uprzedzająca jest to opis programu, ale bez kodu. Pakiet nie musi zawierać deklaracji wszystkich elementów wszystkich rodzajów, np. może zawierać tylko zmienne i kursory.
Ciało pakietu Ciało pakietu jest zapisywane oddzielnie w słowniku danych. Zawiera kody deklaracji uprzedzających z nagłówka pakietu. Każda deklaracja z nagłówka musi mieć odzwierciedlenie w ciele, specyfikacja procedur i funkcji w obu częściach pakietu musi być dokładnie taka sama jeśli chodzi o nazwę podprogramu, nazwy parametrów i ich typy. W ciele pakietu mogą się znajdować dodatkowe deklaracje (których nie było w specyfikacji), np. typy, zmienne, kursory, wyjątki. Tak zadeklarowane elementy są widoczne tylko w danym ciele pakietu.
Definiowanie pakietu Ciało: CREATE OR REPLACE PACKAGE BODY nazwa_pakietu IS deklaracje lokalnych typów, zmiennych, stałych, wyjatków i kursorów definicje procedur i funkcji BEGIN części inicjalizacyjna pakietu / opcjonalnie np.
CREATE OR REPLACE PACKAGE BODY kraj IS CURSOR kraje(r_id INT) RETURN KrajTyp IS SELECT * FROM countries WHERE region_id=r_id; PROCEDURE dodajkraj(k_id IN CHAR,nazwa VARCHAR2,rejon_id INT DEFAULT 1) IS BEGIN INSERT INTO countries VALUES (k_id,nazwa,rejon_id); PROCEDURE wypiszkraj(r_id INT DEFAULT 1) IS BEGIN FOR kraj IN kraje(r_id) LOOP Dbms_Output.put_line( kraj.kraj_id kraj.kraj_nazwa); END LOOP;
Przykład (z dokumentacji Oracle) Specyfikacja: CREATE OR REPLACE PACKAGE emp_actions IS TYPE EmpRecTyp IS RECORD (emp_id INT, salary REAL); CURSOR desc_salary RETURN EmpRecTyp; PROCEDURE hire_employee ( ename VARCHAR2, job VARCHAR2, mgr NUMBER, sal NUMBER, comm NUMBER, deptno NUMBER); PROCEDURE fire_employee (emp_id NUMBER);
Ciało: CREATE OR REPLACE PACKAGE BODY emp_actions IS CURSOR desc_salary RETURN EmpRecTyp IS SELECT empno, sal FROM emp ORDER BY sal DESC; PROCEDURE hire_employee ( ename VARCHAR2, job VARCHAR2, mgr NUMBER, sal NUMBER, comm NUMBER, deptno NUMBER) IS BEGIN INSERT INTO emp VALUES (empno_seq.nextval, ename, job, mgr, SYSDATE, sal, comm, deptno); PROCEDURE fire_employee (emp_id NUMBER) IS BEGIN DELETE FROM emp WHERE empno = emp_id;
Odwołanie do funkcji/procedury zawartej w pakiecie należy poprzedzić nazwą pakietu, o ile odwołujemy się do danej funkcji/procedury z zewnątrz pakietu, np. EXECUTE kraj.wypiszkraj(2); Kompilowanie pakietu: ALTER PACKAGE nazwa COMPILE PACKAGE PACKAGE BODY; Usuwanie pakietu: DROP PACKAGE PACKAGE BODY nazwa;
Użycie pakietów do deklarowania zmiennych globalnych Jeżeli specyfikacja pakietu nie zawiera deklaracji kursorów ani podprogramów (procedur, funkcji), a jedynie typy, stałe, zmienne i wyjątki, wówczas nie ma konieczności tworzenia ciała pakietu, np.: CREATE OR REPLACE PACKAGE klientdane IS TYPE DaneKlTyp IS RECORD ( nr customer.cust_no%type, nazwa customer.customer%type, tel customer.phone_no%type, adres VARCHAR2(60), miasto VARCHAR2(35), kraj customer.country%type, kod_pocztowy customer.postal_code%type); min_oplata CONSTANT NUMBER:= 100.00; ile INT; brak_oplaty EXCEPTION; Tego typu pakiet umożliwia zdefiniowanie typów i zmiennych globalnych, do których można się odwoływać z podprogramów oraz wyzwalaczy, w obrębie danej sesji.
Przeciażanie podprogramów z pakietów W pakiecie mogą znajdować się funkcje lub procedury o takiej samej nazwie, ale w wersjach z różnymi parametrami, Pozwala to na stosowanie tych samych operacji do różnych typów obiektów, Parametry muszą się różnić w liczbie, kolejności lub typie, np. CREATE OR REPLACE PACKAGE pracownik IS FUNCTION srednia_zarobkow(id_dzialu NUMBER) RETURN NUMBER; FUNCTION srednia_zarobkow(id_dzialu NUMBER, id_managera NUMBER) RETURN NUMBER;
Ograniczenia przeciażania Nie można utworzyć dwóch podprogramów jeśli parametry różnią się tylko nazwą lub trybem: PROCEDURE A (p_1 IN NUMBER); PROCEDURE A (p_1 OUT NUMBER); Nie można utworzyć dwóch funkcji jeśli różnią się tylko typem zwracanej wartości: FUNCTION B RETURN NUMBER; FUNCTION B RETURN DATE; Parametry podprogramów muszą należeć do różnych rodzin typów, np. takie przeciążanie jest niedozwolone: PROCEDURE C (p_1 IN CHAR); PROCEDURE C (p_1 IN VARCHAR2);