Reprezinta constructii PL/SQL care permit obiectelor inrudite
sa fie stocate impreuna.
Un pachet contine doua parti distincte: specificatia
si corpul pachetului. Fiecare din acestea sunt memorate separat.
Un pachet poate fi doar stocat (NU poate
fi o constructie locala intr-un bloc), si nu se apeleaza niciodata ( procedurile/functiile
definite intr-un pachet sunt apelate).
Un pachet este in esenta o sectiune declarativa denuumita.
Specificatia unui pachet ( package header)
Contine informatii despre continutul pachetului si nu secvente de cod.
CREATE [OR REPLACE] PACKAGE nume_pachet {IS|AS}
-- fara parametri
specificatie
de procedura |specificatie de functie | declaratii_variabile |definitii
de tipuri |
declarare
de exceptii | declaratii de cursoare
END [nume_pachet];
CREATE OR REPLACE PACKAGE sp_timer IS
PROCEDURE capture(context_in
IN VARCHAR2);
-- fara cuvant de inceput
PROCEDURE show_elapsed;
END sp_timer;
Similar unui modul, specificatia pachetului contine toate informatiile necesare pentru ca un dezvoltator sa intelega modul de apelare al unui obiect din pachet. Nu trebuie examinat niciodata codul din spatele specificatiei (corpul pachetului) pentru a intelege cum se utilizeaza si care sunt beneficiile pachetului.
Corpul pachetului (package body) (obiect separat de specificatie
in dictionarul de date )
Contine codul corespunzator declaratiilor din header
-- nu poate fi compilat in absenta specificatiei.
Specificatia pentru proceduri sau functii trebuie sa fie aceeasi
atat in header cat si in body.
CREATE OR REPLACE PACKAGE BODY nume_pachet {IS|AS}
[BEGIN]
-- in cele mai mule cazuri nu este necesar
-- de obicei contine rutine de gestiune
END nume_pachet];
CREATE OR REPLACE PACKAGE BODY sp_timer IS
Last_timing NUMBER := NULL;
-- element privat
PROCEDURE capture (context_in IN VARCHAR2) IS
BEGIN
Last_timing := DBMS_UTILITY.GET_TIME;
END;
PROCEDURE show_elapsed IS
BEGIN
DBMS_OUTPUT_PUT_LINE(DBMS_UTILITY.GET_TIME - last_timing);
END;
-- BEGIN poate fi adaugat aici daca exista declaratii care trebuie executate
END sp_timer;
Corpul pachetului poate contine elemente care nu apar in specificatie. Acestea se numesc elemente private ale pachetului. Un element privat nu poate fi referit in afara pachetului deoarece el nu apare in specificatie.
Pachetele si domeniul lor de vizibilitate
Orice obiect declarat in header-ul pachetului este vizibil
in afara acestuia. Acest lucru poate fi util in declararea variabilelor
globale. Obiectele pot fi adresate prin prefixarea numelui cu numele pachetului.
Exemplu: DBMS_OUTPUT.PUT_LINE('hello');
Apelul procedurii este similar apelului unei proceduri de sine
statatoare.
Suprapunerea subprogramelor
In cadrul unui pachet, procedurile si functiile pot fi suprapuse. Aceasta
inseamna ca pot fi mai multe proceduri sau functii cu acelasi nume,
dar -obligatoriu- cu parametri diferiti.
Initializarea pachetelor
La primul apel al unui pachet acesta este instantiat, adica,
pachetul este citit de pe disc in memorie (in asa numitul format
p-cod) si este rulat.
Pachete si dependente
Corpul unui pachet depinde de header si de tabelele
referite.
Header-ul pachetului nu depinde de nimic (aceasta reprezinta un avantaj).
Ca urmare se poate modifica corpul unui pachet fara a
schimba header-ul acestuia (ascunderea informatiei!).
Daca se schimba antetul unui pachet automat este invalidat
corpul acestuia.
Referirea elementelor dintr-un pachet
Un pachet este proprietarul obiectelor incluse- similar cum
un tabel este proprietar al coloanelor sale. Pentru a specifica complet
un obiect dintr-un pachet se foloseste notatia cu punct.
DBMS_OUTPUT.PUT_LINE(Hello, World).
Exemplu: Urmatoarea specificatie de pachet declara o constanta, o exceptie, un cursor si cateva subprograme:
CREATE OR REPLACE PACKAGE pets_inc IS
Max_pets_in_facility CONSTANT INTEGER := 120;
Pet_is_sick EXCEPTION;
CURSOR pet_cur RETURN pet%ROWTYPE;
FUNCTION next_pet_shots(pet_id_in IN NUMBER) RETURN DATE;
PROCEDURE set_schedule(pet_id_in IN NUMBER);
END pets_inc;
Pentru a referi oricare din aceste obiecte intr-un alt bloc PL/SQL se va prefixa numele obiectului cu numale pachetului astfel:
BEGIN
IF pets_inc.max_pets_in_facility
> 100 THEN
END IF;
OPEN pets_inc.pet_cur;
:pet_master.next_appointment
:= pets_inc.next_pet_shots(:pet_master.pet_id);
EXCEPTION
WHEN pets_inc.pet_is_sick
THEN
END;
Daca apelul unui obiect nu este prefixat cu numele pachetului,
PL/SQL nu poate rezolva referinta si compilarea esueaza.
Daca intr-un pachet se face referire la un alt element al aceluiasi
pachet, nu este necesara prefixarea numelui elementuluireferit deoarce
PL/SQL rezolva automat referintele in interiorul domaniului
pachetului..
Modificarea si eliminarea pachetelor
ALTER PACKAGE nume_pachet COMPILE [PACKAGE | BODY]
DROP PACKAGE nume_pachet
DROP PACKAGE BODY nume_pachet