Delphi - Csomagok fejlesztése

Oracle adatbázis-kezelés 4. rész

forráskód letöltése
Miután megismertük, hogy milyen módszerekkel lehet a hatékonyság növelése érdekében tárolt eljárásokat és függvényeket létrehozni, mostani cikkünkben bemutatjuk, hogyan lehet ezeket az alprogramokat egy speciális adatabsztrakciós eszköz, a PL/SQL-csomag segítségével összefogni, csoportba rendezni, és logikailag egy egységként kezelni. Bemutatásra kerül továbbá az Oracle egy beépített csomagja, melyet jól használhatunk például a létrehozott alprogramok tesztelésekor, a fordítási hibák kiszűrésére.
A példaprogram használata előtt létre kell hozni egy SOUSER sémát az Oracle adatbázis-rendszerünkben, és fel kell ruházni DBA jogosultsággal. A mellékelt program az ezt megelőző cikk adattábláira támaszkodik, így az Oracle04.sql script lefuttatása csak az említett táblák hiánya esetén szükséges. Ezek meglétéről meg kell győződni, ugyanis ezek hiányában a létrehozandó további objektumok létrejönnek ugyan, de fordítási hibával. A sémába bejelentkezve le kell viszont futtatni a mellékelt Oracle04ph.sql és Oracle04pb.sql script-eket a hivatkozott további objektumok létrehozásához.
Csomagok fejlesztése
A csomag olyan, magasszintű adatabsztrakciós eszköz, mellyel összetartozó változókat, konstansokat és alprogramokat írhatjuk le, és kezelhetjük egy egységként. Felhasználója a csomagból pontosan annyit láthat egy előre definiált interfészen keresztül, amennyi a csomagban megvalósított funkciók végrehajtásához számára szükséges, de a konkrét megvalósítás részleteit a csomag felhasználója elől elrejti.
A PL/SQL csomagok a korábbiakban megismert objektumokat, nevezetesen konstansokat, változókat, tárolt eljárásokat és függvényeket, valamint a későbbiekben ismertetett kurzorokat, kivételes állapotokat tartalmazhatnak.
A csomagok két fő részből állnak:
  • Csomag specifikáció
A csomag nyilvános része. A csomag kívülről elérhető elemeit adja meg, melyeken keresztül a felhasználók a csomag objektumaira hivatkozhatnak. A csomag specifikáció típusdefiníciókat, konstans-, változó- és kurzor deklarációkat, valamint eljárás- és függvény definíciókat tartalmazhat, azonban blokkokat (tehát névtelen blokkot, illetve eljárás- vagy függvénytörzset) nem.
  • Csomagtörzs
A csomag privát része, melynek elemei a felhasználók számára nem hozzáférhetők. A csomag specifikációban megadott eljárások és függvények teljes definícióit tartalmazza (fejléccel és törzzsel együtt). Ezen kívül tartalmazhat még típusdefiníciókat, konstans, változó és kurzor deklarációkat is.
A csomag fejlesztése alapvetően 3 lépésből áll:
  • Készítsük el a csomag specifikációt, és helyezzük el egy szöveges állományban.
  • Készítsük el a csomag törzsét, és helyezzük el egy másik szöveges állományban.
  • Futtassuk a létrehozott szöveges állományokat az SQL*Plus segítségével. Ezzel a csomag fejét és törzsét tároltuk az adatbázisban, a forráskód P-kóddá alakul (a P-kódról bővebben az előző cikkben olvashat).
A csomag bármely nyilvános elemére hivatkozhatunk a szintaktikai szabályoknak megfelelően.
A nyilvános építőelemeket a csomagok specifikációs részében deklaráljuk a CREATE PACKAGE utasítás segítségével, melynek szintaxisa a következő:
CREATE OR REPLACE PACKAGE <csomagnév> IS
  {<típus definíció> | <kivétel definíció> | <konstans definíció> | <változó deklaráció> | <kurzor deklaráció> | <eljárás fej> | <függvény fej>}
