• Nem Talált Eredményt

fejezet - Kivételkezelés

In document PL/SQL programozás (Pldal 101-106)

SELECT INTO

7. fejezet - Kivételkezelés

Egy PL/SQL programban a kivételek események. A kivételek rendszere a PL/SQL-ben a futás közben bekövetkező események (kiemelt módon a hibák) kezelését teszi lehetővé. A kivételek lehetnek beépített kivételek (amelyeket általában a futtató rendszer vált ki), vagy felhasználói kivételek, amelyeket valamelyik programegység deklarációs részében határoztunk meg. A beépített kivételeknek lehet nevük (például ZERO_DIVIDE), a felhasználói kivételeknek mindig van nevük. A felhasználói kivételeket mindig explicit módon, külön utasítással kell kiváltani. Ezzel az utasítással beépített kivétel is kiváltható.

A kivételek kezelésére a programegységekbe kivételkezelőt építhetünk be.

Egy kivételhez a PL/SQL-ben egy kód és egy üzenet tartozik. A beépített üzenetek kódja (egyetlen esettől eltekintve) negatív, a felhasználói kivételeké pozitív.

A beépített kivételeket a STANDARD csomag definiálja. A megnevezett beépített kivételek és a hozzájuk tartozó, az Oracle-rendszer által adott hibaüzenetek (ezek nyelve az NLS beállításoktól függ) a 7.1. táblázatban láthatók. A 7.2. táblázat ismerteti a beépített kivételek tipikus kiváltó okait.

7.1. táblázat - Hibaüzenetek

Kivétel Hibakód

SQLCOD E

Hibaüzenet SQLERRM

ACCESS_INTO_NULL -6530 ORA-06530: Incializálatlan összetett objektumra való hivatkozás

CASE_NOT_FOUND -6592 ORA-06592: CASE nem található a CASE állítás végrehajtásakor

COLLECTION_IS_NUL L

-6531 ORA-06531: Inicializálatlan gyűjtőre való hivatkozás

CURSOR_ALREADY_O PEN

-6511 ORA-06511: PL/SQL: A kurzor már meg van nyitva

DUP_VAL_ON_INDEX -1 ORA-00001: A(z) (.) egyediségre vonatkozó megszorítás nem teljesül

INVALID_CURSOR -1001 ORA-01001: Nem megengedett kurzor INVALID_NUMBER -1722 ORA-01722: Nem megengedett szám

LOGIN_DENIED -1017 ORA-01017: Nem megengedett

felhasználónév/jelszó; a bejelentkezés visszautasítva

NO_DATA_FOUND 100 ORA-01403: Nem talált adatot NOT_LOGGED_ON -1012 ORA-01012: Nincs bejelentkezve PROGRAM_ERROR –6501 ORA-06501: PL/SQL: programhiba

ROWTYPE_MISMATC -6504 ORA-06504: PL/SQL: Az Eredmény halmaz

Kivételkezelés

H változói vagy a kérdés visszaadott típusai nem

illeszkednek

SELF_IS_NULL -30625 ORA-30625: A metódus használata nem engedélyezett NULL SELF argumentummal STORAGE_ERROR -6500 ORA-06500: PL/SQL: tárolási hiba

SUBSCRIPT_BEYOND_

COUNT

-6533 ORA-06533: Számlálón kívüli indexérték

SUBSCRIPT_OUTSIDE_

LIMIT

-6532 ORA-06532: Határon kívüli index

SYS_INVALID_ROWID -1410 ORA-01410: Nem megengedett ROWID

TIMEOUT_ON_RESOU RCE

-51 ORA-00051: Időtúllépés történt erőforrásra várakozás közben

TOO_MANY_ROWS -1422 ORA-01422: A pontos lehívás (FETCH) a kívántnál több sorral tér vissza

VALUE_ERROR -6502 ORA-06502: PL/SQL: numerikus- vagy

értékhiba

ZERO_DIVIDE -1476 ORA-01476: Az osztó értéke nulla

7.2. táblázat - Beépített kivételek tipikus kiváltó okai

Kivétel Kiváltódik, ha …

ACCESS_INTO_NULL Megpróbál értéket adni egy inicializálatlan (automatikusan NULL) objektum attribútumának.

CASE_NOT_FOUND A CASE utasítás egyetlen WHEN ága sem egyezik meg a feltétellel és nincs ELSE ág.

COLLECTION_IS_NUL L

