Ugrás a fő tartalomhoz

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ípusLeírás
Implicit kurzorAz Oracle automatikusan létrehozza minden INSERT, UPDATE, DELETE, SELECT INTO utasítás után
Explicit kurzorA 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útumLeírás
SQL%FOUNDTRUE, ha az utasítás legalább egy sort érintett
SQL%NOTFOUNDTRUE, ha egy sort sem érintett
SQL%ROWCOUNTAz érintett sorok száma
SQL%ISOPENImplicit 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útumJelentés
%FOUNDIgaz, ha a legutóbbi FETCH visszaadott sort
%NOTFOUNDIgaz, ha a FETCH nem adott vissza sort
%ROWCOUNTEddig beolvasott sorok száma
%ISOPENIgaz, 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 neveMikor keletkezik
NO_DATA_FOUNDSELECT INTO nem ad vissza sort
TOO_MANY_ROWSSELECT INTO több sort ad vissza
ZERO_DIVIDEOsztás nullával
VALUE_ERRORTípuskonverziós hiba vagy túl nagy szám
OTHERSMinden 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.