END {<csomagnév>}
A nyilvános (csomag specifikációban deklarált) változók értékeire a csomagon kívülről is hivatkozhatunk, értékeik meg is változtathatók. A nyilvános eljárás vagy függvény a csomagon kívülről meghívható és végrehajtható.
A csomag specifikációban elhelyezett változók értéke közvetlenül olvasható és írható is, ez azonban a csomag strukturáltságát rontja, hiszen az alapelv az, hogy a csomagban elhelyezkedő adatokhoz csak a csomag procedúráin keresztül lehessen hozzáférni.
Ezért a legjobb módja a nyilvános változó deklarációjának a következő: hozzunk létre egy privát változót, és deklaráljunk olyan nyilvános alprogramokat, melyek a privát változó értékét változtatják, vagy adják vissza.
Lássunk ezzel kapcsolatban egy példát:
A példa EMP_PACK nevű csomagjában egy képzeletbeli, dolgozói adatokat tároló táblán (EMP) végezhetünk műveleteket anélkül, hogy ismernénk a tábla pontos felépítését. A függvénnyel felvehetünk egy dolgozót:
CREATE OR REPLACE PACKAGE EMP_PACK IS
  v_hired DATE;
  PROCEDURE hire_emp(p_empno IN NUMBER, p_name IN VARCHAR, p_sal IN NUMBER);
END EMP_PACK;
A csomag privát építőelemeinek helye tehát a csomagtörzs, melyet a következő szintaxissal hozhatunk létre:
CREATE OR REPLACE PACKAGE BODY <csomagnév> IS
{<típus definíció> | <kivétel definíció> | <konstans definíció> | <változó deklaráció> | <kurzor deklaráció> | <eljárás definíció> | <függvény definíció>}
END {<csomagnév>}
Mielőtt a csomag törzsében egy elemre hivatkoznánk, definiálnunk kell azt. Privát eljárások segítségével a nyilvános alprogramok törzsét modularizálhatjuk, ezzel áttekinthetőbbé tehetjük őket. A fenti példacsomag törzse:
CREATE OR REPLACE PACKAGE BODY EMP_PACK IS
  PROCEDURE hire_emp(p_empno IN NUMBER, p_name IN VARCHAR, p_sal IN NUMBER)
  IS
  BEGIN
    INSERT INTO EMP (empno, name, sal, hiredate) VALUES (p_empno, p_name, p_sal, v_hired);
    COMMIT;
  END hire_emp;
END EMP_PACK;
A változók kezdeti értékeinek ’bedrótozása’ helyett lehetőségünk van arra, hogy egy automatikusan végrehajtódó ’egylövetű’ (one-time-only) BEGIN-END blokkot készítsünk a csomagtörzsben. Egy adott munkameneten belül az egylövetű blokk végrehajtódik a csomag bármely elemének első meghívásakor. A fenti példához adjunk egy kiegészítést, mely a v_hired változó értékét állítja be az aktuális dátumra (feltételezve, hogy egyik munkamenet sem tart tovább egy napnál).
CREATE OR REPLACE PACKAGE BODY EMP_PACK IS
  -- Eljárás törzsek;
BEGIN
  V_hired := SYSDATE;
END EMP_PACK;
Csomagok tárolása, hivatkozás csomagok elemeire
Ahogy az alprogramokat, a csomagokat is az adatszótárba tárolja az Oracle. Létrehozásuk, törlésük és módosításuk is a megszokott módon történik:
Parancs Művelet
CREATE [OR REPLACE] PACKAGE Létrehoz egy új csomag specifikációt, vagy módosít egy már meglévőt.
CREATE [OR REPLACE] PACKAGE BODY Létrehoz egy új csomagtörzset, vagy módosít egy már meglévőt.
DROP PACKAGE Törli egy csomag specifikációját és törzsét is.
DROP PACKAGE BODY Törli egy csomag törzsét.
A csomag törzsének módosítása vagy törlése nem követeli meg a specifikáció megfelelő módosítását vagy törlését.
Miután a csomagot tároltuk az adatbázisban, annak egyes elemeire a csomagon belülről vagy kívülről is hivatkozatunk annak megfelelően, hogy az elem privát vagy nyilvános. Ha csomag elemére belülről hivatkozunk, nem kell kitenni az elem neve elé a csomag nevét. Kívülről való hivatkozáskor azonban meg kell adnunk a csomag nevét az elem neve előtt egy ponttal elválasztva. Az említett EMP_PACK csomag hire_emp nevű tárolt eljárására a következőképpen hivatkozhatunk:
EXECUTE EMP_PACK.HIRE_EMP(1001,...);
A csomagok használatának számos előnye van, amelyeket most összefoglalunk:
  • Javítják a tárolt alprogramok strukturáltságát: az összetartozó eljárásokat és függvényeket egy egységként kezelhetjük és feloldhatjuk az egy sémán belüli névkonfliktusokat.
  • A tárolt alprogramok kezelése egyszerűsödik: korlátozza a procedurális függéseket; a csomagok törzsét a specifikációtól függetlenül módosíthatjuk.
  • Javul a tárolt alprogramok használatának biztonsága: elrejti a forráskódot a felhasználók elől; a teljes csomagra érvényes hozzáférési jogokat csak egyszer kell megadni.
  • A változókra globálisan hivatkozhatunk bármely környezetből.
  • Javítja a teljesítményt: az első hivatkozáskor a teljes csomag a memóriába töltődik és lefordul, így csökken a lemezműveletek száma.
