A PL/SQL programozási nyelv

Utasítások, vezérlési szerkezetek

Értékadás, üres utasítás

A legegyszerűbb művelet az értékadás művelete. Az értékadás bal oldalán változónak kell állnia, jobb oldalán pedig változókból, konstansokból és beépített függvényekből álló kifejezés szerepel. Az alábbi példában az x változó értékét eggyel megnöveljük:

x := x + 1;

Illetve a másik lehetőség:

SELECT (FETCH) INTO

Az utóbbival nem lehet logikai változónak értéket adni.

Az üres utasítás létezik! Formája:

NULL;

Kifejezések, operátorok

A kifejezés operátorokból és operandusokból áll. Az operandus lehet literál, nevesített konstans, változó és függvényhívás. Az operátorok lehetnek egyoperandusúak vagy kétoperandusúak.
A kifejezés kiértékelése azt jelenti, hogy az operandusok értékeit felhasználva, az operátorok által meghatározott műveletek adott sorrendben végrehajtódnak, és egy adott típusú értéket kapunk eredményül.
A kifejezések tetszőlegesen zárójelezhetők. A zárójel az operátorok precedenciáját határozza meg

Az operátorok csoportosítása:

Aritmetikai operátorok

Aritemtikai operátorok

Karakteres operátorok
PL/SQL-ben egy karakteres operátor létezik, mégpedig a konkatenáció. Operátora: ||

Példa:

'A'||'kutya az ember '||'leghűségesebb '||'barátja.'

Eredménye: 'A kutya az ember leghűségesebb barátja.'

Hasonlító operátorok

Hasonlító operátorok

Logikai operátorok

Logikai operátorok
A logikai operátorokat tartalmazó kifejezéseket a PL/SQL lusta módon értékeli ki. Azaz, csak addig értékeli ki a kifejezést, amíg értéke el nem dől.

Reguláris kifejezések

A PL/SQL 10-es verziójának egyik legjelentősebb újítása, hogy a reguláris kifejezések használatának támogatása. A REGEXP_INSTR, REGEXP_REPLACE, és REGEXP_SUBSTR beépített függvények a string kezeléshez nyújtanak segítséget, míg a REGEXP_LIKE SQL operátor, a reguláris kifejezések mintakeresésben való felhasználását segíti. A következő táblázat összefoglalja az Oracle által használt jelöléseket.

Reguláris kifejezések

A reguláris kifejezések az Oracle 10g újításaként kerültek be a rendszerbe. Alapvetően négy funkciót implementáltak. Ezek:

REGEXP_LIKE: Karakterlánc és minta összehasonlítására alkalmas. Működése hasonló a LIKE feltételéhez, viszont azzal ellentétben nem csak egyszerű mintákat, hanem bonyolultabb reguláris kifejezéseket is megadhatunk.

Regexp_like(karakterlánc, minta, találati paraméterek)

regexp like leiras
REGEXP_SUBSTR: A SUBSTR műveletet egészíti ki reguláris kifejezésekkel. A pozíció helyett, magával a rész-karakterlánccal tér vissza. Hasznos, ha szövegtartalmú mezőben kutatunk valami után, aminek a pozíciója nem, de maga a részszöveg érdekel minket.
Regexp_substr(karakterlánc, minta, kezdő pozíció, keresett előfordulás, találati paraméterek)

regexp_substr leiras
REGEXP_INSTR: Hasonló a regexp_substr függvényhez. Az INSTR metódust látja el reguláris kifejezések megadásának lehetőségével. A különbség a regexp_substr-hez képest egyedül annyi, hogy a regexp_instr nem a talált karakterlánccal, hanem annak kezdőpozíciójával tér vissza, egy integerrel.
Regexp_instr(karakterlánc, minta, kezdő pozíció, keresett előfordulás, visszatérési opció, találati paraméterek)

regexp_instr leiras
REGEXP_REPLACE: Analóg módon a többi függvénnyel, a nevéből adódóan ő a replace függvényt segíti reguláris kifejezésekkel. Egy string-ben kereshetünk reguláris mintát és cserélhetjük ki, amire szeretnénk. A függvény minden behelyettesített karakterláncot visszaad.
Regexp_replace(karakterlánc, minta, helyettesítő szöveg, induló pozíció, keresett előfordulás, találati paraméterek)

regexp_replace leiras

Operátor

Leírás

\ a

A backslash karakternek négy különböző jelentése lehet:

·         Önmagát jelenti

A következő karakterre vonatkozik

·         Egy operátort vezet be

