Pachete


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