A csomag egy olyan PL/SQL programegység, amely adatbázis-objektum és PL/SQL programozási eszközök gyűjteményének tekinthető. Két részből áll, specifikációból és törzsből. A törzs nem kötelező. A specifikáció és a törzs külön tárolódik az adatszótárban. A specifikáció egy interfészt biztosít, amelyen keresztül hozzáférhetünk a csomag eszközeihez. A specifikációban típusdefiníciók, nevesítettkonstans-deklarációk, változódeklarációk, kivételdeklarációk, kurzorspecifikációk, alprogram-specifikációk és pragmák helyezhetők el. Tehát a specifikáció futtatható kódot nem tartalmaz. A törzs tartalmazza a kurzorok és alprogramok teljes deklarációját, és esetlegesen végrehajtható utasításokat.
A csomagspecifikáció létrehozásának szintaxisa:
CREATE [OR REPLACE] PACKAGE csomagnév
[AUTHID {DEFINER|CURRENT_USER}]
{IS|AS}
{típus_definíció|
nevesített_konstans_deklaráció|
változó_deklaráció|
kivétel_deklaráció|
kurzor_specifikáció|
alprogram_specifikáció|
pragma}
END [csomagnév];
A törzs létrehozásának szintaxisa:
CREATE [OR REPLACE] PACKAGE BODY csomagnév
{IS|AS}
deklarációk
[BEGIN
végrehajtható_utasítások]
END [csomagnév];
A specifikáció és a törzs utasításrészeinek jelentése megegyezik az alprogramoknál tárgyalt CREATE utasítás utasításrészeinek jelentésével.
A csomag specifikációs részének deklarációi nyilvánosak, az itt deklarált eszközök láthatók és tetszés szerint alkalmazhatók a séma bármely alkalmazásában. A nyilvános eszközökre a csomag nevével történő minősítéssel lehet hivatkozni.
Az eszközök felsorolásának sorrendje tetszőleges, kivéve azt, hogy az alprogramoknak kötelezően a többi eszköz deklarációja után kell állniuk, mögöttük már csak pragma szerepelhet.
A PL/SQL hatásköri szabályai természetesen a csomagban is érvényesek, egy eszköz csak a deklaráció után látszik. Tehát ha egy csomagbeli eszközre hivatkozik egy másik csomagbeli eszköz, akkor azt hamarabb kell deklarálni. Természetesen a csomag teljes törzsében már minden olyan csomagbeli eszköz látszik, amelyet a specifikációban deklaráltunk.
Ha a specifikációban szerepel kurzorspecifikáció vagy alprogramspecifikáció, akkor kötelező megadni a törzset, ahol az adott eszközök teljes deklarációját (implementációját) meg kell adni.
A fejezet végén szerepel egy konyvtar_csomag nevű csomag. Ez a csomag deklarál egy nyilvános kurzort, amelynek implementációját a törzs tartalmazza:
CREATE OR REPLACE PACKAGE konyvtar_csomag
AS
⋮
CURSOR cur_lejart_kolcsonzesek(
p_Datum DATE DEFAULT SYSDATE
) RETURN t_lejart_rec;
⋮
END;
CREATE OR REPLACE PACKAGE BODY konyvtar_csomag
AS
⋮
/* Megadja a lejárt kölcsönzéseket. */
CURSOR cur_lejart_kolcsonzesek(
p_Datum DATE DEFAULT SYSDATE
) RETURN t_lejart_rec
IS
SELECT kolcsonzo, konyv, datum,
hosszabbitva, megjegyzes, napok
FROM
(SELECT kolcsonzo, konyv, datum, hosszabbitva, megjegyzes,
TRUNC(p_Datum, 'DD') - TRUNC(datum, 'DD')
- 30*(hosszabbitva+1) AS napok
FROM kolcsonzes)
WHERE napok > 0
;
⋮
END;
A törzsben szereplő deklarációk nem nyilvánosak (privát deklarációk), az itteni eszközök csak a törzsben használhatók.
A törzs végrehajtható utasításai tipikusan változók inicializációjára használatosak.
A fejezet végi konyvtar_csomag csomagban például a következő deklarációk privátak:
CREATE OR REPLACE PACKAGE BODY konyvtar_csomag
AS
⋮
v_Stat t_statisztika_rec;
⋮
/* Beállítja a v_Stat utolsó módosítási dátumát. */
PROCEDURE stat_akt
IS
BEGIN
v_Stat.utolso_modositas := SYSDATE;
END;
⋮
END;
Csomag létrehozásánál a PL/SQL fordító a tárolt alprogramoknál említett p-kódra fordítja le a specifikációt és a törzset. Előbb mindig a specifikációt kell létrehozni. A specifikáció és a törzs elkülönült kezelése lehetővé teszi, hogy a specifikáció változatlanul hagyása mellett a törzset lecseréljük. Az interfész marad, az implementáció megváltozik.
A csomag alprogramjainak nevei túlterhelhetők.
Távoli csomag változói sem közvetlenül, sem közvetett módon nem hivatkozhatók.
Egy csomagban nem használhatunk gazdaváltozót.
A csomag törzsének inicializációs része csak egyszer, a csomagra való első hivatkozáskor fut le.
Ha egy csomag eszközeit csak egyetlen szerverhívásban használjuk, akkor a SERIALLY_REUSABLE pragmával szeriálisan újrafelhasználhatónak minősíthetjük. A pragmát el kell helyezni mind a specifikációban, mind a törzsben. Ekkor a csomag számára a Rendszer Globális Területen (SGA) belül lesz memória lefoglalva, nem pedig az egyes felhasználói területeken, ezért a csomag munkaterülete újrafelhasználható. Az ilyen csomag nyilvános változói minden újrafelhasználás előtt újra kezdőértéket kapnak és lefut a csomag törzsének inicializációs része. Meg kell jegyezni, hogy egy szerverhívásban többször is hivatkozhatunk a csomag elemeire, azok a két hivatkozás között megőrzik értéküket.
A csomag mint adatbázis-objektum megváltoztatására szolgál a következő SQL-parancs:
ALTER PACKAGE csomagnév COMPILE [DEBUG]
[PACKAGE|SPECIFICATION|BODY];
A DEBUG előírja a PL/SQL fordítónak, hogy a p-kód generálásánál használja a PL/SQL nyomkövetőjét.
A PACKAGE (ez az alapértelmezés) megadása esetén a csomag specifikációja és törzse is újrafordítódik. SPECIFICATION esetén a specifikáció, BODY esetén a törzs újrafordítására kerül sor.
A specifikáció újrafordítása esetén minden olyan alkalmazást, amely hivatkozik a csomag eszközeire, újra kell fordítani.
A csomag törlésére a következő utasítás szolgál:
DROP PACKAGE [BODY] csomagnév;
BODY megadása esetén csak a törzs, egyébként a törzs és a specifikáció is törlődik az adatszótárból.
A PL/SQL nyelvi környezetét beépített csomag határozza meg, neve: STANDARD. Ez a csomag globálisan használható típusokat, kivételeket és alprogramokat tartalmaz, amelyek közvetlenül, minősítés nélkül hivatkozhatók minden alkalmazásban. A STANDARD csomag nagyon sok beépített függvénye túlterhelt. Például a TO_CHAR függvény következő specifikációi léteznek benne:
FUNCTION TO_CHAR (right DATE) RETURN VARCHAR2;
FUNCTION TO_CHAR (left NUMBER) RETURN VARCHAR2;
FUNCTION TO_CHAR (left DATE, right VARCHAR2) RETURN VARCHAR2;
FUNCTION TO_CHAR (left NUMBER, right VARCHAR2) RETURN VARCHAR2;
Az Oracle és a különböző Oracle-eszközök termékspecifikus beépített csomagokat bocsátanak a felhasználó rendelkezésére. Ezekkel sokkal hatékonyabban és gyorsabban lehet alkalmazásokat fejleszteni.
Ha saját csomagot írunk, törekedjünk arra, hogy azt a lehető legáltalánosabb formában hozzuk létre, hogy a későbbi újrafelhasználást elősegítsük. A csomagspecifikáció mindig az alkalmazás tervéhez kapcsolódjon, mindig ezt írjuk meg először és csak a feltétlenül szükséges eszközök szerepeljenek benne.
A következőkben megadunk egy saját csomagot, amely a könyvtárunk adatainak kezelését segíti elő. A csomag neve konyvtar_csomag. A csomag specifikációja a következő:
CREATE OR REPLACE PACKAGE konyvtar_csomag AS
/******************************************/
/* Mindenki számára elérhető deklarációk. */
/******************************************/
TYPE t_statisztika_rec IS RECORD (
uj_ugyfelek NUMBER := 0,
uj_konyvek NUMBER := 0,
kolcsonzesek NUMBER := 0,
visszahozott_konyvek NUMBER := 0,
utolso_modositas DATE := SYSDATE,
utolso_nullazas DATE := SYSDATE
);
TYPE t_lejart_rec IS RECORD (
kolcsonzo kolcsonzes.kolcsonzo%TYPE,
konyv kolcsonzes.kolcsonzo%TYPE,
datum kolcsonzes.datum%TYPE,
hosszabbitva kolcsonzes.hosszabbitva%TYPE,
megjegyzes kolcsonzes.megjegyzes%TYPE,
napok INTEGER
);
/* Megadja az adott dátum szerint lejárt kölcsönzésekhez
a kölcsönzési rekordot és a lejárat óta eltelt napok számát.
Ha nem adunk meg dátumot, akkor az aktuális
dátum lesz a kezdeti érték.
Megjegyzés: a törzs nélküli kurzor deklarációnak
visszatérési típussal kell rendelkeznie */
CURSOR cur_lejart_kolcsonzesek(
p_Datum DATE DEFAULT SYSDATE
) RETURN t_lejart_rec;
/* Egy új ügyfélnek mindig ennyi lesz a kvótája. */
c_Max_konyv_init CONSTANT NUMBER := 5;
/* Az alprogramok által kiváltott kivételek. */
hibas_argumentum EXCEPTION;
PRAGMA EXCEPTION_INIT(hibas_argumentum, -20100);
ervenytelen_kolcsonzes EXCEPTION;
PRAGMA EXCEPTION_INIT(ervenytelen_kolcsonzes, -20110);
kurzor_hasznalatban EXCEPTION;
PRAGMA EXCEPTION_INIT(ervenytelen_kolcsonzes, -20120);
/*************************************************/
/* A könyvtárban használatos gyakori alprogramok */
/*************************************************/
/* Megadja az ügyfelet az azonosítóhoz.
Nem létező ügyfél esetén hibas_argumentum kivételt vált ki. */
FUNCTION az_ugyfel(p_Ugyfel ugyfel.id%TYPE) RETURN ugyfel%ROWTYPE;
/* Megadja a könyvet az azonosítóhoz.
Nemlétező könyv esetén hibas_argumentum kivételt vált ki. */
FUNCTION a_konyv(p_Konyv konyv.id%TYPE) RETURN konyv%ROWTYPE;
/* Felvesz egy ügyfelet a könyvtárba a szokásos
kezdeti kvótával és az aktuális dátummal, a
kölcsönzött könyvek oszlopot üres kollekcióra állítja.
Visszatérési értéke az új ügyfél azonosítója. */
FUNCTION uj_ugyfel(
p_Nev ugyfel.nev%TYPE,
p_Anyja_neve ugyfel.anyja_neve%TYPE,
p_Lakcim ugyfel.lakcim%TYPE,
p_Tel_szam ugyfel.tel_szam%TYPE,
p_Foglalkozas ugyfel.foglalkozas%TYPE
) RETURN ugyfel.id%type;
/* Raktárra vesz az adott ISBN kódú könyvből megadott példányt.
Ha van már ilyen könyv, akkor hozzáadja az új készletet a régihez.
Ilyenkor csak az ISBN szám kerül egyeztetésre
a többi paraméter értékét a függvény nem veszi figyelembe.
Visszatérési érték a könyvek azonosítója. */
FUNCTION konyv_raktarba(
p_ISBN konyv.ISBN%TYPE,
p_Cim konyv.cim%TYPE,
p_Kiado konyv.kiado%TYPE,
p_Kiadasi_ev konyv.kiadasi_ev%TYPE,
p_Szerzo konyv.szerzo%TYPE,
p_Darab INTEGER
) RETURN konyv.id%type;
/* Egy ügyfél számára kölcsönöz egy könyvet:
- felveszi a kölcsönzési rekordot a kolcsonzes táblába
és az ugyfel.konyvek beágyazott táblába.
- aktualizálja az ügyfél kvótáját és a könyv szabad
példányainak számát.
Nemlétező könyv, illetve ügyfél esetén hibas_argumentum kivétel,
ha az ügyfélnek 0 a kvótája, vagy nincs szabad példány, akkor
ervenytelen_kolcsonzes kivétel váltódik ki. */
PROCEDURE kolcsonoz(
p_Ugyfel ugyfel.id%TYPE,
p_Konyv konyv.id%TYPE
);
/* Adminisztrálja egy könyv visszahozatalát:
- naplózza a kölcsönzést a kolcsonzes_naplo táblában
- törli a kölcsönzési rekordot a kolcsonzes táblából
és az ugyfel.konyvek beágyazott táblából.
- aktualizálja a könyv szabad példányainak számát.
Ha a paraméterek nem jelölnek valódi kölcsönzési
bejegyzést, akkor hibas_argumentum kivétel váltódik ki. */
PROCEDURE visszahoz(
p_Ugyfel ugyfel.id%TYPE,
p_Konyv konyv.id%TYPE
);
/* Adminisztrálja egy ügyfél összes könyvének visszahozatalát:
- naplózza a kölcsönzéseket a kolcsonzes_naplo táblában
- törli a kölcsönzési rekordokat a kolcsonzes táblából
és az ugyfel.konyvek beágyazott táblából.
- aktualizálja a könyvek szabad példányainak számát.
Ha az ügyfél nem létezik hibas_argumentum kivétel váltódik ki.
Megj.: Ez az eljárásnév túl van terhelve. */
PROCEDURE visszahoz(p_Ugyfel ugyfel.id%TYPE);
/* Kilistázza a lejárt kölcsönzési rekordokat.
Ha a cur_lejart_kolcsonzesek kurzor nyitva van,
az eljárás nem használható. Ilyenkor
kurzor_hasznalatban kivétel váltódik ki. */
PROCEDURE lejart_konyvek;
/* Kilistázza a lejárt kölcsönzési rekordok közül
azokat, amelyek ma jártak le.
Ha a cur_lejart_kolcsonzesek kurzor nyitva van,
az eljárás nem használható. Ilyenkor
kurzor_hasznalatban kivétel váltódik ki. */
PROCEDURE mai_lejart_konyvek;
/* Megadja egy kölcsönzött könyv hátralevő kölcsönzési idejét.
hibas_argumentum kivételt vált ki, ha nincs ilyen kölcsönzés. */
FUNCTION hatralevo_napok(
p_Ugyfel ugyfel.id%TYPE,
p_Konyv konyv.id%TYPE
) RETURN INTEGER;
/*******************************************************************/
/* A csomag használatára vonatkozó statisztikát kezelő alprogramok */
/*******************************************************************/
/* Megadja a statisztikát a legutóbbi nullázás, ill. az indulás óta. */
FUNCTION statisztika RETURN t_statisztika_rec;
/* Kiírja a statisztikát a legutóbbi nullázás ill. az indulás óta. */
PROCEDURE print_statisztika;
/* Nullázza a statisztikát. */
PROCEDURE statisztika_nullaz;
END konyvtar_csomag;
/
show errors
A csomag törzse:
CREATE OR REPLACE PACKAGE BODY konyvtar_csomag
AS
/***********************/
/* Privát deklarációk. */
/***********************/
/* A csomag statisztikáját tartalmazó privát rekord. */
v_Stat t_statisztika_rec;
/******************/
/* Implementációk. */
/******************/
/* Megadja a lejárt kölcsönzéseket. */
CURSOR cur_lejart_kolcsonzesek(p_Datum DATE DEFAULT SYSDATE) RETURN t_lejart_rec
IS
SELECT kolcsonzo, konyv, datum, hosszabbitva, megjegyzes, napok
FROM (SELECT kolcsonzo, konyv, datum, hosszabbitva, megjegyzes,
TRUNC(p_Datum, 'DD') - TRUNC(datum, 'DD')
- 30*(hosszabbitva+1) AS napok
FROM kolcsonzes)
WHERE napok > 0;
/*************************/
/* Privát alprogramok. */
/*************************/
/* Beállítja a v_Stat utolsó módosítási dátumát. */
PROCEDURE stat_akt IS
BEGIN
v_Stat.utolso_modositas := SYSDATE;
END stat_akt;
/* Pontosan p_Hossz hosszan adja meg a p_Sztringet, ha kell
csonkolja, ha kell szóközökkel egészíti ki. */
FUNCTION str(
p_Sztring VARCHAR2,
p_Hossz INTEGER
) RETURN VARCHAR2 IS
BEGIN
RETURN RPAD(SUBSTR(p_Sztring, 1, p_Hossz), p_Hossz);
END str;
/* Kivételek kiváltása hibaüzenetekkel. */
PROCEDURE raise_hibas_argumentum IS
BEGIN
RAISE_APPLICATION_ERROR(-20100, 'Hibás argumentum');
END raise_hibas_argumentum;
PROCEDURE raise_ervenytelen_kolcsonzes IS
BEGIN
RAISE_APPLICATION_ERROR(-20110, 'Érvénytelen kölcsönzés');
END raise_ervenytelen_kolcsonzes;
PROCEDURE raise_kurzor_hasznalatban IS
BEGIN
RAISE_APPLICATION_ERROR(-20120, 'A kurzor használatban van.');
END raise_kurzor_hasznalatban;
/*************************************************/
/* A könyvtárban használatos gyakori alprogramok */
/*************************************************/
/* Megadja az ügyfelet az azonosítóhoz.
Nem létező ügyfél esetén hibas_argumentum kivételt vált ki. */
FUNCTION az_ugyfel(p_Ugyfel ugyfel.id%TYPE) RETURN ugyfel%ROWTYPE IS
v_Ugyfel ugyfel%ROWTYPE;
BEGIN
SELECT * INTO v_Ugyfel
FROM ugyfel WHERE id = p_Ugyfel;
RETURN v_Ugyfel;
EXCEPTION
WHEN NO_DATA_FOUND THEN
raise_hibas_argumentum;
END az_ugyfel;
/* Megadja a könyvet az azonosítóhoz.
Nem létező könyv esetén hibas_argumentum kivételt vált ki. */
FUNCTION a_konyv(p_Konyv konyv.id%TYPE) RETURN konyv%ROWTYPE IS
v_Konyv konyv%ROWTYPE;
BEGIN
SELECT * INTO v_Konyv
FROM konyv WHERE id = p_Konyv;
RETURN v_Konyv;
EXCEPTION
WHEN NO_DATA_FOUND THEN
raise_hibas_argumentum;
END a_konyv;
/* Felvesz egy ügyfelet a könyvtárba a szokásos kezdeti kvótával
és az aktuális dátummal, a kölcsönzött könyvek oszlopot
üres kollekcióra állítja.
Visszatérési értéke az új ügyfél azonosítója. */
FUNCTION uj_ugyfel(
p_Nev ugyfel.nev%TYPE,
p_Anyja_neve ugyfel.anyja_neve%TYPE,
p_Lakcim ugyfel.lakcim%TYPE,
p_Tel_szam ugyfel.tel_szam%TYPE,
p_Foglalkozas ugyfel.foglalkozas%TYPE
) RETURN ugyfel.id%type IS
v_Id ugyfel.id%type;
BEGIN
SELECT ugyfel_seq.nextval
INTO v_Id
FROM dual;
INSERT INTO ugyfel VALUES
(v_Id, p_Nev, p_Anyja_neve,
p_Lakcim, p_Tel_szam, p_Foglalkozas,
SYSDATE, c_Max_konyv_init, T_Konyvek());
/* A statisztika aktualizálása. */
stat_akt;
v_Stat.uj_ugyfelek := v_Stat.uj_ugyfelek + 1;
RETURN v_Id;
END uj_ugyfel;
/* Raktárra vesz az adott ISBN kódú könyvből megadott példányt.
Ha van már ilyen könyv, akkor hozzáadja az új készletet a régihez.
Ilyenkor csak az ISBN számot egyezteti,
a többi paraméter értékét a függvény nem veszi figyelembe.
Visszatérési érték a könyvek azonosítója. */
FUNCTION konyv_raktarba(
p_ISBN konyv.ISBN%TYPE,
p_Cim konyv.cim%TYPE,
p_Kiado konyv.kiado%TYPE,
p_Kiadasi_ev konyv.kiadasi_ev%TYPE,
p_Szerzo konyv.szerzo%TYPE,
p_Darab INTEGER
) RETURN konyv.id%type IS
v_Id konyv.id%type;
BEGIN
/* Megpróbáljuk módosítani a könyv adatait. */
UPDATE konyv
SET keszlet = keszlet + p_Darab,
szabad = szabad + p_Darab
WHERE UPPER(ISBN) = UPPER(p_ISBN)
RETURNING id INTO v_Id;
IF SQL%NOTFOUND THEN
/* Mégiscsak INSERT lesz ez. */
SELECT konyv_seq.nextval
INTO v_Id
FROM dual;
INSERT INTO konyv VALUES
(v_Id, p_ISBN, p_Cim,
p_Kiado, p_Kiadasi_ev, p_Szerzo,
p_Darab, p_Darab);
/* A statisztika aktualizálása. */
stat_akt;
v_Stat.uj_konyvek := v_Stat.uj_konyvek + 1;
END IF;
RETURN v_Id;
END;
/* Egy ügyfél számára kölcsönöz egy könyvet:
- felveszi a kölcsönzési rekordot a kolcsonzes táblába
és az ugyfel.konyvek beágyazott táblába;
- aktualizálja az ügyfél kvótáját és a könyv szabad
példányainak számát.
Nem létező könyv, illetve ügyfél esetén hibas_argumentum kivétel,
ha az ügyfélnek 0 a kvótája, vagy nincs szabad példány, akkor
ervenytelen_kolcsonzes kivétel váltódik ki. */
PROCEDURE kolcsonoz(
p_Ugyfel ugyfel.id%TYPE,
p_Konyv konyv.id%TYPE
) IS
v_Most DATE;
v_Szam NUMBER;
BEGIN
SAVEPOINT kezdet;
v_Most := SYSDATE;
/* Próbáljuk meg beszúrni a kölcsönzési rekordot. */
BEGIN
INSERT INTO kolcsonzes VALUES (p_Ugyfel, p_Konyv, v_Most, 0,
'A bejegyzést a konyvtar_csomag hozta létre');
EXCEPTION
WHEN OTHERS THEN
-- Csak az integritási megszorítással lehetett baj.
raise_hibas_argumentum;
END;
BEGIN
/* A következő SELECT nem ad vissza sort,
ha nem lehet többet kölcsönöznie az ügyfélnek. */
SELECT 1 INTO v_Szam
FROM ugyfel
WHERE id = p_Ugyfel
AND max_konyv - (SELECT COUNT(1) FROM TABLE(konyvek)) > 0;
/* Ha csökkentjük a szabad példányok számát,
megsérthetjük a konyv_szabad megszorítást. */
UPDATE konyv SET szabad = szabad - 1 WHERE id = p_Konyv;
INSERT INTO TABLE(SELECT konyvek FROM ugyfel WHERE id = p_Ugyfel)
VALUES (p_Konyv, v_Most);
/* A statisztika aktualizálása. */
stat_akt;
EXCEPTION
WHEN OTHERS THEN -- kvóta vagy szabad példány nem megfelelő
ROLLBACK TO kezdet;
raise_ervenytelen_kolcsonzes;
END;
END kolcsonoz;
/* Adminisztrálja egy könyv visszahozatalát:
- naplózza a kölcsönzést a kolcsonzes_naplo táblában;
- törli a kölcsönzési rekordot a kolcsonzes táblából
és az ugyfel.konyvek beágyazott táblából;
- aktualizálja a könyv szabad példányainak számát.
Ha a paraméterek nem jelölnek valódi kölcsönzési
bejegyzést, akkor hibas_argumentum kivétel váltódik ki. */
PROCEDURE visszahoz(
p_Ugyfel ugyfel.id%TYPE,
p_Konyv konyv.id%TYPE
) IS
v_Datum kolcsonzes.datum%TYPE;
BEGIN
DELETE FROM kolcsonzes
WHERE konyv = p_Konyv
AND kolcsonzo = p_Ugyfel
AND rownum = 1
RETURNING datum INTO v_Datum;
IF SQL%ROWCOUNT = 0 THEN
raise_hibas_argumentum;
END IF;
UPDATE konyv SET szabad = szabad + 1
WHERE id = p_Konyv;
DELETE FROM TABLE(SELECT konyvek FROM ugyfel WHERE id = p_Ugyfel)
WHERE konyv_id = p_konyv
AND datum = v_Datum;
/* A statisztika aktualizálása */
stat_akt;
v_Stat.visszahozott_konyvek := v_Stat.visszahozott_konyvek - 1;
END visszahoz;
/* Adminisztrálja egy ügyfél összes könyvének visszahozatalát:
- naplózza a kölcsönzéseket a kolcsonzes_naplo táblában;
- törli a kölcsönzési rekordokat a kolcsonzes táblából
és az ugyfel.konyvek beágyazott táblából;
- aktualizálja a könyvek szabad példányainak számát.
Ha az ügyfél nem létezik, hibas_argumentum kivétel váltódik ki.
Megj.: Ez az eljárásnév túl van terhelve.*/
PROCEDURE visszahoz(p_Ugyfel ugyfel.id%TYPE) IS
v_Szam NUMBER;
BEGIN
/* Az csoportfüggvényeket tartalmazó SELECT mindig ad vissza sort. */
SELECT COUNT(1) INTO v_Szam
FROM ugyfel WHERE id = p_Ugyfel;
IF v_Szam = 0 THEN
raise_hibas_argumentum;
END IF;
/* Töröljük egyenként a kölcsönzéseket. */
FOR k IN (SELECT * FROM kolcsonzes
WHERE kolcsonzo = p_Ugyfel
) LOOP
visszahoz(p_Ugyfel, k.konyv);
END LOOP;
END visszahoz;
/* Kilistázza a lejárt kölcsönzési rekordokat.
Ha a cur_lejart_kolcsonzesek kurzor nyitva van,
az eljárás nem használható. Ilyenkor
kurzor_hasznalatban kivétel váltódik ki. */
PROCEDURE lejart_konyvek IS
BEGIN
IF cur_lejart_kolcsonzesek%ISOPEN THEN
raise_kurzor_hasznalatban;
END IF;
DBMS_OUTPUT.PUT_LINE(str('Ügyfél', 40) || ' ' || str('Könyv', 50)
|| ' ' || str('dátum', 18) || 'napok');
DBMS_OUTPUT.PUT_LINE(RPAD('', 120, '-'));
FOR k IN cur_lejart_kolcsonzesek LOOP
DBMS_OUTPUT.PUT_LINE(
str(k.kolcsonzo || ' ' || az_ugyfel(k.kolcsonzo).nev, 40)
|| ' ' || str(k.konyv || ' ' || a_konyv(k.konyv).cim, 50)
|| ' ' || TO_CHAR(k.datum, 'YYYY-MON-DD HH24:MI')
|| ' ' || k.napok
);
END LOOP;
END lejart_konyvek;
/* Kilistázza a lejárt kölcsönzési rekordok közül
azokat, amelyek ma jártak le.
Ha a cur_lejart_kolcsonzesek kurzor nyitva van,
az eljárás nem használható. Ilyenkor
kurzor_hasznalatban kivétel váltódik ki. */
PROCEDURE mai_lejart_konyvek IS
BEGIN
IF cur_lejart_kolcsonzesek%ISOPEN THEN
raise_kurzor_hasznalatban;
END IF;
DBMS_OUTPUT.PUT_LINE(str('Ügyfél', 40) || ' ' || str('Könyv', 50)
|| ' ' || str('dátum', 18) || 'napok');
DBMS_OUTPUT.PUT_LINE(RPAD('', 120, '-'));
FOR k IN cur_lejart_kolcsonzesek LOOP
IF k.napok = 1 THEN
DBMS_OUTPUT.PUT_LINE(
str(k.kolcsonzo || ' ' || az_ugyfel(k.kolcsonzo).nev, 40)
|| ' ' || str(k.konyv || ' ' || a_konyv(k.konyv).cim, 50)
|| ' ' || TO_CHAR(k.datum, 'YYYY-MON-DD HH24:MI')
);
END IF;
END LOOP;
END mai_lejart_konyvek;
/* Megadja egy kölcsönzött könyv hátralevő kölcsönzési idejét.
hibas_argumentum kivételt vált ki, ha nincs ilyen kölcsönzés. */
FUNCTION hatralevo_napok(
p_Ugyfel ugyfel.id%TYPE,
p_Konyv konyv.id%TYPE
) RETURN INTEGER IS
v_Datum kolcsonzes.datum%TYPE;
v_Most DATE;
v_Hosszabbitva kolcsonzes.hosszabbitva%TYPE;
BEGIN
SELECT datum, hosszabbitva
INTO v_Datum, v_Hosszabbitva
FROM kolcsonzes
WHERE kolcsonzo = p_Ugyfel
AND konyv = p_Konyv;
/* Levágjuk a dátumokból az óra részt. */
v_Datum := TRUNC(v_Datum, 'DD');
v_Most := TRUNC(SYSDATE, 'DD');
/* Visszaadjuk a különbséget. */
RETURN (v_Hosszabbitva + 1) * 30 + v_Datum - v_Most;
EXCEPTION
WHEN NO_DATA_FOUND THEN
raise_hibas_argumentum;
END hatralevo_napok;
/*******************************************************************/
/* A csomag használatára vonatkozó statisztikát kezelő alprogramok */
/*******************************************************************/
/* Megadja a statisztikát a legutóbbi nullázás, ill. az indulás óta. */
FUNCTION statisztika RETURN t_statisztika_rec IS
BEGIN
RETURN v_Stat;
END statisztika;
/* Kiírja a statisztikát a legutóbbi nullázás ill. az indulás óta. */
PROCEDURE print_statisztika IS
BEGIN
DBMS_OUTPUT.PUT_LINE('Statisztika a munkamenetben:');
DBMS_OUTPUT.NEW_LINE;
DBMS_OUTPUT.PUT_LINE(RPAD('Regisztrált új ügyfelek száma:', 40)
|| v_Stat.uj_ugyfelek);
DBMS_OUTPUT.PUT_LINE(RPAD('Regisztrált új könyvek száma:', 40)
|| v_Stat.uj_konyvek);
DBMS_OUTPUT.PUT_LINE(RPAD('Kölcsönzések száma:', 40)
|| v_Stat.kolcsonzesek);
DBMS_OUTPUT.PUT_LINE(RPAD('Visszahozott könyvek száma:', 40)
|| v_Stat.visszahozott_konyvek);
DBMS_OUTPUT.PUT_LINE(RPAD('Utolsó módosítás: ', 40)
|| TO_CHAR(v_Stat.utolso_modositas, 'YYYY-MON-DD HH24:MI:SS'));
DBMS_OUTPUT.PUT_LINE(RPAD('Statisztika kezdete: ', 40)
|| TO_CHAR(v_Stat.utolso_nullazas, 'YYYY-MON-DD HH24:MI:SS'));
END print_statisztika;
/* Nullázza a statiszikát. */
PROCEDURE statisztika_nullaz IS
v_Stat2 t_statisztika_rec;
BEGIN
v_Stat := v_Stat2;
END statisztika_nullaz;
/********************************/
/* A csomag inicializáló része. */
/********************************/
BEGIN
statisztika_nullaz;
END konyvtar_csomag;
/
show errors