Megpróbál hivatkozni egy EXISTS-től különböző kollekciómetódusra egy inicializálatlan (automatikusan NULL) beágyazott tábla vagy dinamikus tömb esetén, vagy megpróbál értéket adni egy inicializálatlan beágyazott tábla vagy dinamikus tömb elemének.

CURSOR_ALREADY_O PEN

Megpróbál újra megnyitni egy már megnyitott kurzort. A kurzorokat le kell zárni, mielőtt újra megnyitjuk. A kurzor FOR ciklusa automatikusan megnyitja a hozzárendelt kurzort, így azt a ciklusban nem lehet újra megnyitni.

DUP_VAL_ON_INDEX Már létező értéket próbál meg tárolni egy adatbázistábla olyan oszlopában, amelyen egyedi (UNIQUE) indexmegszorítás van.

INVALID_CURSOR Megpróbál műveletet végezni egy meg nem nyitott kurzoron.

Kivételkezelés

INVALID_NUMBER SQL utasításban sikertelen egy karakterlánc konverziója, mert annak tartalma ténylegesen nem egy számot reprezentál. (A procedurális utasításokban ilyen konverziós hiba esetén VALUE_ERROR kivétel váltódik ki.) Ez a kivétel váltódik ki akkor is, ha a LIMIT előírás nem pozitív számot eredményez egy együttes hozzárendelést tartalmazó FETCH utasításban.

LOGIN_DENIED Bejelentkezéskor hibás a felhasználónév vagy a jelszó.

NO_DATA_FOUND Egy SELECT INTO utasítás nem ad vissza sorokat, vagy a programban hivatkozik egy beágyazott tábla törölt, vagy egy asszociatív tömb inicializálatlan elemére. Az SQL csoportfüggvényei, például AVG, SUM, mindig adnak vissza értéket vagy NULL-t, ezért csoportfüggvényt tartalmazó SELECT INTO utasítás sohasem váltja ki ezt a kivételt.

NOT_LOGGED_ON Megpróbál adatbázis-műveletet végrehajtani úgy, hogy nem kapcsolódik Oracle-példányhoz.

PROGRAM_ERROR PL/SQL belső hiba.

ROWTYPE_MISMATC H

Egy értékadásban a kurzor gazdaváltozó és az értékül adandó PL/SQL kurzor visszatérési típusa nem kompatibilis.

Például abban az esetben, ha egy már megnyitott kurzorváltozót adunk át egy alprogramnak, akkor a formális és aktuális paraméterek visszatérési típusának kompatibilisnek kell lennie. Ugyanígy előfordulhat, hogy egy megnyitott gyenge kurzorváltozót adunk értékül egy erős kurzorváltozónak, és azok visszatérési típusa nem kompatibilis.

SELF_IS_NULL Megpróbálja egy NULL referenciájú objektum metódusát meghívni, azaz a rögzített SELF paraméter (ami minden metódus első paramétere) NULL.

STORAGE_ERROR Elfogyott a PL/SQL számára rendelkezésre álló memória, vagy a memóriaterület megsérült.

SUBSCRIPT_BEYOND_

COUNT

Egy beágyazott tábla vagy dinamikus tömb méreténél nagyobb indexű elemére hivatkozik.

SUBSCRIPT_OUTSIDE_

LIMIT

Egy beágyazott tábla vagy dinamikus tömb elemére hivatkozik egy olyan indexszel, ami nincs a megengedett tartományban (például –1).

SYS_INVALID_ROWID Sikertelen egy karakterlánc konverziója ROWID típussá, mert a karakterlánc ténylegesen nem egy ROWID értéket

TOO_MANY_ROWS Egy SELECT INTO utasítás egynél több sort ad vissza.

Kivételkezelés

VALUE_ERROR Aritmetikai, konverziós, csonkítási vagy hosszmegszorítási hiba történik. Például ha egy sztring változónak a deklarált maximális hosszánál hosszabb sztringet próbál meg értékül adni, akár egy SELECT INTO utasítással. Ilyenkor az értékadás érvénytelen, semmis lesz és VALUE_ERROR kivétel váltódik ki. Procedurális utasítások esetén akkor is ez a kivétel váltódik ki, ha egy sztring konverziója számmá sikertelen (SQL utasításokban ilyenkor INVALID_NUMBER kivétel váltódik ki).

ZERO_DIVIDE Megpróbál nullával osztani.

Felhasználói kivételeket a EXCEPTION alapszóval deklarálhatunk:

DECLARE

sajat_kivetel EXCEPTION;