·         Nincs szerepe

*

Nulla vagy több előfordulás

+

Egy vagy több előfordulás

?

Nulla vagy egy előfordulás

|

Választás operator alternatív minták megadásához

^ b

Illeszkedés a minta elején

$ b

Illeszkedés a minta végén

. c

Bármilyen karaketer a támogatott karakterkészletből, kivéve a NULL

[ ] d

A zárójelek között felsorolt kifejezések bármelyikére való illeszkedés. A ^ karakternek speciális jelentése van, a nem illeszkedést jelenti.

( )

Csoportképző operátor, amelyben szereplő kifejezésre később \n alakban hivatkozhatunk, ahol n a teljes reguláris kifejezésben részkifejezés sorszáma.

{m}

Pontosan m-szeres ismétlődés.

{m,}

Legalább m-szeres ismétlődés.

{m,n}

Legalább m, de legfeljebb n-szeres ismétlődés.

\ne

Hivatkozás az n-edik ’(’ ’)’ zárójelek közé zárt kifejezésre Az n 1 és 9 között lehet.

[..] f

Karakterek egy csoportja vagy egy több karakterből álló szimbólum pl.: ’ny’, ’ly’

[: :] g

Karakterosztály megadása (pl.: [:alpha]). A karakterosztályon belül bármely karakterre illeszkedik

[==] h

Ekvivalens osztályok meghatározása.

Karakterosztályok

Karakterosztály

Jelentés

[:alnum:]

Minden alfanumerikus karakter

[:alpha:]

Minden betű karakter

[:blank:]

Minden fehérelválasztó.

[:cntrl:]

Minden kontroll karakter (nem nyomtatható)

[:digit:]

Minden numerikus szám

[:graph:]

[:punct:],[:upper:],[:lower:], és [:digit:] karakterek.

[:lower:]

Minden kisbetű.

[:print:]

Nyomtatható karakterek.

[:punct:]

Írásjelek.

[:space:]

Minden helyköz karakter (nem nyomtatható).

[:upper:]

Minden nagybetű.

[:xdigit:]

Minden érvényes 16-os számrendszerbeli szám.

Szekvencia

Az egymás után végrehajtandó utasítások sorozatát pontosvesszővel kell elválasztani.

Blokkutasítások

A PL/SQL blokk a következő utasításokat tartalmazhatja:

:=

értékadás

CLOSE

kurzor lezárása (SQL utasítás)

COMMIT

tranzakció sikeres lezárása (SQL utasítás)

DELETE

adatok törlése az adatbázisban (SQL utasítás)

EXIT

kilépés a ciklusból

FETCH

rekord beolvasás a kurzorból (SQL utasítás)

GOTO

ugrás a megadott címkére

IF

feltételes elágazás

INSERT

adatok beszúrása az adatbázisba (SQL utasítás)

LOCK TABLE

táblák zárolása(SQL utasítás)

LOOP

ciklus szervező utasítás

NULL

üres utasítás

OPEN

kurzor nyitása (SQL utasítás)

RAISE

hibajelenség kiváltása

ROLLBACK

tranzakció visszagörgetése(SQL utasítás)

SAVEPOINT

tranzakció mentési pont(SQL utasítás)

SELECT..INTO

lekérdezés az adatbázisból(SQL utasítás)

SET TRANSACTION

tranzakció paraméterzés(SQL utasítás)

UPDATE

adatok módosítása az adatbázisban(SQL utasítás)

Az egyes műveletek végrehajtását számtalan segédfüggvény segíti, melyekkel többek között numerikus, karakterkezelési, dátumkezelési és konverziós műveletek végezhetők. Az utasítások felsorolásából is látszik, hogy a PL/SQL a külvilág felé zárt, csak az adatbázisban tárolt adatokhoz fér hozzá. Adatértékeket, mint például a változók tartalmát nem lehet vele a képernyőre, normál állományba kiírni, vagy a képernyőről, normál állományból beolvasni. A SELECT eredményeit a blokk változóiban kell felfogni. Természetesen ezen értékek nem vesznek el örökre előlünk, a kapcsolatot a PL/SQL blokk és a külvilág között a kapcsolódó segédprogramok, mint például a SQLForms vagy az SQLPlus biztosítja.

Elágazás

Elágazást az IF-THEN-ELSE szerkezetekkel tudunk megvalósítani. Három formája van: IF-THEN, IF-THEN-ELSE, IF-THEN-ELSIF.

IF-THEN
IF feltétel THEN utasítások; END IF;

