PL/SQL kurzorok és kivételkezelés
Kurzorok
Egy kurzor egy mutató, amely egy lekérdezés eredményhalmazára hivatkozik. Segítségével soronként dolgozhatjuk fel a rekordokat.
Kurzor típusai
| Típus | Leírás |
|---|---|
| Implicit kurzor | Az Oracle automatikusan létrehozza minden INSERT, UPDATE, DELETE, SELECT INTO utasítás után |
| Explicit kurzor | A fejlesztő hozza létre névvel, ha több sort szeretne feldolgozni |
Implicit kurzorok
Az Oracle automatikusan kezeli őket, pl. SELECT INTO esetén.
A SQL% attribútumokkal ellenőrizhetjük az utasítás eredményét.
Implicit kurzor attribútumok
| Attribútum | Leírás |
|---|---|
SQL%FOUND | TRUE, ha az utasítás legalább egy sort érintett |
SQL%NOTFOUND | TRUE, ha egy sort sem érintett |
SQL%ROWCOUNT | Az érintett sorok száma |
SQL%ISOPEN | Implicit kurzoroknál mindig FALSE |
Példa – implicit kurzor használata
BEGIN
UPDATE employees
SET salary = salary * 1.05
WHERE department_id = 50;
IF SQL%FOUND THEN
DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT || ' sor frissítve.');
ELSE
DBMS_OUTPUT.PUT_LINE('Nincs frissíthető dolgozó.');
END IF;
END;
Explicit kurzorok
Ha egy lekérdezés több sort ad vissza, explicit kurzort kell használni. Ezeket mi hozzuk létre, nyitjuk meg, olvassuk és zárjuk le.
Explicit kurzor attribútumok
| Attribútum | Jelentés |
|---|---|
%FOUND | Igaz, ha a legutóbbi FETCH visszaadott sort |
%NOTFOUND | Igaz, ha a FETCH nem adott vissza sort |
%ROWCOUNT | Eddig beolvasott sorok száma |
%ISOPEN | Igaz, ha a kurzor nyitva van |
Példa - explicit kurzor létrehozása és használata
DECLARE
CURSOR c_emps IS SELECT first_name, salary FROM employees;
v_name employees.first_name%TYPE;
v_salary employees.salary%TYPE;
BEGIN
OPEN c_emps; -- kurzor megnyitása
LOOP
FETCH c_emps INTO v_name, v_salary; -- következő sor beolvasása
EXIT WHEN c_emps%NOTFOUND; -- kilépés, ha nincs több sor
DBMS_OUTPUT.PUT_LINE(v_name || ': ' || v_salary);
END LOOP;
CLOSE c_emps; -- kurzor lezárása
END;
Kivételkezelés (EXCEPTION)
A kivételkezelés segítségével a program hibák esetén sem szakad meg, hanem kezelni tudjuk azokat.
Kivételkezelés szerkezete
BEGIN
-- fő logika
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Nincs ilyen adat.');
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('Túl sok sor tért vissza.');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Ismeretlen hiba történt.');
DBMS_OUTPUT.PUT_LINE('Hibakód: ' || SQLCODE);
DBMS_OUTPUT.PUT_LINE('Hibaüzenet: ' || SQLERRM);
END;
Beépített kivételek
| Kivétel neve | Mikor keletkezik |
|---|---|
NO_DATA_FOUND | SELECT INTO nem ad vissza sort |
TOO_MANY_ROWS | SELECT INTO több sort ad vissza |
ZERO_DIVIDE | Osztás nullával |
VALUE_ERROR | Típuskonverziós hiba vagy túl nagy szám |
OTHERS | Minden egyéb hiba |
Saját kivételek
Saját kivételeket is definiálhatunk a DECLARE részben, és RAISE utasítással váltjuk ki őket.
Példa – saját kivétel használata
DECLARE
e_low_salary EXCEPTION;
v_salary employees.salary%TYPE := 250000;
BEGIN
IF v_salary < 300000 THEN
RAISE e_low_salary;
END IF;
DBMS_OUTPUT.PUT_LINE('Fizetés rendben.');
EXCEPTION
WHEN e_low_salary THEN
DBMS_OUTPUT.PUT_LINE('A fizetés túl alacsony!');
END;
Feladatok
1. Feladat
Írj eljárást, amely:
Lekérdezi az employees tábla összes dolgozóját kurzorral akinek meghaladja a fizetése az 50000-et, majd kiírja a nevüket és fizetésüket.
2. Feladat
Készíts programot, amely:
SELECT INTO utasítással lekérdezi egy dolgozó adatait ID alapján, kezeli a NO_DATA_FOUND és TOO_MANY_ROWS kivételeket.
3. Feladat
Írj függvényt, amely:
Paraméterként kap egy fizetési értéket, saját kivételt dob, ha az kisebb 400000-nél, egyébként visszaadja a fizetést 10%-os bónusszal.