Olyan beépített kivételhez, amely eredetileg nincs nevesítve, egy pragma segítségével a programunkban nevet rendelhetünk egy programegység deklarációs részében. Ekkor deklarálnunk kell egy felhasználói kivételnevet, majd ugyanezen deklarációs részben később alkalmazni rá a pragmát. Ezután az adott beépített kivételt név szerint tudjuk kezelni. A pragma alakja:

PRAGMA EXCEPTION_INIT(kivételnév,kód);

1. példa DECLARE

i PLS_INTEGER;

j NUMBER NOT NULL := 1;

/* Egy névtelen hiba nevesítése. */

numeric_overflow EXCEPTION;

PRAGMA EXCEPTION_INIT(numeric_overflow, -1426); -- numeric overflow /* Egy már amúgy is nevesített kivételhez még egy név rendelése. */

VE_szinonima EXCEPTION;

PRAGMA EXCEPTION_INIT(VE_szinonima, -6502); -- VALUE_ERROR BEGIN

/* Kezeljük a numeric overflow hibát, PL/SQL-ben ehhez a hibához nincs előre definiálva kivételnév. */

<<blokk1>>

BEGIN i := 2**32;

EXCEPTION

WHEN numeric_overflow THEN

DBMS_OUTPUT.PUT_LINE('Blokk1 - numeric_overflow!' || SQLERRM);

END blokk1;

/* A VE_szinonima használható VALUE_ERROR helyett. */

Kivételkezelés

<<blokk2>>

BEGIN i := NULL;

j := i; -- VALUE_ERROR-t vált ki, mert i NULL.

DBMS_OUTPUT.PUT_LINE(j);

EXCEPTION

WHEN VE_szinonima THEN

DBMS_OUTPUT.PUT_LINE('Blokk2 - VALUE_ERROR: ' || SQLERRM);

END blokk2;

/* A VALUE_ERROR is használható VE_szinonima helyett. A két kivétel megegyezik. */

<<blokk2>>

BEGIN

RAISE VE_szinonima;

EXCEPTION

WHEN VALUE_ERROR THEN -- A saját kivételünk szinonima a VALUE_ERROR-ra DBMS_OUTPUT.PUT_LINE('Blokk3 - VALUE_ERROR: ' || SQLERRM);

END blokk1;

END;

/ /*

Eredmény:

Blokk1 - numeric_overflow!ORA-01426: numerikus túlcsordulás

Blokk2 - VALUE_ERROR: ORA-06502: PL/SQL: numerikus- vagy értékhiba () Blokk3 - VALUE_ERROR: ORA-06502: PL/SQL: numerikus- vagy értékhiba () A PL/SQL eljárás sikeresen befejeződött.

*/

Bármely megnevezett kivétel kiváltható a következő utasítással:

RAISE kivételnév;

Az utasítás bárhol elhelyezhető, ahol végrehajtható utasítás szerepelhet.

Kivételkezelő bármely programegység végén az EXCEPTION alapszó után helyezhető el. Felépítése a következő:

WHEN kivételnév [OR kivételnév]…

THEN utasítás [utasítás]…

[WHEN kivételnév [OR kivételnév]…

THEN utasítás [utasítás]…]…

Kivételkezelés

[WHEN OTHERS THEN utasítás [utasítás]…]

A kivételkezelő tehát olyan WHEN ágakból áll, amelyek név szerint kezelik a kivételeket és legutolsó ágként szerepelhet egy OTHERS ág, amely minden kivételt kezel.

Ha egy blokkban vagy alprogramban a végrehajtható részben bekövetkezik egy kivétel, akkor a végrehajtható rész futása félbeszakad és a futtató rendszer megvizsgálja, hogy a blokk vagy alprogram tartalmaz-e kivételkezelőt. Ha igen, megnézi, hogy valamelyik WHEN ágban nevesítve van-e a bekövetkezett kivétel. Ha igen, akkor végrehajtódnak a THEN után megadott utasítások. Ha köztük van GOTO, akkor a megadott címkén, ha nincs GOTO, blokk esetén a blokkot követő utasításon (ha van tartalmazó programegység) folytatódik a futás, egyébként pedig a vezérlés visszaadódik a hívási környezetbe. Az a programegység, amelyben egy kivétel bekövetkezik, inaktívvá válik, tehát futása nem folytatható. Így GOTO-val sem lehet visszatérni azon végrehajtható részre, ahol a kivétel bekövetkezett.

2. példa DECLARE

a NUMBER NOT NULL := 1;

b NUMBER;

In document PL/SQL programozás (Pldal 101-106)