A feltétel teljesülése esetén a törzsben szereplő utasítások végrehajtódnak.

IF-THEN-ELSE
IF feltétel THEN utasítások1; ELSE utasítások2; END IF;

Ha a feltétel hamis, akkor az ELSE ág hajtódik végre.

IF-THEN-ELSEIF
IF feltétel1 THEN utasítások1; ELSIF feltétel2 THEN utasítások2; ELSE utasítások3; END IF;

Ha feltétel1 hamis, akkor feltetel2 is kiértékelődik és ennek megfelelően hajtódnak végre az utasítások2 vagy az utasítások3.

Példa:

IF l_ertek = 1 THEN value := 1; ELSE IF l_ertek = 2 THEN value := 2; ELSIF l_ertek = 3 THEN value := 3; END IF; END IF;

A feltétel részben a hagyományos operátorok, relációk mellett alkalmazhatók az SQL-ben megismert speciális operátorok is, mint az
IS [NOT] NULL üres érték ellenőrzése
[NOT] LIKE szövegkeresés minta alapján
[NOT] BETWEEN értéktartományba esés
[NOT] IN halmazban való előfordulás operátorok.

A CASE utasítás

A PL/SQL 9-es verziójától kezdve használhatjuk a CASE utasítást, hogy több ágú elágazást írjunk. Két lehetőség közül választhatunk. Vagy a

CASE szelektor WHEN kifejezés1 THEN utasítás1 WHEN kifejezés2 THEN utasítás2 WHEN kifejezésN THEN utasításN [ELSE utasításN+1] END CASE;

formát választjuk, vagy a

CASE WHEN logikai_kifejezés1 THEN utasítás1 WHEN logikai_kifejezés2 THEN utasítás2 WHEN logikai_kifejezésN THEN utasításN ELSE utasításN+1] END CASE;

alakot.

Az első esetben a when ágak kifejezései szekvenciális sorrendben összehasonlításra kerülnek a szelektorral. Az első olyan ág fog végrehajtódni, ahol a két érték megegyezik.
A második esetben a when ágak feltételei szintén szekvenciális sorrendben értékelődnek ki és azon utasítás fog végrehajtódni, amelyhez tartozó feltétel teljesül (vagyis „igaz” értékkel értékelődik ki).
Az utasítás lehet blokkutasítás is, így az egyes ágakhoz bonyolultabb utasítássorozat is hozzárendelhető.
Ha a kiértékelés után egyetlen when ág sem hajtódik végre, akkor az else ág hajtódik végre. Amennyiben létezik.
Ha nincs else ág, akkor a végrehajtás az elágazást követő első utasítással folytatódik.
Ez utóbbi történik abban az estben is, ha a szelektor értéke NULL.

Ciklus

Három fajta ciklust találhatunk: LOOP, WHILE-LOOP, FOR-LOOP

LOOP

LOOP utasitasok; END LOOP;

Végtelen ciklus, az utasítások egymás után hajtódnak végre. Ha meg akarjuk szakítani a ciklus futását, akkor azt az EXIT vagy EXIT-WHEN szerkezetekkel tehetjük meg. Az EXIT azonnal kilép a ciklusból, az EXIT-WHEN pedig egy feltétel teljesüléséhez köti a kilépést.

Példa:

eredmeny := szam; LOOP EXIT WHEN i > 10; eredmeny := szam * eredmeny; i := i + 1; END LOOP;

WHILE-LOOP

WHILE feltétel LOOP utasítások; END LOOP;

Mindaddig, amíg a feltétel teljesül, a ciklus törzsében szereplő utasítások sorozatosan végrehajtódnak.

Példa:

eredmeny := szam; WHILE i <= 10 LOOP eredmeny := szam * eredmeny; i := i + 1; END LOOP;

FOR-LOOP

FOR számláló IN [REVERSE] alsó_korlát..felső_korlát LOOP utasítások; END LOOP;

A ciklus mindaddig végrehajtódik, míg a számláló az alsó- és felső korlát között található. Minden egyes végrehajtás után a számláló eggyel növekszik (vagy csökken, ha a REVERSE meg van adva). A ciklusban megadott indexváltozót nem szükséges külön deklarálni a deklarációs részben, mivel a rendszer automatikusan létrehozza NUMBER típusúként. A ciklus fejrészében megadott index csak a cikluson belül látható és úgy kezelhető, mint egy konstans: használhatjuk az aktuális értékét, de közvetlenül nem változtathatjuk meg.

Példa:

