Kalmár György Adatbázis alapú rendszerek
Oracle-ben az SQL utasítások feldolgozásához szükség van egy ún. kontextus memóriára, amely az összes lényeges információt tárolja egy utasítás végrehajtásához. Pl: feldolgozandó sorok száma. A kurzor ezen területre mutató pointer, amelyen keresztül tehát információt szerezhetünk az SQL utasításokról és azok eredményeiről. Két féle kurzor létezik: Explicit Implicit
Automatikusan generálódik minden utasításhoz. Nem tudjuk módosítani. INSERT esetén: tárolja az adatot, ami beszúrásra kerül DELETE, UPDATE esetén: meghatározza a sorokat, amelyek érintettek lesznek Attribútumai: SQL%FOUND: a legutóbbi SQL utasítás legalább egy sort feldolgozott SQL%NOTFOUND: a legutóbbi SQL utasítás nem dolgozott fel sort SQL%ROWCOUNT: a kurzorral összesen feldolgozott sorok száma SQL%ISOPEN: igaz, ha a kurzor meg van nyitva Explicit kurzor esetén kurzornev%... alakúak
--Folyómenti városok száma. set serveroutput on; DECLARE TYPE folyomenti_tabla IS TABLE OF VAROSOK%ROWTYPE INDEX BY PLS_INTEGER; folyomenti_varosok folyomenti_tabla; SELECT * BULK COLLECT INTO folyomenti_varosok FROM VAROSOK WHERE FOLYOMENTIE=1; DBMS_OUTPUT.PUT_LINE('Folyomenti varosok szama: ' SQL%ROWCOUNT); /
BULK COLLECT Az előző példában láthatjuk, hogyan használható a BULK COLLECT arra, hogy egyszerre több sort mentsünk el egy asszociatív tömb (gyűjtőtábla) típusú változóba.
Mi definiáljuk és nagyobb ráhatásunk van a mutatott területre. A DECLARE-blokkban kell definiálni. Deklaráció: CURSOR kurzornév IS lekérdezés Megnyitás: OPEN kurzornév (megnyitáskor hajtódik végre a lekérdezés) Léptetés: FETCH kurzornév INTO változók (az aktuális sor adatai a változókba kerülnek és a kurzor eggyel előre lép, ellenőrizni kell, hogy a kurzorhoz tartozó eredménytáblának van-e sora) Lezárás: CLOSE kurzornév
--Folyómenti városok végigjárása explicit kurzorral. set serveroutput on; DECLARE CURSOR folyomentik IS SELECT * FROM VAROSOK WHERE FOLYOMENTIE=1; aktualis_varos VAROSOK%ROWTYPE; OPEN folyomentik; LOOP FETCH folyomentik INTO aktualis_varos; EXIT WHEN folyomentik%notfound; DBMS_OUTPUT.PUT_LINE('Folyomenti: ' aktualis_varos.nev); END LOOP; CLOSE folyomentik; /
--Folyómenti városok végigjárása explicit kurzorral. set serveroutput on; DECLARE CURSOR folyomentik IS SELECT * FROM VAROSOK WHERE FOLYOMENTIE=1; FOR aktualis_varos IN folyomentik LOOP DBMS_OUTPUT.PUT_LINE('Folyomenti: ' aktualis_varos.nev); END LOOP; /
--Folyómenti városok végigjárása explicit paraméteres kurzorral. set serveroutput on; DECLARE CURSOR varoslista(folyomenti_e VAROSOK.FOLYOMENTIE%TYPE) IS SELECT NEV FROM VAROSOK WHERE FOLYOMENTIE=folyomenti_e; folyomenti_e_var NUMBER(1) := 0; FOR aktualis_varos IN varoslista(folyomenti_e_var) LOOP DBMS_OUTPUT.PUT_LINE('Folyomenti_e: ' folyomenti_e_var ',neve:' aktualis_varos.nev); END LOOP; /
CURRENT OF KURZORNÉV - utoljára FETCH-elt sor módosítását vagy törlését engedi meg. FOR UPDATE OF ADATTAG - megmondjuk, hogy mely adattagot szeretnénk a kurzoron keresztül frissiteni NOWAIT - Ha egy másik tranzakció zárolta a kérédéses sort, akkor hibajelentéssel tovább fut
--A megadott nevü város irányítószámának növelése eggyel. set serveroutput on; DECLARE CURSOR novelendo(varosnev VAROSOK.NEV%TYPE) IS SELECT * FROM VAROSOK WHERE NEV=varosnev FOR UPDATE OF IRSZ NOWAIT; varos_record VAROSOK%ROWTYPE; irsz_valt VAROSOK.IRSZ%TYPE; OPEN novelendo('&bekert'); FETCH novelendo INTO varos_record; DBMS_OUTPUT.PUT_LINE('Elotte: ' varos_record.irsz); UPDATE VAROSOK SET IRSZ = varos_record.irsz+1 WHERE CURRENT OF novelendo; SELECT IRSZ INTO irsz_valt FROM VAROSOK WHERE NEV=varos_record.NEV; DBMS_OUTPUT.PUT_LINE('Utana: ' irsz_valt); /
Pseudooszlop nem általunk tárolt adat, de minden rekordhoz tárolt Egy rekord fizikai címe --A megadott nevü város országának kiirása ROWID-t használva. set serveroutput on; DECLARE row_id ROWID; orszag_valt VAROSOK.ORSZAG%TYPE; SELECT ROWID INTO row_id FROM VAROSOK WHERE NEV LIKE '&beker'; SELECT ORSZAG INTO orszag_valt FROM VAROSOK WHERE ROWID=row_id; DBMS_OUTPUT.PUT_LINE('A megadott varos ' orszag_valt ' orszagban talalhato.'); /
Névvel ellátott és paraméterezhető blokk Deklarációjuk a főprogram DECLARE szegmens végén Eljárások: PROCEDURE név [(paraméterek)] IS lokális deklarációk utasítások END [név]; IN, OUT, IN OUT paraméterek
--Személy kiirása eljárás segítségével set serveroutput on; DECLARE szemely_valt SZEMELY%ROWTYPE; PROCEDURE szemely_kiir( szemely_p IN SZEMELY%ROWTYPE ) IS DBMS_OUTPUT.PUT_LINE('A ' szemely_p.szigsz ' szigsz-u szemely, kinek neve ' szemely_p.nev ', a(z) ' szemely_p.orszag ' orszag ' szemely_p.irsz ' iranyitoszamu varosaban lakik. Szuletett: ' TO_CHAR(szemely_p.SZULETESIDATUM,'YYYY.MM.DD')); SELECT * INTO szemely_valt FROM SZEMELY WHERE ROWNUM<2; szemely_kiir(szemely_valt); /
Visszatérési értékkel is rendelkeznek. FUNCTION név [(paraméterek)] RETURN adattípus IS lokális deklarációk utasítások END [név];
--Megadott város lakosainak számának visszaadása függvénnyel. set serveroutput on; DECLARE lakosszam NUMBER; FUNCTION lakosok_szama(varosnev_p IN VAROSOK.NEV%TYPE) RETURN NUMBER IS cnt NUMBER; SELECT COUNT(SZEMELY.NEV) INTO cnt FROM VAROSOK,SZEMELY WHERE VAROSOK.NEV LIKE varosnev_p AND SZEMELY.IRSZ=VAROSOK.IRSZ AND SZEMELY.ORSZAG=VAROSOK.ORSZAG; RETURN cnt; lakosszam := lakosok_szama('&varosnev'); DBMS_OUTPUT.PUT_LINE('Lakosok szama: ' lakosszam);
Az elözöekhez hasonlóan kell öket definiálni, de nem csak az adott programban érhetök el, hanem az adatbázisban definiálódnak. deklaráció elejére CREATE feltüntetése alapértelmezés IN típusu paraméterekhez: paraméternév típus DEFAULT érték, paramétert csak a lista végéről lehet elhagyni tárolt eljárás PL/SQL blokkból futtatható, vagy SQL*Plus környezetben az EXECUTE paranccsal
CREATE PROCEDURE szemely_kiir( szemely_p IN SZEMELY%ROWTYPE ) IS DBMS_OUTPUT.PUT_LINE('A ' szemely_p.szigsz ' szigsz-u szemely, kinek neve ' szemely_p.nev ', a(z) ' szemely_p.orszag ' orszag ' szemely_p.irsz ' iranyitoszamu varosaban lakik. Szuletett: ' TO_CHAR(szemely_p.SZULETESIDATUM,'YYYY.MM.DD'));