9.GYAKORLAT (ADATBÁZISOK)
A 9.-10.-11.gyakorlatok témaköre: SQL/PSM (adatbázisban tárolt
eljárások)
a gyakorlatban: Oracle PL/SQL,
ami az Oracle által az SQL
kiterjesztéseként
kifejlesztett procedurális
programozási
nyelv. Az Oracle PL/SQL gyakorlatokon
feltételezzük, hogy
rendelkezik az alábbi alapvető informatikai
alapismeretekkel:
- az előző 1.-8.gyakorlatok anyaga, az
SQL
szabvány és az Oracle SQL
ismerete,
- a különböző
programozási
nyelvek alapeszközeinek fogalmi szintű ismerete,
- és programozási gyakorlat
valamely
magasszintű
programozási nyelven.
Témakör: Oracle PL/SQL
1.rész: programegységek,
vezérlési szerkezetek
Az első PL/SQL gyakorlaton az
ún. "Eljut"-feladatra, gráfok lekérdezésre
írunk
PL/SQL programot. Ehhez az
alábbi PL/SQL alapokra lesz
szükségünk:
-
Változóhasználat,
Vezérlési
szerkezetek: feltételes utasítások,
ciklusok,
- DML
utasítások (insert, delete, update, merge)
használata programban,
- egy sort
visszaadó SELECT INTO használata
programban.
Megj.: A több sort
visszaadó
SELECT-re és a
kurzorok használata
köv.órán,
a PL/SQL
haladó
témaköreit
pedig majd két hét múlva tanuljuk,
lépésenként.
-
Oracle PL/SQL doksi: Oracle
Database 12.2 - PL/SQL
Language Reference
(Ez az egyetlen megengedett
segédlet, amit a ZH írás alatt
használhatunk)
>> a
doksiból nézünk példákat:
List
of Examples (PL/SQL Lang.Ref.12.2)
>> 9.gyakorlaton az 1-5.fejezet
lényegi
részét és a
példáit dolgozzuk fel,
főként
a 2.fejezet PL/SQL alapjait és a 4.fejezet vezérő
utasításokat.
- További
segédanyagok a PL/SQL
feldolgozásához:
>> PL/SQL-I.rész (alapok az Eljut-feladathoz) 08.ab1ea.pdf (AB1ea/HajasCs.)
>> PL/SQL-II.rész
(kurzorok, alprogramok) 09.ab1ea.pdf
(AB1ea/HajasCs.)
>> Oracle
PL/SQL Oracle
Junior Program korábbi ea
>> Oracle
PL/SQL.pdf
>> További anyagok eduPLSQL
mappában >>
Tankönyvtár: plsql_progr.pdf
1.rész:
Oracle PL/SQL programegységek,
vezérlési szerkezetek
1.1. PROGRAMEGYSÉGEK:
BLOKK, [TÁROLT] ALPROGRAMOK
- blokk, alprogram (eljárás,
függvény)
- tárolt eljárás,
tárolt
függvény
- csomagok
-- -- -- -- -- --
-- PL/SQL blokk felépítése
[<< label >> -- (címke,
opcionális) ]
[DECLARE --
(BLOKK-1 Deklarációs rész,
opcionális)
-- változók, alprogramok
deklarálása ]
BEGIN --
(BLOKK-2 Végrehajtható rész,
kötelező)
-- végrehajtható
utasítások, például van
NULL;
[EXCEPTION -- (BLOKK-3 Kivételkezelő rész,
opcionális
-- hiba- és kivételkezelés
(lásd később 11.gyak) ]
END;
/
-- Blokk típusok
a.) Névtelen blokk:
[DECLARE]
BEGIN
-- végrehajtható
utasítások;
[EXCEPTION]
END;
/
/* Első példa: PL/SQL blokkra, BEGIN ..
END nem maradhat üresen,
ezért a
végrehajtható
utasítások között van egy
olyan,
hogy NULL,
aminek a programok
fejlesztése-tesztelése során
hasznát vesszük.
*/
BEGIN
NULL;
END;
/
b.) Procedure/Eljárás
specifikáció:
[CREATE OR REPLACE]
PROCEDURE név
[(formális_paraméter[, formális
paraméter] ...)]
IS
BEGIN
-- végrehajtható
utasítások;
[EXCEPTION]
END;
/* A formális paraméter neve után
a paraméterátadás
módját lehet megadni:
IN esetén érték
szerinti,
OUT esetén eredmény
szerinti,
IN OUT esetén
érték-eredmény szerinti a
paraméterátadás.
Ha nem adjuk meg, akkor az IN
alapértelmezett.
*/
c.) Function/Függvény
specifikáció:
[CREATE OR REPLACE]
FUNCTION név
[(formális_paraméter[, formális
paraméter] ...)]
RETURN adattípus
IS
BEGIN
-- végrehajtható
utasítások;
RETURN érték;
[EXCEPTION]
END;
/
/* Ahhoz, hogy egy függvényt SQL
utasításban is
használhassunk,
néhány
megszorításnak még eleget
kell tennie, mint például
tárolt fv legyen, csak IN módú
paraméterei legyenek, stb,
lásd később 11.gyak.pl-proc-fv.txt
*/
Folyt.köv. ALPROGRAMOK később 11.gyak: Oracle
Példatár 10.fej.PSM.pdf
PL/SQL eljárások
és
függvények: 8.fej.
PL/SQL Alprogramok folyt.11.gyak:
>> 8.1.
Alprogramokról áttekintés:
Miért van szükség alprogramokra,
előnyök
-- Példák
procedurákra/függvényekre: pl-proc-fv.txt
további példák később...
>> példa2-17
Változók hatásköre,
láthatósága, élettartalma
(2.fej. Alapok)
>> példa4-1
Megnézzük az IF-THEN
utasításnál az
eljárást (4.fej.
Utasítások)
>> 8.5.fej.
Példák példa8-1
PL/SQL eljárásra és példa8-2
PL/SQL függvényre
>>
8.7.fej. Paraméterátadás; 8.9.fej.Túlterhelés
példa8-26
túlterhelésre példa
1.2. PROGRAMOK TESZTELÉSE,
ELJÁRÁSHÍVÁS,
FÜGGVÉNYHÍVÁS
a.) ELJÁRÁSHÍVÁS:
I/O: DBMS_OUTPUT
CSOMAG PUT_LINE
ELJÁRÁS HASZNÁLATA
- Input/Output PL/SQL-ben nincs I/O
utasítás, általában a be-
és kimenet (I/O)
SQL utasításokkal
történik, az
adatokat az adatbázis tábláiban
tároljuk,
és
ott módosítjuk vagy onnan
lekérdezzük ezeket a
táblákat.
- Minden más PL/SQL I/O pl. képernyőre
való
kíiírás az Oracle Database
által
biztosított PL/SQL csomagokkal
történik.
- DBMS_OUTPUT csomag link: DBMS_OUTPUT.html (PL/SQL
Packages)
DBMS_OUTPUT.PUT_LINE (item IN VARCHAR2)
eljárásra példa:
-- Tesztelés:
SET SERVEROUTPUT ON
BEGIN
DBMS_OUTPUT.PUT_LINE ('Szia Világ!');
END;
/
- PL/SQL feladat: Írjuk át a
fenti programot: Szia ....! (nevet bekérni) ehhez:
- Ismétlés: Felhasználói
változó,
Példatár 4.fej.pdf
(Interaktív környezet)
>> innen
felhasználói
(helyettesítő változók
használata SQL
utasításokban
volt 7.gyak.
INSERT 2.feladatát, de most
bekérjük az új sorhoz az
értékeket,
&dkod
(numerikus), '&dnev'
(karaktersorozat) típusú helyettesítő
változókba.
b.) FÜGGVÉNYHÍVÁS:
DBMS_RANDOM CSOMAG VALUE
FÜGGVÉNY HASZNÁLATA
- DBMS_RANDOM csomag link: DBMS_RANDOM.html (PL/SQL
Packages)
DBMS_RANDOM.VALUE(AlsóHatár,
FelsőHatár) függvény
használata.
-- Tesztelés:
SELECT ROUND(DBMS_RANDOM.VALUE(0, 10000), -2) from dual;
- Ismétlés: Ez is volt SQL DDL
feladatban,
olyan nézettáblát
készítsünk
a dolgozo
tábla (dkod, dnev,
fizetes, jutalek) oszlopaihoz vegyünk fel
egy új nyeremény
nevű oszlopot, amit úgy töltsünk fel
adatokkal, hogy
0
és 10000
közötti véletlen egész
számot százasokra kerekítve adjunk
hozzá a jutalékhoz, ha a
jutalék ismeretlen, akkor tekintsük 0
értéknek.
1.3. DEKLARÁCIÓS
RÉSZ-1:
VÁLTOZÓK DEKLARÁLÁSA
VÉGREHAJTHATÓ RÉSZ-1:
ÉRTÉKADÁS, SELECT INTO
PL/SQL
alapok, PL/SQL
blokk >> 2.fej.
PL/SQL alapok -> 2.6.rész
[1_deklarációs_rész] 2_végrehajtható_rész [3_kivételkezelő_rész]
SET SERVEROUTPUT ON;
>> példa-2-24
deklarációk-és-értékadás,
típusok, %TYPE, %ROWTYPE
-- Az itt szereplő
példák
kipróbálásához hozzunk
létre
szinonimákat:
create or replace synonym
departments for hr.departments;
create or replace synonym
employees for hr.employees;
--
Egészítsük ki:
például legyen DATE típusú
változó is,
illetve
nézzünk
%TYPE és
%ROWTYPE használatára további
példákat!
[ opcionális,
részletek: 3.fej. PL/SQL adattípusok,
5.fej. Kollekciók ]
>> példa-2-25
Értékadás
változónak a SELECT INTO
utasítással
/* Itt
a 2-25
példa futtatásához át kell
tenni az end;-et
a legvégére!
Ez a
példa
abból a szempontból is tanulságos,
hogy
önállóságra
biztassa a
halllgatókat, hogy írják át
a
példát, emloyees -> dolgozo
táblára
salary -> fizetes, employee_id -> dkod vagy helyette
dnev.
Kérem a
hallgatókat, hogy ha az
önálló
gyakorlás során találnak
az
Oracle PL/SQL Lang.Ref.
doksiban érdekes példákat,
írják
meg!
*/
>> SELECT
INTO-t akkor használjuk, ha a
lekérdezés pontosan egy sort
ad! Ha a
lekérdezés
nem ad vissza sort vagy több sorral tér
vissza,
akkor kurzort kell
használni, ez lesz a köv.10.gyakorlat
tananyaga,
illetve a
11.gyakorlaton a
hiba- és kivételkezelésnél
is visszatérünk!
Kieg.Példatárból: KÜLSŐ ÉS BELSŐ
VÁLTOZÓK HASZNÁLATA
>> Változóhasználat,
vezérlési szerkezetek: Oracle
Példatár 8.fej.pdf
innen egy
példa: 1a_valtozok_pelda_Oracle_Peldatar_8fej.txt
1.4. VÉGREHAJTHATÓ RÉSZ-2:
VEZÉRLŐ UTASÍTÁSOK
VEZÉRLŐ UTASÍTÁSOK >> 4.fej.
PL/SQL vezérlő utasítások
Feltételes
utasítások:
>> példa-4-4 if-then-elsif
utasítás
!!! Ebben a
példában
figyeljük meg a deklarációs
részben az
eljárást,
írjuk
át az itt szereplő eljárást CREATE OR
REPLACE PROCEDURE-re!
>> példa-4-6
egyszerű case utasítás, és itt
írjuk át grade
:= 'B' ->
'&B'
írjuk át
helyettesítési
változóra: a
felhasználó adja meg az
értékét!
Ciklusok:
>> példa-4-10
alap LOOP ciklus utasítás EXIT WHEN
kilépés a ciklusból
>> példa-4-15
FOR ciklus utasítás
>> példa-4-28
WHILE ciklus utasítás
SQL UTASÍTÁSOK A PROGRAMBAN >> 6.fej.elején (folyt.később 10.gyak)
>> példa6-1
DML utasítások a programban (Eljut feladathoz
csak INSERT)
FOLYT.KÖV. 10.gyak: DML
utasítások, implicit kurzor,
kurzorattribútumok (később)
AZ ELSŐ NAGYOBB PL/SQL FELADAT:
Az "Eljut-feladat" PL/SQL-ben
SQL
WITH RECURSIVE utasítást,
az Eljut
feladatot lásd a 08.gyakorlaton
Adott Járatok tábla
alapján programmal INSERT INTO Eljut (SFW);
Rekurzió: SQL-1999
szabvány
WITH RECURSIVE utasítása helyett itt programmal
> Eljut feladat, gráf
adatszerkezet
lekérdezésére írjunk
programot PL/SQL-ben!
> Ullman-Widom tankönyv
10.2 szakasza 08.ab1ea.pdf (korábbi AB1ea/HajasCs.)
Az Eljut-feladat a
Tankönyv
(Ullman-Widom kék
könyv) 10.2 szakaszára épül:
> Adott Jaratok(legitarsasag,
honnan, hova, koltseg, indulas, erkezes) táblában
repülőjáratok
adatait
tároljuk (honnan-hova várospárok). Azt
keressük, hogy
Dallasból
mely városokba tudunk eljutni
(közvetlenül vagy
egy/több átszállással).
-- Ezzel a
scripttel jaratok_tabla.txt
készítsük el a
repülőgépjáratokról a
táblát.
> Rek1.feladat: Mely
(x, y)
várospárokra lehetséges
egy vagy több átszállással
eljutni x
városból y városba? -- Ehhez
készítsünk egy Eljut(honnan,
hova)
táblát,
a sorait a járatok
tábla alapján PL/SQL programmal
töltsük fel (ciklust szervezni,
az insert 2.alakja:
több sor felvitele
alkérdéssel/járatok és
eljut táblák alapján).
>>> (csak ha
kell, egy kis
segítség, további ötletek
és a
megoldás vázlata: itt)
> Rek2.feladat: Mely
(x,y)
város
párokra hány
átszállással és
milyen költségekkel
lehetséges egy
vagy több
átszállással eljutni x
városból y városba? -- Ehhez
is
készítsünk Eljut2(honnan,
hova,
atszallas, koltseg) táblát, a sorait
programmal.
>> Papíron
megoldandó feladat: Fejezzük
ki az SQL-1999-es szabvány SELECT
WITH RECURSIVE
utasítással, hogy mely mely
városokba (hova) tudunk eljutni
'DAL'
(Dallas)-ból legfeljebb 3
átszállással és
legfeljebb 5000
költségből.
>>> (csak ha kell, egy kis
segítség WITH RECURSIVE
papíros részéhez itt)
> Rek3.feladat: Tegyük
fel, hogy nemcsak
az
érdekel, hogy el tudunk-e jutni az
egyik
városból a másikba, hanem az
is, hogy
utazásunk
során az átszállások is
ésszerűek legyenek, ez azt
jelenti, hogy
ha több
járattal utazunk, akkor nézni
kell
átszálláskor az
érkező
járatnak legalább
egy órával a
rákövetkező indulás
előtt meg
kell
érkeznie. (Tegyük fel, hogy nincs
egy
napnál hosszabb utazás!)
> Rek4.feladat: Ne
csak a
várospárokat, hanem a teljes
útvonalat is
listázzuk ki.
GYAKORLÓ PL/SQL
FELADATSOR --1
--
A
DBMS_OUTPUT.PUT_LINE() képernyőre való
kiíráshoz állítsuk
be:
SET SERVEROUTPUT ON
-- -- -- --
-- 1.)
/* Az első
feladat képernyőre
kiírás: Írjuk ki PL/SQL
blokkból: 'Szia Világ!'
*/
-- -- -- --
-- 2.)
/* Írjuk ki KING
fizetését és
jutalékát
(olvasás táblából
változókba), ha
ismert,
hogy pontosan egy
KING nevű dolgozó szerepel a
táblában (SELECT INTO).
SELECT INTO csak
akkor működik, ha a
lekérdezés pontosan egy sort
ad,
erre a feladatra
visszatérünk a 11.gyakorlaton a
hiba- és kivételkezelésnél.
*/
-- -- -- --
-- 3.)
/* Írjunk meg egy függvényt, amelyik
eldönti
egy számról, hogy prím-e.
igen/nem
-> 1/0 értékeket adja vissza a
függvény
*/
CREATE OR REPLACE FUNCTION prim(n integer) RETURN number IS
-- Tesztelés:
SELECT prim(101) from dual;
SELECT prim(108) from dual;
SELECT prim(26388279066623) from dual;
-- -- -- --
-- 4.)
/* Írjunk meg egy procedúrát, amelyik
kiírja az n-edik Fibonacchi számot
fib_1 = 0, fib_2 = 1, fib_3 = 1, fib_4
= 2, . . .
fib_i = a megelőző kettő
összege
*/
CREATE OR REPLACE PROCEDURE fib(n integer) IS
-- Tesztelés:
SET SERVEROUTPUT ON
BEGIN
fib(10);
END;
/
-- vagy lehet így is
set serveroutput on
execute fib(10);
-- -- -- --
-- 5.)
/* Írjunk meg egy függvényt, amelyik
visszaadja
két szám legnagyobb közös
osztóját
*/
CREATE OR REPLACE FUNCTION lnko(p1 integer, p2 integer) RETURN number IS
-- Tesztelés:
SELECT lnko(3570,7293) FROM dual;
-- -- -- --
-- 6.)
/* Írjunk meg egy függvényt, amelyik
visszaadja n faktoriálisát
*/
CREATE OR REPLACE FUNCTION faktor(n integer) RETURN integer IS
-- Tesztelés:
SELECT faktor(10) FROM dual;
-- -- -- --
-- 7.)
/* Írjunk meg egy függvényt, amelyik
megadja, hogy hányszor fordul elő
egy karakterláncban
-> p1 egy
másik részkarakterlánc -> p2
*/
CREATE OR REPLACE FUNCTION hanyszor(p1 VARCHAR2, p2 VARCHAR2) RETURN
integer IS
-- Tesztelés:
SELECT hanyszor ('ab c ab ab de ab fg', 'ab') FROM dual;
-- -- -- --
-- 8.)
/* Írjunk meg egy függvényt, amelyik
visszaadja a paraméterként szereplő '+'-szal
elválasztott számok
összegét.
*/
CREATE OR REPLACE FUNCTION osszeg(p_char VARCHAR2) RETURN number IS
-- Tesztelés:
SELECT osszeg('1 + 4 + 13 + -1 + 0') FROM dual;
Ţovábbi
gyakorló
PL/SQL feladatok
Fejezze be önállóan
a fenti
feladatokból a hiányzó feladatokat,
és gyakoroljon
oldja meg önállóan
az Oracle
Példatár Feladatok.pdf
8.fejezet 8.1-8.9.feladatait!
[Megjegyzés: Az Oracle
Példatár ezeket a táblákat
használja: cr_dept_emp.txt
az emp és dept
táblák helyett használjuk itt is a dolgozo,
osztaly tábláinkat!]