eredmeny := szam; FOR i IN 1..10 LOOP eredmeny := szam * eredmeny; END LOOP;

A for ciklust kurzorokkal összevonva is használhatjuk, így végig tudunk iterálni a kurzor által ismert rekordokon. Az alábbi kódban látható egy egyszerű példa, amely végig megy a rekordokon és kiírja azok azonosítóját.

DECLARE cursor c1 is SELECT azonosito from dolgozo; r1 c1%ROWTYPE; BEGIN FOR r1 IN c1 LOOP DBMS_OUTPUT.PUT_LINE('Azonosito:' || r1.azonosito); END LOOP; END;

Vezérlésátadó utasítások

Ugró utasítás – GOTO; címke
A nagyobb méretű, kevésbé szabályos vezérlésátadások megvalósítására rendelkezésre áll a GOTO utasítás, melynek formátuma:

GOTO cimke;

A cimkét a blokkban, a műveleti részben helyezhetjük el. A cimke azonosítót nem kell előzőleg definiálni. A címke kijelölésének alakja:

<>

A címke használatára, a vezérlésátadásra viszonylag több megkötés is vonatkozik. Elsőként meg kell említeni, hogy címke csak végrehajtható utasítások előtt állhat, tehát nem szerepelhet END IF, END LOOP, END kulcsszavak előtt. E megkötés szerencsére igen könnyen kikerülhető, ha a kívánt helyre beszúrunk egy üres utasítást (NULL utasítást), amely formailag végrehajtató utasítás, habár semmi nem történik eredményeképpen.
Így például az alábbi programrészlet szintaktikailag helytelen, mivel a cimke END LOOP előtt áll:

FOR x IN 1..33 LOOP ... IF y > 20 THEN GOTO ujra; END IF; ... <> END LOOP;

A kijavított változatban az END LOOP elé egy üres utasítást teszünk:

FOR x IN 1..33 LOOP ... IF y > 20 THEN GOTO ujra; END IF; ... <> NULL; END LOOP;

További megkötés, hogy a GOTO paranccsal nem ugorhatunk tetszőleges cimkére, csak olyanra, amely az adott utasításcsoportban, vagy az őt tartalmazó külső utasításcsoportok valamelyikében helyezkedik el. Utasításcsoport alatt nemcsak PL/SQL blokkokat, hanem egy vezérlési utasítással (IF, LOOP) összekötött utasításokat értünk. Igy például az alábbi blokkban helytelen a vezérlésátadás művelete:

... GOTO belul; IF x IS NULL THEN y := -1; <> x := x +1; END IF ...

A hiba oka, hogy egy tartalmazott utasításcsoportba kell belépni, amit nem enged meg a PL/SQL. Ha egymással felcseréljük az ugrás és a címke pozícióját, akkor viszont helyes elrendezést kapunk, mivel az ugrás a külső, a GOTO utasítást tartalmazó csoportba történik. Az alábbi példa egy helyes blokkrészletet mutat.

<> NULL; IF x IS NULL THEN y := -1; GOTO belul; x := x +1; END IF

A hibakezelő részben is szerepelhet GOTO utasítás és címke is. Azonban itt olyan megkötés áll fenn, hogy kintről, a műveleti részből nem lehet beugrani a hibakezelő részbe, s a hibakezelő részből sem átlépni a saját PL/SQL blokk műveleti részébe.
A címkék nemcsak végrehajtható utasítások előtt állhatnak, hanem blokkok előtt is, azaz a bevezető DECLARE vagy BEGIN kulcsszavak előtt. E címkék szerepe elsősorban nem a vezérlés átadó ugrásoknál van, hanem a változók elérésénél. Mint már korábban említettük, egy adott blokkban deklarált változó elrejti a külső blokkban ugyanolyan néven létrehozott változókat. A címke használatával lehetőség van azonban arra, hogy blokkra explicite hivatkozzunk, így közvetlenül hivatkozhatunk a benne létrehozott változókra is a

blokk_cimke.változó

formátumban. Erre mutat egy példát a következő kódrészlet:

<> DECLARE datum DATE; BEGIN ... <> DECLARE datum DATE; BEGIN ... IF datum = kulso_blokk.datum THEN .... END IF; END belso_blokk; .... END kulso_blokk;
A példában a saját és a külső blokkban deklarált ugyanolyan azonosítóval rendelkező változókat hasonlítjuk össze. Mint a példa is mutatja, ha a blokk előtt cimkét adunk meg a blokk azonosítására, akkor a blokk végén is szerepeltetni kell ugyanazt a címkét.