Az Oracle rendelkezik bizonyos előre gyártott csomagokkal, melyek funkciói elérhetők. A beépített csomagok közül egyet emelnénk ki, mely nagy segítséget jelenthet a tárolt alprogramok adatainak megjelenítésében, valamint a fordítási hibák felderítésében. A csomag neve DBMS_OUTPUT, melynek köszönhetően a tárolt alprogramok kimenő értékeit és üzeneteket jeleníthetünk meg. Ilyen módon adatokat gyűjthetünk egy pufferbe, ahol ezeket majd elérhetjük.
A DBMS_OUTPUT csomag elemei:
Elem neve Művelet
PUT Szöveget fűz a kimeneti puffer aktuális sorához.
NEW_LINE Sor vége jelet tesz a kimeneti pufferbe.
PUT_LINE Az előbbi kettő kombinációja.
GET_LINE Visszaadja a kimeneti puffer aktuális sorát.
GET_LINES Visszaadja a kimeneti puffer összes sorát.
ENABLE Engedélyezi a DBMS_OUTPUT alprogramjainak hívását.
DISABLE Letiltja a DBMS_OUTPUT alprogramjainak hívását.
Bizonyosodjunk meg róla, hogy a DMBS_OUTPUT csomag elérhető. Ehhez le kell futtatni a SYS sémában a dbmsotpt.sql parancsállományt, melyet a catproc.sql hív meg a procedurális opció installálásának részeként. A DBMS_OUTPUT puffer engedélyezésre és tiltására a SQL*Plus a SET SERVEROUTPUT ON/OFF parancsokat tartalmazza.
A mellékelt alkalmazásban egy csomagot használunk, melynek ’WriteString’ nevű eljárása illusztrálja, milyen módon írhatunk tárolt alprogramból a pufferbe. Az eljárás egy VARCHAR bemenő paramétert kap, melyet kiír a hívó környezetbe a DBMS_OUTPUT csomag PUT_LINE eljárása segítségével. A puffer engedélyezése után hívás a következő:
SET SERVEROUTPUT ON;
EXECUTE Collection.WriteString(’A kiírandó szöveg...’);
A mellékelt programban az Oracle04ph.sql és az Oracle04pb.sql parancsállományok segítségével hozható létre a ’Collection’ nevű csomag specifikációja és törzse. A tartalmazott eljárások nevei: ’GetSumPrice’ és ’WriteString’. Az előbbi eljárás műveletében megegyezik az ezt megelőző cikkben leírtakkal, vagyis megadja egy dolgozó neve alapján annak értékesítéseinek összegét. A Form elemei segítségével ez elvégezhető. Itt most a hangsúly a csomag elemeinek felhasználásán volt, vagyis hogy eljárásainkat egy csomag részeiként érjük el. Ennek érdekében a procCommand nevű TADOCommand komponens CommandText property-jében az eljárás minősített nevét kellett megadni:
DM.procCommand.CommandText := ’Collection.GetSumPrice’;
A mellékelt programban a fő Form alsó táblázatában tekinthető meg a TRIPS tábla adathalmaza, míg a DEALERS tábla értékeit a „DEALERS” feliratú gombra kattintva megjelenő Form-on nézhetjük meg. Ezekből követhetjük az eredmény helyességét.
A Form-on elhelyezett TabControl kontrol megfelelő fülét választva, majd a dolgozó nevét megadva a ComboBox kontrolban kapható meg az eredmény az „Összesítés” gomb megnyomásával.

Oracle adatbázis-kezelés cikksorozat