SVEUČILIŠTE U ZAGREBU FAKULTET ORGANIZACIJE I INFORMATIKE V A R A Ž D I N Anđelko Spevec Oracle PL/SQL DIPLOMSKI RAD Varaždin, 2014.
SVEUILITE U ZAGREBU
FAKULTET ORGANIZACIJE I INFORMATIKE
V A R A D I N
Anelko Spevec
Oracle PL/SQL
DIPLOMSKI RAD
Varadin, 2014.
SVEUILITE U ZAGREBU
FAKULTET ORGANIZACIJE I INFORMATIKE
V A R A D I N
Anelko Spevec
Matini broj: 41753/12-R
Studij: Baze podataka i baze znanja
Oracle PL/SQL
DIPLOMSKI RAD
Mentor:
Doc.dr.sc. Markus Schatten
Varadin, lipanj 2014.
I
Sadraj
1. Uvod ...................................................................................................................................... 1
2. Uvod u PL/SQL ..................................................................................................................... 2
2.1. PL/SQL blok ................................................................................................................... 3
2.1.1. Deklarativni dio ....................................................................................................... 4
2.1.2. Izvrni dio ................................................................................................................ 4
2.1.3. Dio za obradu iznimaka ........................................................................................... 5
2.2. Prednosti PL/SQL-a ........................................................................................................ 5
3. ERA model baze podataka .................................................................................................... 7
4. Varijable i konstante u PL/SQL-u ......................................................................................... 8
5. Tipovi podataka u PL/SQL-u .............................................................................................. 10
5.1. Skalarni tipovi podataka ............................................................................................... 10
5.1.1. Brojani tipovi podataka ....................................................................................... 11
5.1.2. Znakovni tipovi podataka ...................................................................................... 12
5.1.3. BOOLEAN tip podataka ....................................................................................... 13
5.1.4. Tipovi podataka za oznaavanje datuma, vremena i intervala .............................. 13
5.2. Usidreni tipovi podataka ............................................................................................... 16
6. Operatori .............................................................................................................................. 18
6.1. Aritmetiki operatori .................................................................................................... 18
6.2. Operatori usporedbe ..................................................................................................... 18
6.3. Logiki operatori .......................................................................................................... 19
7. Izrazi za kontrolu programskog toka PL/SQL-a .................................................................. 20
7.1. Selekcija ....................................................................................................................... 20
7.2. Iteracija ......................................................................................................................... 23
8. Kursori ................................................................................................................................. 26
8.1. Implicitni kursor ........................................................................................................... 26
8.2. Eksplicitni kursor .......................................................................................................... 27
8.2.1. Kursori s parametrima ........................................................................................... 29
8.2.2. Ugnjeeni kursori ................................................................................................ 30
8.2.3. UPDATE i DELETE redaka aktivnog seta kursora .............................................. 31
9. Kolekcije .............................................................................................................................. 33
9.1. Asocijativni niz ............................................................................................................. 33
9.2. Ugnjeene tablice ....................................................................................................... 34
9.3. Metode kolekcija .......................................................................................................... 35
9.4. Polja varijabilne duljine ................................................................................................ 36
II
9.5. Vieslojne kolekcije ...................................................................................................... 38
10. Zapis ............................................................................................................................. 39
11. Iznimke ......................................................................................................................... 41
11.1. Ugraene iznimke .................................................................................................. 42
11.2. Iznimke definirane od strane korisnika .................................................................. 43
11.3. Propagacija iznimaka ............................................................................................. 44
11.4. Ponovno dizanje iznimaka ..................................................................................... 45
11.5. PRAGMA EXCEPTION_INIT ............................................................................. 46
12. Potprogrami .................................................................................................................. 48
12.1. Procedure ............................................................................................................... 49
12.2. Vrste parametara u potprogramima........................................................................ 50
12.3. Vrste proslijeivanja .............................................................................................. 52
12.4. Funkcije .................................................................................................................. 53
13. Paketi ............................................................................................................................ 55
13.1. Specifikacija paketa ............................................................................................... 55
13.2. Tijelo paketa ........................................................................................................... 55
14. Okidai ......................................................................................................................... 58
14.1. Kreiranje okidaa ................................................................................................... 58
14.2. Promjena i brisanje okidaa .................................................................................. 61
14.3. Napomene za rad s okidaima ............................................................................... 61
15. Dinamiki SQL ............................................................................................................ 62
15.1. Nativni dinamiki SQL .......................................................................................... 62
15.2. DBMS_SQL paket ................................................................................................. 67
16. Objektno orijentirano programiranje u PL/SQL-u ....................................................... 69
16.1. Metode objektnog tipa ........................................................................................... 70
16.2. Usporedba objekata ................................................................................................ 73
16.3. Nasljeivanje PL/SQL objekata ............................................................................. 75
16.4. Apstraktni objekti u PL/SQL-u .............................................................................. 76
17. Usporedba PL/SQL-a s PL/pgSQL-om ........................................................................ 77
18. Usporedba PL/SQL-a s T-SQL-om .............................................................................. 79
19. Zakljuak ...................................................................................................................... 80
20. Literatura ...................................................................................................................... 81
1
1. Uvod
U dananje vrijeme kad gotovo svaka aplikacija koristi bazu podataka za pohranu svojih
podataka od velike je vanosti iskoristiti te podatke to bolje. Povezanost izmeu aplikacija i
baze podataka se moe obaviti koristei standardne SQL DML (eng. Data Manipulation
Language) naredbe, ali svaki od dohvata podataka iz baze zahtjeva prijenos putem mree,
pretvorbu podataka iz tipa podataka iz baze u tip podataka u programskom jeziku to oduzima
i vrijeme i resurse. Zato PL/SQL omoguava da se vie naredbi odradi unutar jednog bloka,
odnosno da se podatci i obrade koristei operatore, petlje i provjere kao u ostalim
programskim jezicima. Omoguava se i prihvat i obrada iznimaka unutar samog bloka to
olakava sam rad s podatcima. PL/SQL aplikacije su prenosive i neovisne o operacijskom
sustavu, te tako omoguavaju konzistentan rad na svim raunalima.
U ovo radu e se obraditi mogunosti PL/SQL jezika koji se koristi za Oracle baze podataka
te ih prikazati na primjerima. Nakon toga e se mogunosti PL/SQL-a usporediti s
mogunostima proceduralnog jezika za PostgreSQL bazu podataka (PL/pg SQL) te
proceduralnog jezika za Microsoft i Sybase bazu podataka (T-SQL).
2
2. Uvod u PL/SQL PL/SQL (eng. Procedural Language/Structured Query Language) je proirenje proceduralnog
jezika za SQL u Oracle bazama podataka. To je kombinacija SQL-a s proceduralnim
osobinama programskih jezika kao to su petlja, selekcija, iteracija, deklariranje varijabli,
strukture, upravljanje grekama itd. Moe koristiti sve SQL naredbe, funkcije, operatore i
tipove podataka koji su dostupni u SQL-u. 1
Jo jedna od prednosti PL/SQL-je da se moe grupirati vie SQL naredbi te ih poslati prema
bazi kao jedan upit te se tako ubrzava aplikacija i smanjuje mreni promet. Inae svaka SQL
naredba koja se izvrava putuje od klijenta do baze podataka na posluitelju, te nakon obrade
vraa rezultat korisniku. Za svaku naredbu je isti postupak, pa se kod vie naredbi poveava i
mreni promet jer svaki od njih uzrokuje dva prijenosa putem mree. Ako je vie takvih
naredbi unutar PL/SQL bloka oni se alju kao jedna cjelina te se rezultat itavog bloka
takoer vrati kao jedna cjelina. 2 Na slici 1 je prikazana komunikacija izmeu klijenta i
posluitelja.
Slika 1. Komunikacija izmeu klijenta i posluitelja za SQL i PL/SQL3
Razlika izmeu SQL-a i PL/SQL-a je i u nainu izvoenja. Za izvoenje PL/SQL bloka je
zaduen PL/SQL stroj koji izvrava PL/SQL izraze dok SQL naredbe alje na procesor
zaduen za obradu SQL izraza (eng. SQL statement processor). Ako se PL/SQL stroj nalazi
na posluitelju, obrada se ostvaruje kao to je prikazano na slici 2.
1Oracle (2009) - Oracle Database PL/SQL Language Reference 11g Release 1, Tight Integration with SQL, URL:
http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/overview.htm#CJAGBBAD, dostupno 14.06.2014. 2Rosenzweig B., Rakhimov E. (2009) Oracle PL/SQL by Example Fourth Edition, str. 2.
3 Rosenzweig B., Rakhimov E. (2009) Oracle PL/SQL by Example Fourth Edition, str. 4.
3
Slika 2. Obrada PL/SQL bloka4
Ako se PL/SQL stroj nalazi na klijentskoj strani tada obrada PL/SQL-a se ostvaruje na
klijentskoj strani dok se SQL naredbe koje se nalaze u bloku alju na server na daljnju obradu.
Uz to aplikacije pisane u PL/SQL-u su neovisne o operacijskom sustavu i platformi na kojoj
se nalazi baza.
PL/SQL kombinira mogunosti SQL-a za manipulaciju podataka te ih kombinira s
mogunostima obrade proceduralnih jezika. Tako omoguava deklaraciju varijabli i konstanti,
kao i kontrolu toka programa, potprograme i obradu iznimki. Pisanje potprograma omoguava
smanjivanje kompleksnosti programa podjelom u manje, vie razumljive potprograme koji se
kasnije mogu koristiti. 5
2.1. PL/SQL blok6
Najosnovnija struktura PL/SQL-a je blok, te je uobiajeno da jedan blok predstavlja jednu
logiku cjelinu koja se izvrava. PL/SQL blok se sastoji od tri dijela, a to su deklarativni dio,
izvrni dio i dio za obradu iznimaka. Svaki dio zapoinje svojom kljunom rijei, a blok
zavrava kljunom rijei END.
DECLARE
Izrazi za deklariranje varijabli
BEGIN
Izrazi za izvravanje
4 Rosenzweig B., Rakhimov E. (2009) Oracle PL/SQL by Example Fourth Edition, str. 3.
5 Oracle (2009) - Oracle Database PL/SQL Language Reference 11g Release 1, PL/SQL Blocks, URL:
http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/overview.htm#i8859, dostupno 14.06.2014. 6TutorialsPoint (2014) - PL/SQL Tutorial, PL/SQL - Basic Syntax, URL: http://www.tutorialspoint.com
/plsql/plsql_basic_syntax.htm, dostupno 14.06.2014.
4
EXCEPTION
Izrazi za obradu iznimaka
END;
2.1.1. Deklarativni dio
Prvi dio PL/SQL bloka je deklarativni dio, te se u njemu definiraju varijable, konstante,
kursori i slino. Sam dio zapoinje kljunom rijei DECLARE. Svaka varijabla ima naziv koji
se dodjeljuje memorijskom prostoru kao i tip podataka koji odreuje veliinu prostora i
operacije koje se mogu obavljaju nad tom varijablom.
DECLARE
ime_zaposlenika VARCHAR2(30);
broj_sati INTEGER:
cijena_po_satu CONSTANT DECIMAL(5,2) := 100.00;
2.1.2. Izvrni dio
Sljedei dio PL/SQL bloka je izvrni dio koji zapoinje kljunom rijei BEGIN, te on sadri
izvrne naredbe.
DECLARE
a INTEGER := 5;
b INTEGER := 4;
opseg INTEGER;
BEGIN
opseg := 2 * a + 2 * b;
DBMS_OUTPUT.PUT_LINE('Opseg je: ' || opseg);
END;
Opseg je: 18
No, u izvrnom bloku se inae izvravaju sloenije operacije, te emo njih opisivati i prolaziti
u sljedeim poglavljima. Kod ovog djela bloka je vano napomenuti da je to jedini obavezan
dio bloka, tako da mogu postojati blokovi samo sa izvrnim djelom. Izvrni dio se mora
sastojati od barem jedne naredbe, ali mogue je da ta naredba bude prazna, odnosno null.
BEGIN
null;
END;
U izvrnom djelu se jo mogu koristiti i SQL naredbe te vrijednosti rezultata zapisivati u
varijable deklarirane u deklarativnom djelu.
5
2.1.3. Dio za obradu iznimaka
Zadnji dio PL/SQL bloka je dio za obradu iznimaka te poinje kljunom rijei EXCEPTION.
Sadri naredbe koje se izvravaju u sluaju da doe do iznimke kod izvoenja u izvrnom
djelu bloka.
DECLARE
ime VARCHAR2(30);
BEGIN
SELECT ime_zap
INTO ime
FROM zaposlenik
WHERE id_zap = 11;
DBMS_OUTPUT.PUT_LINE('Ime zaposlenika: ' || ime);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Nema zaposlenika s tim identifikacijskim
brojem');
END;
Nema zaposlenika s tim identifikacijskim brojem
Ovaj PL/SQL blok izvrava SQL naredbu u izvrnom djelu te zapisuje rezultat te naredbe u
varijablu deklariranu u deklarativnom djelu bloka. U sluaju da SELECT INTO naredba ne
vrati niti jedan red, pokree se obrada iznimke NO_DATA_FOUND i ispisuje odgovarajuu
poruku.
PL/SQL blokovi se mogu ugnjeivati unutar drugih blokova, te se tako unutar bloka moe
deklarirati drugi blok bilo gdje unutar izvrnog dijela. Blokove dijelimo jo u dvije grupe, a to
su imenovani i anonimni. Imenovani blokovi kao to su procedure, funkcije, okidai i paketi
mogu biti spremljeni za kasnije koritenje. Oni se prevode u strojni kd kod kreiranja i kod
svake promjene, pa se kod pozivanja ne trebaju. Dok se anonimni blokovi prevode u strojni
kd prije izvravanja, te kasnije ne mogu biti pozvani.
2.2. Prednosti PL/SQL-a
Uz sve prednosti PL/SQL-a koje su navedene postoje jo7:
Uska povezanost s SQL-om
Provjera i obrada pogreaka
Veliki broj tipova podataka
Razne strukture podataka
7 TutorialsPoint (2014) - PL/SQL Tutorial, PL/SQL - Overview, URL:
http://www.tutorialspoint.com/plsql/plsql_overview.htm, dostupno 14.06.2014.
6
Omoguava funkcije i procedure
Podrava objektno orijentirano programiranje
Veliki broj predefiniranih SQL paketa
Visoka razina sigurnosti
Prijenosne aplikacije
7
3. ERA model baze podataka
Za potrebe ovog rada i zbog lakeg objanjavanja mogunosti PL/SQL-a, kreirana je Oracle
baza prema ERA modelu na slici 3. Baza je zamiljena kao mali servis laptopa, te se zapisuju
nalozi odnosno ureaji zaprimljeni na servis. Tablice u bazi su:
proizvodac podatci o proizvoau ureaja koji je zaprimljen na servis
kvar openita podjela kvarova ureaja (npr. pregrijavanje, grafika kartica i slino)
servis podatci o lokaciji servisa (grad, adresa)
zaposlenik podatci o zaposlenicima servisa te njihova pripadnost odreenoj
poslovnici
nalog podatci o zaprimljenom ureaju, kvaru, proizvoau, kontaktni podatci,
vrijeme zaprimanja, osoba koja je zaprimila ureaj, da li je ureaj pod garancijom,
cijena servisiranja i slino
Slika 3. ERA model baze podataka
Sama baza je kreirana na Oracle 11.1g sustavu za upravljanje bazama podataka te je za rad s
njom, odnosno pisanje PL/SQL koda koriten Oracle SQL Developer.
8
4. Varijable i konstante u PL/SQL-u8
Varijable i konstante se u PL/SQL-u deklariraju u deklarativnom dijelu bloka, a koriste se u
izvrnom dijelu. Tako se u deklarativnom dijelu mogu definirati varijable, konstante, kursori i
slino. Svaka varijabla ima naziv koji se dodjeljuje memorijskom prostoru kao i tip podataka
koji odreuje veliinu prostora i operacije koje se mogu obavljati nad tom varijablom. Naziv
varijable zapoinje slovom, te moe sadravati slova, brojeve, znakove ($,_,#) i mora biti
manje od 30 znakova. Tip podatka takoer mora biti valjani PL/SQL tip podatka. Osnovna
sintaksa za deklariranje varijable je sljedea:
naziv_varijable [CONSTANT] tip_podataka [NOT NULL] [:= | DEFAULT inicijalna];
Iz gore navedene sintakse se vidi da je za varijablu obavezno napisati njezin naziv i tip
podataka. Nakon naziva varijable se moe navesti je li varijabla konstanta, tako da se prije
tipa podataka napie kljuna rije CONSTANT. Ako se navede da je varijabla konstanta,
mora obavezno sadravati i inicijalnu vrijednost koja se kasnije u bloku ne moe mijenjati. Za
varijablu se moe definirati i da ne bude prazna odnosno da ne bude null koristei kljunu
rije NOT NULL nakon tipa podatka. Kada se upie ta kljuna rije, takoer mora postojati i
inicijalna vrijednost koja se moe mjenjati dalje unutar bloka. Za svaku varijablu inicijalno
vrijedi NULL, odnosno doputeno je da bude i prazna, odnosno null. Tako da se taj dio ne
deklarira kod postavljanja same varijable. Inicijalna vrijednost varijable se postavlja koristei
operator pridruivanja := ili kljunu rije DEFAULT. Deklaracija svake varijable zavrava s
toka-zarez.
DECLARE
ime_zaposlenika VARCHAR2(30);
broj_sati INTEGER:
cijena_po_satu CONSTANT DECIMAL(5,2) := 100.00;
Kao to je ve spomenuto blokovi se mogu nalaziti jedni unutar drugih, te se javlja pitanje
vidljivosti varijabli. Tako postoje dvije vidljivosti varijable, a to su lokalna i globalna
vidljivosta. Globalno definirane varijable su definirane u vanjskom bloku, te su vidljive svim
blokovima koji se nalaze unutar tog bloka. Dok su lokalno definirane varijable definirane u
unutarnjem bloku i nisu dostupne za koritenje u vanjskom bloku.
DECLARE
prvi_broj INTEGER := 11;
8 TutorialsPoint (2014) - PL/SQL Tutorial, PL/SQL - Variables, URL:
http://www.tutorialspoint.com/plsql/plsql_variable_types.htm, dostupno 14.06.2014.
9
drugi_broj INTEGER := 12;
BEGIN
DBMS_OUTPUT.PUT_LINE('Vanjski blok prvi: ' || prvi_broj); DBMS_OUTPUT.PUT_LINE('Vanjski blok drugi: ' || drugi_broj); --unutarnji blok
DECLARE
prvi_broj INTEGER := 13;
BEGIN
DBMS_OUTPUT.PUT_LINE('Unutarnji blok prvi: ' || prvi_broj); DBMS_OUTPUT.PUT_LINE('Unutarnji blok drugi: ' || drugi_broj);
END;
END;
Vanjski blok prvi: 11 Vanjski blok drugi: 12 Unutarnji blok prvi: 13 Unutarnji blok drugi: 12
U ovom bloku su definirane dvije varijable u vanjskom bloku, odnosno te su varijable
globalno vidljive. Dok je u drugom, unutarnjem bloku definirana trea varijabla koja je
vidljiva samo unutar tog bloka.
Kada se unutar vanjskog bloka ispisuju dvije varijable one ispisuju vrijednosti 11 i 12. U
unutarnjem bloku se deklarira nova varijabla pod istim imenom kao i u vanjskom bloku samo
joj je inicijalna vrijednost 13. Pa kod ponovnog ispisa prve varijable ispisuje ona koja je
lokalno definirana, odnosno ispisuje se vrijednost 13. Dok se kod ispisa druge varijable
ispisuje globalno definirana varijabla, odnosno vrijednost 12.
U gornjem bloku je koritena DBMS_OUTPUT.PUT_LINE naredba koja je dio
DBMS_OUTPUT paketa koji naee slui za prikaz poruka i izvjetaja. Dok naredbe PUT i
PUT_LINE mogu stavljati informacije u meuspremnik, kako bi se te iste mogle proitati od
strane drugog okidaa, procedure ili paketa.
Uz to koriteni sui komentari unutar bloka, koji se u PL/SQL blokovima obiljeavaju na dva
naina. Prvi nain je koristei dvije crtice -- koje znaavaju da je taj redak komentar, a drugi
nain je da komentar zapoinje znakom /* te se nastavlja sve do prvog pojavljivanja znaka */
to znai da se moe pisati preko vie redaka.
10
5. Tipovi podataka u PL/SQL-u9
Svaka varijabla i parametar moraju imati valjane tipove podataka koji definiraju nain
spremanja, vrijednosti koje mogu poprimiti, operacije koje se mogu izvoditi nad njima i
ogranienja koja se primjenjuju. PL/SQL ima velik broj predefiniranih tipova podataka i
njihovih podtipova te doputa stvaranje vlastitih PL/SQL podtipova. Podtip je podskup
drugog tipa podataka koji se zove osnovni tip, a podtip ima sve iste operacija kao i osnovni ali
nema isti raspon vrijednosti koje moe poprimiti. PL/SQL ima etiri glavne kategorije tipova
podatka, a to su:
skalarni tipovi podataka (eng. Scalar) jedna vrijednost tipa DATE, NUMBER,
VARCHAR2, CHAR
kompozitni tipovi podataka (eng. Composite) podatkovni zapisi koji imaju unutarnje
komponente koje su skalarnog tipa podataka te kojima se moe pristupiti pojedinano
(zapis, kolekcija)
referencirani tipovi podataka (eng. Reference) pokazivai na podatkovne zapise
(kursor varijabla)
veliki objekti (eng. Large Object LOB) pokazivai na velike podatkovne objekte
koji se spremaju odvojeno od ostalih podatkovnih zapisa. To su objekti kao tekst,
slike, video i audio zapisi.
U ovom poglavlju e se obraditi samo skalarni tipovi podataka, dok e ostali biti obraeni u
posebnim poglavljima.
5.1. Skalarni tipovi podataka
Skalarni tipovi podataka pohranjuju jednu vrijednost.. U kategoriju skalarnih tipova podataka
pripadaju tipovi podataka:
brojani tip podataka (eng. numeric data types)
znakovni tip podataka (eng. character data types)
BOOLEAN tip podataka
datumski i vremenski tip podataka (eng. datetime data types)
intervalni tip podataka (eng. interval data types)
9 Oracle (2009) - Oracle Database PL/SQL Language Reference 11g Release 1, PL/SQL Data Types, URL:
http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/datatypes.htm#i10924, dostupno 14.06.2014.
11
5.1.1. Brojani tipovi podataka10
Brojani tipovi podataka (eng. numeric) zapisuju brojane vrijednosti nad kojima se mogu
izvoditi aritmetike operacije.
PLS_INTEGER i BINARY_INTEGER su identini tipovi podataka te spremaju cijele
brojeve s predznakom u rasponu od -2 147 483 648 do 2 147 483 647. Sam zapis se sprema
pomou 32 bita, te ovdje ima prednost nad NUMBER tipom podataka koji zauzima vie
mjesta za pohranu. Druga prednost je da se operacije nad PLS_INTEGER tipom podataka
izvode strojno.
BINARY_FLOAT i BINARY_DOUBLE tipovi podataka predstavljaju single-precision i
double-precision zapis broja prema IEEE 754 standardu za zapis decimalnih brojeva. Razlika
je u tome to BINARY_FLOAT kao single_precision zauzima 32 bita za zapis, to je duplo
manje od 64 koje zauzima BINARY_DOUBLE kao double-precision.
NUMBER tip podataka moe spremati decimalni i cijeli broj. Definira se kao
NUMBER(preciznost, skala) gdje preciznost (eng. precision) predstavlja ukupan broj
znamenki, a skala (eng. scale) predstavlja broj znamenki nakon decimalne toke. Da bi se
definirao cijeli broj koristi se NUMBER(3), gdje broj ne moe imati vie od 3 znamenke.
Decimalni zapis se moe zapisati s pominom ili fiksnom decimalnom tokom. Za pominu
decimalnu toku je dovoljno napisati NUMBER, te se ona moe zapisati na bilo kojem
mjestu. Dok za fiksnu decimalnu toku treba napisati NUMBER(5,2), te sada broj ne moe
imati vie od 5 znamenki i mora imati dvije znamenke nakon decimalne toke. Parametar
preciznost ima najveu vrijednost 38, dok za parametar skala vrijednosti se kreu od -84 i
127. Ako je skala podeena na 2, tada e se vrijednost 2.111 zaokruiti na najbliu deseticu
odnosno 2.11. A ko je skala podeena na -2, tada se vrijednost 2111 zaokruuje na najbliu
deseticu s lijeve strane decimalne toke odnosno 2110. Ako je skala na svojoj zadanoj
vrijednosti koja je 0, tada se decimalni brojevi zaokruuju na najblii cijeli broj, odnosno
vrijednost 2.11 na 2.
10
Oracle (2009) - Oracle Database PL/SQL Language Reference 11g Release 1, Predefined PL/SQL Numeric Data Types and Subtypes, URL: http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/datatypes.htm#i10726, dostupno 14.06.2014.
12
5.1.2. Znakovni tipovi podataka11
Znakovni tipovi podataka (eng. character) mogu zapisivati alfanumerike vrijednosti koje
predstavljaju jedan znak ili niz znakova (eng. string) sa kojima moemo manipulirati (spajati,
rastavljati, pretraivati i slino).
CHAR i NCHAR zapis znakovnog niza fiksne duljine, te se definiraju kao CHAR(veliina) i
NCHAR(veliina). Najvea doputena duljina je 32 767 bajtova. Parametar veliina (eng.
size) definira broj znakova koji se sprema u tu varijablu. Ako je broj znakova manji od zadane
veliine, tada se razlika broja znakova popuni praznim mjestima. Razlika izmeu CHAR i
NCHAR je u standardu zapisa (eng. charset) koji se koristi, tako CHAR koristi standard
zapisa kakav koristi i sama baza dok NCHAR koristi Unicode, odnosno nacionalni standard
zapisa.
VARCHAR2 i NVARCHAR2 zapis znakovnog niza varijabilne duljine, te se definiraju kao
VARCHAR(veliina) i NVARCHAR(veliina). Najvea doputena duljina je takoer 32 767
bajtova. Kod ovog tipa podataka, parametar veliina (eng. size) definira najvei broj znakova
koji se spremaju u tu varijablu. Tako da se sprema samo onoliko znakova koliko je upisano,
pod uvjetom da ne prelaze definiranu granicu. Razlika izmeu VARCHAR i NVARCHAR je
takoer u standardu zapisa koji se koristi.
LONG je zapis kao i VARCHAR2 samo to je najvea doputena duljina 2 gigabajta, pa
moe spremati tekst, nizove znakova te ak i krae dokumente.
LONG RAW je zapis najvee doputene duljine 2 gigabajta samo to sprema sirove binarne
podatke.
ROWID je oznaka dodatne kolone koja sprema binarne vrijednosti rowid koje jednoznano
identificiraju redove te omoguavaju bri pristup retcima. Pomou funkcije
ROWIDTOCHAR se vrijednost pretvara i zapisuje kao CHAR.
select ROWIDTOCHAR(ROWID) into karakter from servis where id_servisa = 1;
Gornja naredba daje vrijednost rowid-a AAAFJPAABAAAK/xAAA, pomou kojega se
jednoznano moe pristupiti tome retku.
11
Oracle (2009) - Oracle Database PL/SQL Language Reference 11g Release 1, Predefined PL/SQL Character Data Types and Subtypes, URL: http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/datatypes.htm# CIHGBBIG, dostupno 14.06.2014.
13
5.1.3. BOOLEAN tip podataka12
BOOLEAN tip podataka sprema logike vrijednosti TRUE i FALSE, ali i vrijednost NULL.
Vrijednosti tog tipa podataka se mogu koristiti u logikim operacijama. Ali taj tip podataka se
moe koristiti samo unutar PL/SQL-a, a ne unutar samog SQL-a. to znai da se ne koristi u
SQL naredbama, predefiniranim SQL funkcijama ni PL/SQL funkcijama koje se pozivaju u
SQL naredbama.
U tablicu se ne moe unijeti logika vrijednost koja predstavlja TRUE i FALSE, pa se
najee koriste vrijednost (0,1), ('Y','N'),('true','false') te se kasnije moe koristiti IF-THEN
ili CASE za prijevod znaenja tih stupaca tablice.
5.1.4. Tipovi podataka za oznaavanje datuma, vremena i intervala13
Tipovi podataka omoguavaju pohranu i rad s datumima, vremenima i intervalima, odnosno
vremenskim razdobljima. Tri su glavna tipa podataka, a to su DATE, TIMESTAMP i
INTERVAL.
DATE predstavlja datumski tip podataka koji sprema datum u formatu dd.MM.yyyy. zajedno
s vremenom dana, koje se inae ne prikazuje. Funkcija SYSDATE vraa trenutni datum i
vrijeme. Kako bi se maknuo vremenski dio datuma koristi se funkcija TRUNC(SYSDATE)
koja vraa datum i vrijeme postavljeno na 00:00:00. Ako elimo saznati vremenski dio DATE
tipa podataka moemo koristiti funkciju TO_CHAR(datum, 'hh24:mi:ss') koja vrati samo
vrijeme datuma.
DECLARE
datum DATE := SYSDATE;
BEGIN
DBMS_OUTPUT.PUT_LINE('Datum s vremenom: ' || datum);
DBMS_OUTPUT.PUT_LINE('Vremenski dio: ' || to_char(datum, 'hh24:mi:ss'));
DBMS_OUTPUT.PUT_LINE('Datum bez vremena: ' || trunc(datum));
DBMS_OUTPUT.PUT_LINE('Vremenski dio: ' || to_char(trunc(datum),
'hh24:mi:ss'));
END;
Datum s vremenom: 20.05.14
Vremenski dio: 23:48:10
Datum bez vremena: 20.05.14
Vremenski dio: 00:00:00
12
Oracle (2009) - Oracle Database PL/SQL Language Reference 11g Release 1, Predefined PL/SQL BOOLEAN Data Type, URL: http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/datatypes.htm#CJACJGBG, dostupno 14.06.2014. 13
Oracle (2009) - Oracle Database PL/SQL Language Reference 11g Release 1, Predefined PL/SQL Datetime and Interval Data Types, URL: http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/datatypes.htm#i45907, dostupno 14.06.2014.
14
U varijabli datum je spremljen trenutni datum, te se prvo ispisuje kao to je i deklariran te se
dobiva datumski dio. Da se dobije vremenski dio mora se pretvoriti prema nekom
predefiniranom uzorku te se za to koristi 'hh24:mi:ss' format s kojim se dobiva vremenski dio
u dvadeset i etiri satnom formatu. Jo se moe koristiti i format 'hh:mi:ss' gdje vrijeme nije u
dvadeset i etiri satnom formatu. Datum bez vremenskog dijela se ispisuje isto kao i i datum s
vremenskim dijelom, ali kada se pokua ispisati vrijeme datuma bez vremenskog dijela za
vrijednost vremena se dobije 00:00:00.
TMESTAMP proiruje DATE format podataka te sprema godinu, mjesec, sat, minutu i
sekundu, te se definira kao TIMESTAMP(preciznost) gdje je preciznost (eng. precision)
duljinu broja koji se zapisuje poslije sekundi i predstavlja djeli sekunde koji je protekao u
zadanoj preciznosti.
TIMESTAMP WITH TIME ZONE je tip podataka kao i TIMEZONE, samo to se na kraju
ispisuje vremenska zona.
TIMEZONE WITH LOCAL TIME ZONE isti tip podataka kao i TIMESTAMP WITH
TIME ZONE samo to je kada se upisuje vrijednost u bazu, ona se pretvara u vrijednost
prema vremenskoj zoni baze podataka te se razlika ne pohranjuje u stupac. A kada se dohvaa
iz baze vrijednost se mjenja prema korisnikoj lokalnoj vremenskoj zoni.
DECLARE
vrijeme TIMESTAMP(4) := SYSTIMESTAMP;
vrijeme_tz TIMESTAMP(4) WITH TIME ZONE := SYSTIMESTAMP;
vrijeme_tz_loc TIMESTAMP(4) WITH LOCAL TIME ZONE := SYSTIMESTAMP;
BEGIN
DBMS_OUTPUT.PUT_LINE('Vrijeme: ' || vrijeme);
DBMS_OUTPUT.PUT_LINE('Vrijeme s vremenskom zonom: ' || vrijeme_tz);
DBMS_OUTPUT.PUT_LINE('Vrijeme s lokalnom vremenskom zonom: ' ||
vrijeme_tz_loc);
END;
Vrijeme: 21.05.14 00:22:33,8630
Vrijeme s vremenskom zonom: 21.05.14 00:22:33,8630 +02:00
Vrijeme s lokalnom vremenskom zonom: 21.05.14 00:22:33,8680
INTERVAL YEAR TO MONTH je tip podataka koji sprema interval koji predstavlja
razdoblje godine i mjeseca. Definira se kao INTERVAL YEAR [(preciznost)] TO MONTH
gdje je preciznost (eng. precision) neobavezan podatak koji predstavlja preciznost godina te
moe biti od 0 do 4, a ako se ne navede zadana vrijednost je 2.
DECLARE
trenutak TIMESTAMP(4) := SYSTIMESTAMP;
razdoblje INTERVAL YEAR(1) TO MONTH;
15
BEGIN
razdoblje := INTERVAL '5-4' YEAR TO MONTH;
DBMS_OUTPUT.PUT_LINE('Razdoblje: ' ||razdoblje);
razdoblje := INTERVAL '9' YEAR;
DBMS_OUTPUT.PUT_LINE('Razdoblje: ' ||razdoblje);
razdoblje := INTERVAL '3' MONTH;
DBMS_OUTPUT.PUT_LINE('Razdoblje: ' ||razdoblje);
razdoblje := '2-7';
DBMS_OUTPUT.PUT_LINE('Razdoblje: ' ||razdoblje);
DBMS_OUTPUT.PUT_LINE('Trenutak: ' || trenutak);
trenutak := trenutak + razdoblje;
DBMS_OUTPUT.PUT_LINE('Trenutak + razdoblje: ' || trenutak);
END;
Razdoblje: +5-04
Razdoblje: +9-00
Razdoblje: +0-03
Razdoblje: +2-07
Trenutak: 21.05.14 23:22:04,8590
Trenutak + razdoblje: 21.12.16 23:22:04,8590
Postoji vie naina kako pridjeliti vrijednost varijabli tog tipa podatka. Pa je tako mogue
dodati posebno svaki dio, odnosno posebno godinu i posebno mjesec razdoblja. Mogue je
pridjeliti vrijednost kao karakter koji se implicitno pretvara interval. I kao literal, odnosno
fiksno zadana vrijednost INTERVAL '5-4' YEAR TO MONTH. Svi primjeri su pokazani u
primjeru iznad, te je zadnja vrijednost intervala '2-07' dodana na trenutak u vremenu koji je
sada uvean za dvije godine i sedam mjeseci.
INTERVAL DAY TO SECOND je tip podataka koji sprema interval koji predstavlja broj
dana, sati, minuta i sekundi. Sama sintaksa za njegovu deklaraciju je INTERVAL DAY
[(preciznost_dana)] TO SECOND [(preciznost_sekundi)], gdje se odabire preciznost za dan i
za dio sekunde, ali ako se ne definira zadane vrijednosti su 2 za dan i 6 za dio sekunde.
DECLARE
trenutak TIMESTAMP(4) := SYSTIMESTAMP;
razdoblje INTERVAL DAY(2) TO SECOND(4);
BEGIN
razdoblje := INTERVAL '8 12:30:45' DAY TO SECOND;
DBMS_OUTPUT.PUT_LINE('Razdoblje: ' ||razdoblje);
razdoblje := razdoblje + INTERVAL '4' HOUR;
DBMS_OUTPUT.PUT_LINE('Razdoblje: ' ||razdoblje);
razdoblje := razdoblje + '1 00:00:00';
DBMS_OUTPUT.PUT_LINE('Razdoblje: ' ||razdoblje);
END;
16
Razdoblje: +08 12:30:45.0000
Razdoblje: +08 16:30:45.0000
Razdoblje: +09 16:30:45.0000
Kao i za prethodni tip podataka, mogue je u interval dodati svaku vrijednost posebno, kao
literal odnosno fiksno te kao karakter koji se implicitno pretvara u interval.
5.2. Usidreni tipovi podataka14
Varijabli je mogue dodati i tip podataka koji predstavlja jedan redak u tablici ili stupac u
tablici. Tako je sintaksa za deklariranje varijable prema stupcu ili retku sljedea:
naziv_varijable ime_tablice.ime_stupca%TYPE naziv_varijable ime_tablice%ROWTYPE
Prednost je da se kod promjene tipa podataka u tablici ne treba mjenjati PL/SQL kod jer se tip
uzima direktno iz tablice to olakava odravanje baze podataka, odnosno potprograma,
okidaa i slino.
DECLARE
ime zaposlenik.ime_zap%TYPE;
id_serv servis.id_servisa%TYPE;
grad servis.grad_servisa%TYPE;
red servis%ROWTYPE;
BEGIN
SELECT z.ime_zap, s.id_servisa, s.grad_servisa
INTO ime, id_serv, grad
FROM zaposlenik z
JOIN servis s on s.id_servisa = z.servis_id_servisa
WHERE z.id_zap = 1;
DBMS_OUTPUT.PUT_LINE('Zaposlenik ' || ime ||' radi u servisu ' || grad);
SELECT * INTO red
FROM servis WHERE id_servisa = id_serv;
DBMS_OUTPUT.PUT_LINE('Servis se nalazi na adresi: ' || red.adresa_servisa);
END;
Zaposlenik Ivica radi u servisu Zagreb
Servis se nalazi na adresi: Ilica 58
U primjeru iznad definirane su tri varijable kojima je za tip podataka pridruen tip podataka
stupca u odreenoj tablici, te je definirana jo jedna varijabla kojoj je tip podataka tip cijelog
retka u tablici. Prvim upitom dobavimo ime servisera, identifikator servisa i grad servisa te
spremimo podatke u za to predviene varijable. Koristei varijablu koja predstavlja
identifikator servisa, drugim upitom se dohvaa cijeli redak koji predstavlja taj servis. Za
pristup komponentama te varijable, odnosno retka koristi se sintaksa:
14
Rosenzweig B., Rakhimov E. (2009) Oracle PL/SQL by Example Fourth Edition, str.29.
17
ime_varijable.ime_stupca
U ovom primjeru prikazan dohvat i koritenje usidrenih tipova podataka u PL/SQL-u.
Najvanija prednost je ta da se uklanja potreba za tipovima podataka te odravanjem PL/SQL
koda kod svake promjene na bazi. Primjerice za sada je tip podataka za stupac adresa_servisa
u tablici servis VARCHAR2(30) i ako bi se on u budunosti poveao na VARCHAR2(45) u
njega bi se upisivale adrese koje su do te duljine. U isto vrijeme je PL/SQL kod ostao isti i
varijabla ostala pod tipom podataka VARCHAR2(30). Sada kod dohvaanja varijable koja
prelazi duljinu 30 za taj tip podataka doi do greke zbog neprikladnog tipa podataka. Zato
usidreni tipovi podataka eliminiraju potrebu za odravanjem tipova podataka u kodu, jer se
tipovi uzimaju direktno iz tablice.
18
6. Operatori15
Operatori omoguavaju rad sa varijablama, odnosno operandima te vraanje rezulatata. Svaki
operand ima rezervirani znak ili kljunu rije koja se pojavljuje ispred operanda ili izmeu
dva operanda. To ovisi o tome je li operand unaran ili binaran. Ako je unaran tada se
pojavljuje kao 'operator operand', dok se binaran pojavljuje kao 'operand operator operand'.
A postoje ak i operatori koji prihvaaju vie operanada.
6.1. Aritmetiki operatori
Aritmetiki operatori omoguavaju rad s brojevima, odnosno rad s varijablama koje su
numerikog tipa podataka. Operatori su:
zbrajanje (+) prvom operandu dodaje drugi operand
oduzimanje (-) od prvog operanda oduzima drugi operand
mnoenje (*) mnoi prvi operand s drugim operandom
djeljenje (/) dijeli prvi operand s drugim operandom
potenciranje (**) potencira prvi operand na drugi operand
Aritmetiki operatori omoguavaju rad s brojevima, odnosno njihovo zbrajanje, oduzimanje,
mnoenje i potenciranje. Koriste se nad numerikim tipovima podataka.
6.2. Operatori usporedbe
Operatori usporedbe usporeuju dva izraza. Rezultat je BOOLEAN vrijednost, a operatori su:
operator jednakosti (=) usporeuje jednakost dviju vrijednosti
operator razliitosti (!=, , ~=) usporeuje razliitost dviju varijabli
vei od (>) usporeuje da li je prva vrijednost vea od druge vrijednosti
manji (=) - usporeuje da li je prva vrijednost vea ili jednaka drugoj
manji ili jednak (
19
boja' LIKE '%oja' vraa TRUE jer znak % u ovom sluaju zamjenjuje izraz 'Crna b'. U
sluaju da je izraz bio 'Crna boja' LIKE '%xja' rezultat bi bio FALSE. U izrazu 'boja'
LIKE '_oja' rezultat bi bio TRUE jer znak _ zamjenjuje slovo 'b', dok bi u izrazu
'bxoja' LIKE '_oja' rezultat bio FALSE.
BETWEEN operator provjerava da li je neka vrijednost unutar nekog intervala.
Operacija se provjerava izrazom vrijednost BETWEEN pocetna_vrijednost AND
krajnja_vrijednost. Rezultat je istinit odnosno TRUE ako je vrijednost vea ili jednaka
poetnoj vrijednosti i manja ili jednaka krajnjoj. Za napomenuti je da je vano da
poetna vrijednost bude manja od prve, jer ako se usporeuje da li je broj 3 u intervalu
od 1 do 5 vratit e se TRUE. Dok e se za interval od 5 do 1 vratiti FALSE.
IN operator provjerava da li se neka vrijednost nalazi u skupu nekih vrijednosti, te se
provjerava izrazom vrijednost IN (vrijednost1, ..., vrijednostN). Ako se vrijednost
nalazi u tom skupu vrijednosti, rezultat je TRUE dok je u suprotnom FALSE.
IS NULL provjerava da li je neka vrijednost jednaka null. U SQL-u se openito ne
koristi izraz jednakosti za provjeru da li je vrijednost jednaka null nego operator IS
NULL i njegova varijacija IS NOT NULL. Za napomenuti je da CHAR ili
VARCHAR2 tip podataka koji imaju samo whitespaces nije jednak null, ali ako se
koristi funkcija TRIM nad tom vrijednosti, ona makne whitespaces pa e vrijednost
biti jednaka null te e se u tom sluaju vratiti TRUE.
6.3. Logiki operatori
Pomou logikih operatora grade se sloeniji uvjeti koji se ispituju. Rade samo s logikim,
odnosno BOOLEAN izrazima i kao rezultat takoer daju BOOLEAN izraz.
AND operator daje TRUE samo ako su oba izraza istinita, odnosno TRUE
OR operator daje TRUE ako je bilo koji od dva izraza istinit, odnosno TRUE
NOT operator unarni operator koji mjenja logiku vrijednost iz TRUE u FALSE i
obrnuto
20
7. Izrazi za kontrolu programskog toka PL/SQL-a
Izrazi za kontrolu ukljuuju selekciju, iteraciju i sekvencu. Oni omoguavaju testiranje uvjeta,
petlje te grananje kako bi se mogli napisati dobro strukturirani PL/SQL programi. U
programerskom smislu to znai da se naredbe ne moraju izvravati sekvencijalno, nego da se
skupina naredbi izvri ili ne izvri ovisno o tome da li je ispunjen odreeni upit.16 Prikaz
izvoenja tih kontrolnih struktura je prikazan slikom 4.
Slika 4. Kontrolne strukture17
7.1. Selekcija18
Selekcija omoguava da ovisno o ispunjenosti uvjeta se izvri odreena grupa naredbi. Ako
uvjet nije ispunjen, moe se izvriti druga grupa naredbi. Selekcija se ugrubo moe podjeliti
na IF i CASE kontrole.
IF-THEN je najjednostavnija inaica selekcije koja provjerava jedan uvjet, te u sluaju da je
on istinit odnosno TRUE, izvrava naredbe koje se nalaze izmeu kljunih rijei THEN i
END IF. Ako je uvjet FALSE ili NULL ne izvrava se nita.
IF uvjet THEN
naredbe_koje_se_izvravaju END IF;
16
Rosenzweig B., Rakhimov E. (2009) Oracle PL/SQL by Example Fourth Edition, str.53. 17
Oracle (2009) - Oracle Database PL/SQL Language Reference 11g Release 1, Overview of PL/SQL Control Structures, URL: http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/controlstructures.htm #LNPLS00401, dostupno 14.06.2014. 18
Oracle (2009) - Oracle Database PL/SQL Language Reference 11g Release 1, Testing Conditions, URL: http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/controlstructures.htm#LNPLS00402, dostupno 14.06.2014.
21
IF-THEN-ELSE je dosta slina kao i IF-THEN, samo je razlika u tome to se definiraju i
naredbe koje se izvravaju u sluaju da je uvjet FALSE ili NULL. Naredbe u sluaju
istinitosti uvjeta se nalaze izmeu kljunih rijei THEN i ELSE, dok se za drugi sluaj
naredbe nalaze izmeu kljunih rijei ELSE i END IF.
IF uvjet THEN
naredbe_uvjet_ispunjen
ELSE
naredbe_uvjet_neispunjen
END IF;
IF-THEN-ELSIF omoguava testiranje vie uvjeta te odabir naredbi za izvoenje na temelju
tih uvjeta. Prvi uvjet se testira sa IF, dok svaki svaki sljedei se testira s kljunom rijei
ELSIF. Na kraju jo postoji i ELSE kljuna rije nakon koje se nalaze naredbe koje se
izvravaju ako se nije izvrio ni jedan dio iznad.
IF uvjet_1 THEN
naredbe_uvjet_1_ispunjen
ELSIF uvjet_2 THEN
naredbe_uvjet_2_ispunjen
ELSE
naredbe_uvjeti_neispunjeni
END IF;
Sve IF selekcije se mogu meusobno ugnjeivati pa je u sljedeem primjeru prikazano
ugnjeivanje sa IF-THEN, IF-THEN-ELSE i IF-THEN-ELSIF naredbama. Unutar IF-THEN
se ispituje da li je varijabla jednaka null. Ako nije izvrava se unutarnji dio koji je IF-THEN-
ELSE naredba koja ispituje da li je ocjena pozitivna ili negativna te ovisno o rezultatu
izvrava jedan od dva dijela. Ako je ocjena pozitivna, pomou IF-THEN-ELSIF naredbe se
ispituje koja je ocjena te ovisno o tome dodjeljuje vrijednosti u drugu varijablu. Tako se mogu
izvravati razliite grupe naredbi ovisno o uvjetima.
DECLARE
ocjena INTEGER := 4;
naziv VARCHAR2(10);
BEGIN
IF ocjena IS NOT NULL THEN
IF ocjena >= 2 AND ocjena
22
DBMS_OUTPUT.PUT_LINE('Prolaz na ispitu, ocjenom ' || naziv);
ELSE
DBMS_OUTPUT.PUT_LINE('Pad na ispitu');
END IF;
END IF;
END;
Prolaz na ispitu, ocjenom Vrlo dobar
CASE je veoma slian IF-THEN-ELSE naredbi, samo je razlika da umjesto vie uvjeta
kojima se ispituje istinitost, koristi selektor. Zapoinje kljunom rijei CASE nakon koje
dolazi selektor i nakon toga se navodi vie izjava kojima se ispituje selektor. Zapoinje
kljunom rijei WHEN nakon koje dolazi vrijednost, te ako je selektor jednak toj vrijednosti
izvrava se blok naredbi koje se nalaze iza kljune rijei THEN i prije sljedee kljune rijei
WHEN ili ELSE. ELSE se izvrava ako ni jedna izjava iznad nije bila izvrena. Sam blok
zavrava kljunom rijei END CASE.
CASE selektor
WHEN 'X' THEN naredbe_selektor_X
WHEN 'Y' THEN naredbe_selektor_Y
ELSE naredbe _default
END CASE;
Postoji i druga verzija CASE selekcije koja nema selektor nego pretrauje na nain da
usporeuje varijablu izmeu kljunih rijei WHEN i THEN, te ako usporedba rezultira
istinitim rezultatom izvodi se taj blok izjava.
CASE
WHEN selektor = 'X' THEN naredbe_selektor_X
WHEN selektor = 'Y' THEN naredbe_selektor_Y
ELSE naredbe_default
END CASE;
Isti primjer kao i za IF grupu naredbi je prikazan u sljedeem primjeru, te se ovdje koristi
CASE naredba sa selektorom. Verzija bez selektora bi se razlikovala samo po tome to bi se
varijabla ocjena uspreivala sa vrijednosti izmeu kljunih rijei WHEN i THEN.
DECLARE
ocjena INTEGER := 4;
naziv VARCHAR2(10);
BEGIN
IF ocjena IS NOT NULL AND ocjena BETWEEN 2 AND 5 THEN
CASE ocjena
WHEN 2 THEN naziv := 'Dovoljan';
WHEN 3 THEN naziv := 'Dobar';
WHEN 4 THEN naziv := 'Vrlo dobar';
WHEN 5 THEN naziv := 'Izvrstan';
END CASE;
23
DBMS_OUTPUT.PUT_LINE('Prolaz na ispitu, ocjenom ' || naziv);
ELSE
DBMS_OUTPUT.PUT_LINE('Pad na ispitu');
END IF;
END;
Prolaz na ispitu, ocjenom Vrlo dobar
7.2. Iteracija19
Iteracije se koriste kada se blok naredbi treba izvriti vie puta. Blok naredbi se izvodi sve dok
je uvjet za izvoenje iteracije, odnosno petlje ispunjen.
Osnovna petlja okruuje blok naredbi koje se trebaju izvriti izmeu dvije kljune rijei
LOOP i END LOOP.
LOOP
blok_naredbi;
END LOOP;
Ova petlja nema ispitivanja uvjeta koji odreuje kada se prekida izvoenje petlje. Zato se
koriste naredbe EXIT i EXIT WHEN. Naredba EXIT se koristi zajedno sa IF-THEN
naredbom, dok se EXIT WHEN moe koristiti sama.
DECLARE
x NUMBER := 1;
BEGIN
LOOP
x := x + 10;
IF x > 10 THEN
EXIT;
END IF;
END LOOP;
END;
DECLARE
x NUMBER := 1;
BEGIN
LOOP
x := x + 10;
EXIT WHEN x > 10;
END LOOP;
END;
U sljedeem primjeru e se prikazati izvoenje osnovne petlje na jednostavnom primjeru koji
ispituje djeljivost broja sa brojevima od 1 do 10. Izlaz iz petlje je ostvaren EXIT WHEN
naredbom koja provjerava uvjet, te kada je on ispunjen izlazi iz petlje.
DECLARE
n INTEGER := 85;
brojac INTEGER := 1;
BEGIN
LOOP
IF(MOD(n, brojac) = 0) THEN
DBMS_OUTPUT.PUT_LINE(n || ' je djeljiv s ' || brojac);
END IF;
19
Oracle (2009) - Oracle Database PL/SQL Language Reference 11g Release 1, Controlling Loop Iterations, URL: http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/controlstructures.htm#LNPLS00403, dostupno 14.06.2014.
24
brojac := brojac + 1;
EXIT WHEN brojac > 10;
END LOOP;
END;
Broj 85 je djeljiv s 1
Broj 85 je djeljiv s 5
WHILE petlja je petlja koja se izvrava neodreeni broj puta, odnosno izvrava se sve dok je
uvjet istinit.
WHILE uvjet LOOP
blok_naredbi;
END LOOP;
Isti primjer kao za osnovnu LOOP petlju je sada napravljen pomou WHILE petlje. Razlika je
u tome to se uvjet mora biti ispunjen definira nakon kljune rijei WHILE, te petlja sama
prekida izvoenje kada uvjet vie nije ispunjen.
DECLARE
n INTEGER := 85;
brojac INTEGER := 1;
BEGIN
WHILE brojac
25
BEGIN
FOR brojac IN 1 .. 10 LOOP
IF(MOD(n, brojac) = 0) THEN
DBMS_OUTPUT.PUT_LINE(n || ' je djeljiv s ' || brojac);
END IF;
END LOOP;
END;
85 je djeljiv s 1
85 je djeljiv s 5
26
8. Kursori
Kursori (eng. cursor) su memorijski prostori gdje su pohranjene informacije koje su potrebne
da Oracle izvrava SQL naredbe.20 PL/SQL upravlja tim memorijskim prostorom pomou
kursora koji slui kao pokaziva na taj memorijski prostor. U kursoru se nalaze podatci kao
broj redaka koji su dohvaeni upitom, retci koji su dohvaeni i slino. Retci koji se nalaze u
kursoru jo se nazivaju aktivan skup (eng. active set). Najvanija karakteristika kursora je da
on moe biti imenovan kako bi se mogao pozivati u kodu, te omoguava obradu svih redaka
koji se nalaze u njemu. Postoje dvije vrste kursora21
:
implicitni kursor
eksplicitni kursor
8.1. Implicitni kursor22
Svaki put kada se izvri SQL naredba, Oracle implicitno kreira kursor. Implicitni kursor se
kreira za DML (eng. data manipulation language) naredbe, odnosno UPDATE, DELETE i
INSERT naredbe. UPDATE i DELETE naredbe imaju kursor koji identificira retke koji e se
promijeniti ili obrisati, dok za INSERT naredbu kursor sprema podatke koji se upisuju bazu
podataka. Implicitni kursor se koristi jo za SELECT INTO naredbu, koja dobavlja samo
jedan red te njegove vrijednosti upisuje u neku varijablu. Zadnji otvoreni implicitni kursor se
naziva SQL kursor, te mu se pristupa preko oznake SQL. Preko te oznake se moe saznati
koliko je redova bilo zahvaeno zadnjom SQL naredbom, koristei %ROWCOUNT nad SQL
oznakom, odnosno SQL%ROWCOUNT.
DECLARE
broj INTEGER;
BEGIN
UPDATE nalog SET cijena = 0;
broj := SQL%ROWCOUNT;
DBMS_OUTPUT.PUT_LINE('Broj redaka: ' || broj);
UPDATE nalog SET cijena = 1 WHERE idnalog = 54;
broj := SQL%ROWCOUNT;
DBMS_OUTPUT.PUT_LINE('Broj redaka: ' || broj);
END;
Broj redaka: 3134
Broj redaka: 1
20
Rosenzweig B., Rakhimov E. (2009) Oracle PL/SQL by Example Fourth Edition, str.229. 21
Rosenzweig B., Rakhimov E. (2009) Oracle PL/SQL by Example Fourth Edition, str.230. 22
Rosenzweig B., Rakhimov E. (2009) Oracle PL/SQL by Example Fourth Edition, str.231.
27
8.2. Eksplicitni kursor23
Za razliku od implicitnog kursora kojeg deklarira Oracle, eksplicitni kursor treba deklarirati u
programu. On se koristi za upite koji vraaju vie od jednog retka, te se deklarira u
deklarativnom dijelu PL/SQL bloka. Nakon toga se u izvrnom dijelu bloka mogu obraivati
retci koji se nalaze u tom kursoru. Rad s eksplicitnim kursorom se sastoji od etiri koraka:
deklariranje kursora (eng. declaring) deklaracija kursora u memoriji
otvaranje kursora (eng. opening) otvaranje deklariranog kursora i dodjeljivanje
memorije
dohvaanje kursora (eng. fetching) dohvaanje podataka iz deklariranog i otvorenog
kursora
zatvaranje kursora (eng. closing) deklarirani, otvoreni i dohvaeni kursor se zatvara
da se alocirana memorija oslobodi
Kursor se deklarira u deklarativnom dijelu PL/SQL bloka gdje mu se dodijeli ime za koje je
uobiajena praksa da zapone sa c_ kako bi se dalje u bloku znalo da se radi o kursoru. Uz to
jo mu se pridrui SELECT naredba, te je sintaksa za deklariranje sljedea:
CURSOR ime_kursora IS select_naredba;
Nakon deklariranja slijedi otvaranje kursora kod kojega se provjeri WHERE klauzula
SELECT naredbe, odredi aktivan skup, odnosno retci koji se zapisuju u kursor te se pokaziva
aktivnog skupa postavlja na prvi redak. Sintaksa za otvaranje kursora je:
OPEN ime_kursora;
Kada je kursor deklariran i otvoren, podatci iz njega se mogu dohvatiti. Iz kursora se dohvaa
red na koji pokazuje pokaziva kursora, te se podatci iz reda zapisuju u varijable deklariranu u
deklarativnom dijelu bloka. Sintaksa za dohvaanje retka iz kursora je:
FETCH ime_kursora INTO varijable
Kursor se moe zapisati u vie varijabli ili ako se dobavljaju podatci iz jedne tablice
uobiajeno je definirati varijablu koja je tipa %ROWTYPE. Nakon dohvaanja jednog retka,
pokaziva kursora se pomie na sljedei red aktivnog skupa. Taj postupak se ponavlja sve dok
se ne prou svi retci u aktivnom skupu. Zbog toga je uobiajeno koristiti osnovnu petlju gdje
se uvjet izlaza kontrolira pomou %NOTFOUND nad kursorom.
23
Rosenzweig B., Rakhimov E. (2009) Oracle PL/SQL by Example Fourth Edition, str.232.
28
DECLARE
CURSOR c_servis IS SELECT * FROM servis;
grad servis%ROWTYPE;
BEGIN
OPEN c_servis;
LOOP
FETCH c_servis INTO grad;
EXIT WHEN c_servis%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(grad.adresa_servisa || ', ' || grad.grad_servisa);
END LOOP;
CLOSE c_servis;
END;
Ilica 58, Zagreb
Radnika cesta 12, Zagreb Ulica brae Radi 2, Varadin
Kada se obrade svi retci iz kursora, on se treba zatvoriti kako bi se oslobodila alocirana
memorija. U bloku je mogue imati vie otvorenih kursora, te se kod kompliciranijih blokova
moe zauzeti puno memorije ako se ne vodi rauna o njihovom zatvaranju. Sintaksa za
zatvaranje kursora je
CLOSE ime_kursora;
Atributi koji se koriste kako bi se odredile neke karakteristike kursora kada je on otvoren ili
dohvaen:
ime_kursora%NOTFOUND BOOLEAN vrijednost, koja je TRUE ako prethodni
FETCH nije vratio red
ime_kursora%FOUND BOOLEAN vrijednost, koja je TRUE ako je prethodni
FETCH vratio red
ime_kursora%ROWCOUNT broj redaka u kursoru
ime_kursora%ISOPEN BOOLEAN vrijednost, koja je TRUE ako je kursor otvoren
Postoji i elegantniji nain za rad sa kursorima, a to je pomou FOR petlje koja
pojednostavljuje rad. Otvaranje, dohvaanje i zatvaranje kursora se radi implicitno te je lake
pisati i odravati kod.
DECLARE
CURSOR c_servis IS SELECT * FROM servis;
BEGIN
FOR r IN c_servis LOOP
DBMS_OUTPUT.PUT_LINE(r.adresa_servisa || ', ' || r.grad_servisa);
END LOOP;
END;
29
Ilica 58, Zagreb
Radnika cesta 12, Zagreb Ulica brae Radi 2, Varadin
U primjeru iznad je pokazan isti kod kao sa osnovnom LOOP petljom, te je kod puno ii
zbog toga jer FOR petlja implicitno prepoznaje kursor te obavlja sve korake potrebne za rad
sa njim.
8.2.1. Kursori s parametrima24
Kursoru se kod deklaracije mogu dodati i parametri, kako bi se isti mogao ponovno koristiti i
dati druge rezultate, odnosno aktivan skup. Kursoru se vrijednost parametra proslijeuje kod
njegovog otvaranja, ali mu se moe dodjeliti i DEFAULT vrijednost koja se koristi ako nije
nita proslijeeno. Vrijednost samog parametra je vidljiva samo unutar kursora.
DECLARE
CURSOR c_zaposlenici (p_servis IN servis.id_servisa%TYPE DEFAULT 2) IS
SELECT z.ime_zap, z.prezime_zap, s.grad_servisa
FROM zaposlenik z
JOIN servis s on s.id_servisa = z.servis_id_servisa
WHERE s.id_servisa = p_servis;
BEGIN
FOR r IN c_zaposlenici(1)
LOOP
DBMS_OUTPUT.PUT_LINE(r.ime_zap || ' ' ||r.prezime_zap || ', ' ||
r.grad_servisa);
END LOOP;
END;
Ivica Ivic, Zagreb
Marija Maric, Zagreb
Marko Markic, Zagreb
Gornji primjer prikazuje kursor koji ima DEFAULT vrijednost 2, te prima parametar koji je
istog tipa kao i stupac id_servisa u tablici servis. U izvrnom dijelu mu se proslijeuje
identifikator servisa, odnosno parametar vrijednosti 1 te kursor vrati zaposlenike koji rade u
tom servisu. Da kursoru nije proslijeen parametar vratio bi sve zaposlenike koji rade u
servisu koji ima identifikator 2. U sluaju da kursor nema DEFAULT vrijednost, dolazi do
greke ako mu se ne proslijedi parametar.
24
Rosenzweig B., Rakhimov E. (2009) Oracle PL/SQL by Example Fourth Edition, str.254.
30
8.2.2. Ugnjeeni kursori25
U PL/SQL-u kursori se mogu i ugnjeivati, te se tako vrijednosti koje vraa jedan kursor
mogu proslijediti drugom kursoru koji vraa retke prema tim vrijednostima.
DECLARE
CURSOR c_servisi IS
SELECT id_servisa, adresa_servisa, grad_servisa
FROM servis;
CURSOR c_zaposlenici (p_servis IN servis.id_servisa%TYPE) IS
SELECT ime_zap, prezime_zap
FROM zaposlenik
WHERE servis_id_servisa = p_servis;
BEGIN
FOR s IN c_servisi
LOOP
DBMS_OUTPUT.PUT_LINE('SERVIS: ' || s.adresa_servisa || ', ' ||
s.grad_servisa);
FOR r IN c_zaposlenici(s.id_servisa)
LOOP
DBMS_OUTPUT.PUT_LINE(r.ime_zap || ' ' ||r.prezime_zap);
END LOOP;
END LOOP;
END;
SERVIS: Ilica 58, Zagreb
Ivica Ivic
Marija Maric
Marko Markic
SERVIS: Radnika cesta 12, Zagreb Kruno Krunic
Matija Matic
Kreso Kresic
SERVIS: Ulica brae Radi 2, Varadin Petar Petric
Slavko Slavic
Sanja Sanjic
U primjeru iznad je prikazano ugnjeivanje kursora gdje prvi kursor prolazi kroz sve servise,
te za svaki dobiveni servis u prvom kursoru se dohvaaju retci, odnosno zaposlenici tog
servisa u drugom kursoru.
25
Rosenzweig B., Rakhimov E. (2009) Oracle PL/SQL by Example Fourth Edition, str.255.
31
8.2.3. UPDATE i DELETE redaka aktivnog seta kursora26
Do sada su obraeni kursori koji samo dohvaaju retke, ali postoje jo kursori koji se koriste
za promjenu ili brisanje redaka koji se nalaze u aktivnom setu kursora. Ako se e se kursor
koristiti za promjenu ili brisanje koristi se sljedea sintaksa27:
CURSOR ime_kursora
IS
select_naredba
FOR UPDATE [OF imena_stupaca] [NOWAIT];
Na kraju kursora se dodaje FOR UPDATE kljuna rije koja zakljuava retke na koje se
odnosi kursor, to znai da ostali korisnici ne mogu mijenjati te retke prije nego se izvri
promjena ili retci ne otkljuaju. Retci se otkljuavaju koritenjem kljune rijei COMMIT ili
ROLLBACK. Opcionalni dijelovi su jo kljuna rije OF iza koje se navode imena stupaca na
kojima e se izvoditi promjene. Ako se koristi vie tablica unutar SELECT naredbe kursora,
moe se navesti redak iz jedne koji se namjerava mjenjati te e se tada zakljuati samo ta
tablica dok e preostale tablice biti na raspolaganju drugim korisnicima. Ako se pokua
pristupiti retcima koji su ve zakljuani Oracle inae eka dok se ti retci ne oslobode. Ali ako
se navede kljuna rije NOWAIT, kontrola se vraa programu koji se izvodi kako bi nastavio
raditi prije nego opet proba pristupiti retcima.28
DECLARE
CURSOR c_zaposlenici (p_servis IN servis.id_servisa%TYPE) IS
SELECT *
FROM zaposlenik
WHERE servis_id_servisa = p_servis
FOR UPDATE OF placa_zap NOWAIT;
BEGIN
FOR r IN c_zaposlenici(2)
LOOP
UPDATE zaposlenik
SET placa_zap = r.placa_zap + 100
WHERE CURRENT OF c_zaposlenici;
END LOOP;
COMMIT;
END;
U primjeru iznad je koritena klauzula koja se koristi kada se mijenjaju ili briu retci koji se
nalaze u aktivnom setu kursora, a to je WHERE CURRENT OF koja pokazuje zadnje
26
Rosenzweig B., Rakhimov E. (2009) Oracle PL/SQL by Example Fourth Edition, str.258. 27
Tech On The Net (2014) - Oracle/ PLSQL, SELECT FOR UPDATE Statement, URL: http://www.techonthenet.com/oracle/cursors/for_update.php, dostupno 14.06.2014. 28
Oracle (2005) - Oracle Database PL/SQL Language Reference 10g Release 2, Using FOR UPDATE, URL: http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/sqloperations.htm#i3314, dostupno 14.06.2014.
32
dohvaeni redak kursora.29 Nakon izvrene promjene, odnosno poveanja plae zaposlenicima
servisa pod identifikatorom 2, promjene se predaju kljunom rijei COMMIT, nakon koje se
retci otkljuavaju. Moe se i cijela transakcija ponititi kljunom rijei ROLLBACK, te da je
ona umjesto COMMIT u ovom primjeru promjena se ne bi zapisala. Kod velikog broja redaka
koji se mjenjaju, programer moe definirati da se COMMIT izvrava svakih nekoliko tisua
redaka, tako da u sluaju greke ROLLBACK nije prevelik.
29
Tech On The Net (2014) - Oracle/ PLSQL, WHERE CURRENT OF Statement, URL: http://www.techonthenet.com/oracle/cursors/current_of.php, dostupno 14.06.2014.
33
9. Kolekcije30
Kolekcije u PL/SQL-u omoguavaju zapisivanje grupe elemenata istog tipa podataka, te
funkcioniraju kao polja u ostalim programskim jezicima. Svakom elementu kolekcije se
pristupa pomou indeksa, koji u PL/SQL-u zapoinju od broja 1 dok je u ostalim
programskim jezicima uobiajeno da indeksi zapoinju od broja 0. Kolekcije u PL/SQL-u se
djele na:
Asocijativni niz (eng. Associative Arrays) (jo poznato kao Index-By Tables)
Ugnjeene tablice (eng. Nested Tables)
Polja varijabilne duljine (eng. Variable-Size Arrays) (jo poznato kao Varrays)
9.1. Asocijativni niz31
Asocijativni niz je kolekcija koja se sastoji od kljua i vrijednosti, slino kao hash tablice u
ostalim programskim jezicima. Definira se sljedeom sintaksom:
TYPE ime_tipa IS TABLE OF tip_elementa [NOT NULL]
INDEX BY tip_elementa;
ime_tablice IME_TIPA;
Deklaracija se sastoji od dva koraka, gdje se u prvom koraku definira tip tablice. Odabere se
ime koje e se koristiti za taj tip i koje e se koristiti u drugom koraku kao tip podataka.
Nakon TABLE OF kljune rijei dolazi tip podataka za polja, odnosno vrijednosti koje e se
upisivati te se uz to moe definirati da li vrijednost moe biti null. Nakon kljune rijei
INDEX BY se odabire tip podataka za klju, odnosno tip podataka po kojem e se pretraivati
kolekcija i dobavljati vrijednosti. Moe se pretraivati po brojevima ili po znakovima. Drugi
korak je kao normalno deklariranje varijable, osim to se za tip podataka koristi ime tipa
deklarirano u prvom koraku.
DECLARE
CURSOR c_servis IS
SELECT * FROM servis;
TYPE servisi IS TABLE OF VARCHAR2(50)
INDEX BY BINARY_INTEGER;
tablica servisi;
BEGIN
FOR r IN c_servis LOOP
tablica(r.id_servisa) := r.adresa_servisa || ', ' || r.grad_servisa;
DBMS_OUTPUT.PUT_LINE('Vrijednost: ' || tablica(r.id_servisa));
END LOOP;
END;
30
Rosenzweig B., Rakhimov E. (2009) Oracle PL/SQL by Example Fourth Edition, str.315. 31
Rosenzweig B., Rakhimov E. (2009) Oracle PL/SQL by Example Fourth Edition, str.317.
34
Vrijednost: Ilica 58, Zagreb
Vrijednost: Radnika cesta 12, Zagreb Vrijednost: Ulica brae Radi 2, Varadin
U primjeru iznad je kreiran asocijativni niz pod imenom servisi, te kasnije varijabla tablica
koja ima taj tip. U tu varijablu su spremljene lokacije servisa dohvaene kursorom. Lokacije
su spremljene kao vrijednosti, dok im je klju identifikator koji se koristi u tablici. Odnosno
za red u tablici pod identifikatorom 2, odgovarajuu vrijednost u kolekciji nalazimo tako da ju
pretraujemo za klju 2 te dobivamo odgovarajuu lokaciju.
9.2. Ugnjeene tablice32
Ugnjeena tablica je kolekcija koja odgovara jednodimenzionalnom polju sa proizvoljnim
brojem elemenata. Definira se dva koraka, slino kao i asocijativni niz samo bez INDEX BY
kljune rijei jer e se elementima pristupati pomou indeksa koji je moe biti samo
cjelobrojna vrijednost. Sama definicija je dana sintaksom:
TYPE ime_tipa IS TABLE OF tip_elementa[NOT NULL];
ime_tablice IME_TIPA;
Razlikuje se od jednodimenzionalnog polja po tome to dinamiki poveava broj redaka dok
polje ima odreenu granicu. Uz to kod brisanja ugnjeene tablice ona postaje uplja,
odnosno ako se obrie polje na indeksu 5, ono e ostati prazno kao to vidimo na slici 5.
Slika 5. Razlika izmeu ugnjeene tablice i jednodimenzionalnog polja
33
No, postoje jo neke razlike s obzirom na asocijativni niz, a to je da kod drugog koraka
deklariranja e doi do greke ORA-06531: Reference to uninitialized collection jer se sama
kolekcija nije inicijalizirala, pa je dalje u kodu ona null. Kako bi se to izbjeglo koristi se
konstruktor kako bi se kreirala prazna kolekcija koja nije null. U konstruktoru se mogu
32
Rosenzweig B., Rakhimov E. (2009) Oracle PL/SQL by Example Fourth Edition, str.319. 33
Oracle (2009) - Oracle Database PL/SQL Language Reference 11g Release 1, Understanding Nested Tables, URL: http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/collections.htm#i24239, dostupno 14.06.2014.
35
pridjeliti i neke vrijednosti, ali kod same deklaracije je rijetka situacija da se one znaju, pa se
koristi prazni konstruktor kako je prikazano sljedeom sintaksom:
ime_varijable tip_podataka := tip_podataka()
I uz to prije svakog zapisivanja u kolekciju potrebno je proiriti njezinu veliinu, naredbom
ime_kolekcije.EXTEND kako je pokazano u sljedeem primjeru.
DECLARE
CURSOR c_servis IS
SELECT * FROM servis;
TYPE servisi IS TABLE OF servis.adresa_servisa%TYPE;
tablica servisi := servisi();
BEGIN
FOR r IN c_servis LOOP
tablica.EXTEND;
tablica(r.id_servisa) := r.adresa_servisa;
DBMS_OUTPUT.PUT_LINE('Vrijednost: ' || tablica(r.id_servisa));
END LOOP;
END;
Vrijednost: Ilica 58
Vrijednost: Radnika cesta 12 Vrijednost: Ulica brae Radi 2
9.3. Metode kolekcija34
Za rad s kolekcijama postoje metode koje se mogu koristiti, te je u prethodnom poglavlju
koitena jedna od njih EXTEND. Metode se koriste koristei sintaksu
ime_kolekcija.ime_metode
Metode za rad s kolekcijama su sljedee:
EXISTS metoda vraa TRUE ako postoji element pod tim indeksom
COUNT vraa ukupan broj elemenata kolekcije
EXTEND poveava veliinu kolekcije za jedno polje
DELETE metoda koja brie sve elemente kolekcije, elemente u nekom rasponu ili
odreeni element. Za napomenuti je da DELETE metoda ne obrie polja, nego samo
vrijednosti tih polja.
FIRST metoda koja vraa prvi indeks kolekciji
LAST metoda koja vraa zadnji indeks u kolekciji
PRIOR metoda vraa element koji se nalazi na indeksu koji se nalazi prije
proslijeenog indeksa
34
Rosenzweig B., Rakhimov E. (2009) Oracle PL/SQL by Example Fourth Edition, str.322.
36
NEXT metoda vraa element koji se nalazi na indeksu koji slijedi nakon
proslijeenog indeksa
TRIM metoda koja brie jedan ili vie elemenata s kraja liste, te ova metoda obrie
vrijednosti i polja
DECLARE
TYPE tip_kol IS TABLE OF NUMBER;
kolekcija tip_kol := tip_kol(2,3,4);
BEGIN
DBMS_OUTPUT.PUT_LINE('Zadnji indeks: ' || kolekcija.last());
FOR i IN 1 .. kolekcija.LAST() LOOP
DBMS_OUTPUT.PUT_LINE('Indeks ' || i ||': ' || kolekcija(i));
END LOOP;
kolekcija.TRIM(1);
DBMS_OUTPUT.PUT_LINE('Zadnji indeks: ' || kolekcija.last());
FOR i IN 1 .. kolekcija.LAST() LOOP
DBMS_OUTPUT.PUT_LINE('Indeks ' || i ||': ' || kolekcija(i));
END LOOP;
END;
Zadnji indeks: 3
Indeks 1: 2
Indeks 2: 3
Indeks 3: 4
Zadnji indeks: 2
Indeks 1: 2
Indeks 2: 3
Vano je za napomenuti da se metode TRIM i EXTEND ne mogu koristiti za asocijativne
nizove. U primjeru iznad metoda TRIM obrie zadnji element kolekcije. Kad se koristi
DELETE metoda moe se koristiti metoda bez parametara koja obrie sve elemente kolekcije,
DELETE(x) gdje je x indeks elementa koji se brie ili DELETE(x,y) gdje je su x i y raspon
indeksa koji se briu iz kolekcije.
9.4. Polja varijabilne duljine35
Polja varijabilne duljine su kolekcije koja su slina ugnjeenim tablicama, odnosno to je
jednodimenzionalno polje koje ima ogranien maksimalni broj elemenata kako je i prikazano
na slici 6.
35
Rosenzweig B., Rakhimov E. (2009) Oracle PL/SQL by Example Fourth Edition, str.334.
37
Slika 6. Polje varijabilne duljine
36
Polje varijabilne duljine ima poetni indeks koji poinje od 1 te se poveava za 1 sve do svoje
maksimalne veliine. To ogranienje se definira kod deklaracije kolekcije sljedeom
sintaksom:
TYPE ime_tipa IS {VARRAY | VARYING ARRAY} (maksimalna_veliina) OF tip_elemenata [NOT NULL];
ime_polja IME_TIPA;
Princip deklariranja je slian kao i kod ugnjeenih tablica te se odvija u dva koraka gdje prvo
definiramo tip polja,a u drugom ga inicijaliziramo. Te ponovno moramo koristiti konstruktor
kako kolekcija ne bi bila jednaka null nego prazna ili napunjena nekim inicijalnim
vrijednostima.
DECLARE
CURSOR c_servis IS
SELECT * FROM servis;
TYPE servisi IS VARRAY(10) OF servis.adresa_servisa%TYPE;
polje servisi := servisi();
BEGIN
FOR r IN c_servis LOOP
polje.EXTEND;
polje(r.id_servisa) := r.adresa_servisa;
END LOOP;
polje.TRIM(1);
FOR i in 1 .. polje.LAST() LOOP
DBMS_OUTPUT.PUT_LINE('Vrijednost: ' || polje(i));
END LOOP;
END;
Vrijednost: Ilica 58
Vrijednost: Radnika cesta 12
U gornjem primjeru smo koristili TRIM metodu za brisanje iz polja varijabilne duljine, iz
razloga to DELETE metoda ne radi jer je taj tip kolekcije je uzastopan te ne moe imati rupe
koje se uzrokuju tom metodom. Moe se koristiti samo DELETE() za micanje svih elemenata
kolekcije i metoda TRIM koja mie elemente s kraja kolekcije te tako ne uzrokuje rupe. Uz to
ovdje postoji i metoda LIMIT() koja vraa ogranienje tog tipa kolekcije.
36
Rosenzweig B., Rakhimov E. (2009) Oracle PL/SQL by Example Fourth Edition, str.334.
38
9.5. Vieslojne kolekcije37
Oracle omoguava kreiranje kolekcija koje za tip podataka imaju drugu kolekciju. Primjerice
se tako mogu definirati dvodimenzionalna polja, te je za pristupanje elementu tog polja
potreban indeks prvog i drugog polja isto kao i u ostalim programskim jezicima.
DECLARE
TYPE tip_1 IS VARRAY(2) OF INTEGER;
TYPE tip_2 IS VARRAY(2) OF tip_1;
v1 tip_1 := tip_1();
v2 tip_2 := tip_2();
BEGIN
v1 := tip_1(1,2);
v2.EXTEND;
v2(1) := v1;
v1 := tip_1(3,4);
v2.EXTEND;
v2(2) := v1;
FOR i IN 1 .. v2.LAST() LOOP
DBMS_OUTPUT.PUT_LINE('Vanjski element - ' || i);
FOR j IN 1 .. v2(i).LAST() LOOP
DBMS_OUTPUT.PUT_LINE('Element ('||i||','||j||') - '||v2(i)(j));
END LOOP;
END LOOP;
END;
Vanjski element - 1
Element (1,1) - 1
Element (1,2) - 2
Vanjski element - 2
Element (2,1) - 3
Element (2,2) - 4
U primjeru iznad je definirano v1 polje koje prima elemente tipa INTEGER, dok drugo polje
v2 prima elemente koji su tipa prvog definiranog polja v1. Zatim se inicijalizira prvo polje v1
s vrijednostima (1,2) te se to polje doda u drugo polje v2, te se isti postupak ponovi jo
jednom za vrijednosti (3,4). Nadalje se ispis svih elemenata odvija kroz dvije FOR petlje gdje
vanjska petlja prolazi kroz polje v2, a unutarnja petlja prolazi kroz elemente tog polja,
odnosno polja v1. Tako je drugi element polja v2, polje v1 s vrijednostima (3,4) gdje se
vrijednost 3 nalazi na lokaciji (2,1). U lokaciji (2,1), indeks 2 predstavlja drugi element polja
v2, a indeks 1 predstavlja prvi element u polju v1.
37
Oracle (2009) - Oracle Database PL/SQL Language Reference 11g Release 1, Using Multidimensional Collections, URL: http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/collections.htm#LNPLS00507, dostupno 14.06.2014.
39
10. Zapis38
Zapis (eng. Record) je kompozitna struktura podataka koja grupira logiki povezane podatke
pohranjene u polja, gdje svako polje ima svoje ime i tip podatak. Najblie je struct tipu
podataka u jezicima C i C++.39
PL/SQL omoguava deklariranje zapisa na tri naina:
zapis temeljen na tablici (eng. table-based record)
zapis temeljen na kursoru (eng. cursor-based record)
korisniki definiran zapis (eng. programmer-defined records)
Zapis temeljen na tablici se deklarira pomou %ROWTYPE atributa nad tablicom. Polja e
imati ista imena i tip podataka kao i stupci u odabranoj tablici.
DECLARE
table_based proizvodac%ROWTYPE;
BEGIN
SELECT * INTO table_based
FROM proizvodac where id_proizvodac = 4;
DBMS_OUTPUT.PUT_LINE('Proizvoa: ' || table_based.ime_proizvodac); END;
Proizvoa: Toshiba
Zapis temeljen na kursoru se takoer deklarira pomou %ROWTYPE atributa, ali nad
kursorom. Takva struktura podatak ima malo vie slobode jer nije ograniena na polja samo
jedne tablice ve na polja svih tablica koje deklariraju u SELECT upitu kursora.
DECLARE
CURSOR kursor IS
SELECT p.ime_proizvodac, count(*) AS broj FROM nalog n
JOIN proizvodac p ON p.id_proizvodac = n.proizvodac_id_proizvodac
WHERE p.id_proizvodac < 4 GROUP BY p.ime_proizvodac;
cursor_based kursor%ROWTYPE;
BEGIN
FOR r IN kursor LOOP
cursor_based := r;
DBMS_OUTPUT.PUT_LINE('Za proizvoaa: ' || cursor_based.ime_proizvodac || ' je zaprimljeno ' || cursor_based.broj || '
ureaja'); END LOOP;
END;
Za proizvoaa: Acer je zaprimljeno 263 ureaja
38
ZenTut (2014) - PL/SQL, PL/SQL Record, URL: http://www.zentut.com/plsql-tutorial/plsql-record, dostupno 14.06.2014. 39
Oracle (2005) - Oracle Database PL/SQL Language Reference 10g Release 2, Record Definition, URL: http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/record_definition.htm, dostupno 14.06.2014.
40
Za proizvoaa: Asus je zaprimljeno 402 ureaja Za proizvoaa: Hewlett-Packard je zaprimljeno 387 ureaja
Korisniki definiran zapis se deklarira u dva koraka. Prvo je potrebno definirati tip koristei
TYPE te unutar njega definirati sva polja koja e se koristiti, pomou sljedee sintakse:
TYPE ime_zapisa IS RECORD (deklaracija_polja[,deklaracija_polja]...);
Kod deklaracije samog polja mogu se koristiti varijable skalarnog tipa podataka, usidrenih
tipova podataka, podtipovi, kolekcije, kursori ak i drugi zapisi. Ovakav zapis nije ogranien
samo na polja koja se nalaze u tablici ili kursoru te tako omoguava kreiranje dodatnih
varijabli te njihovo povezivanje u logiku cjelinu. U drugom koraku se definira varijabla tog
istog tipa te se u nju zapisuju vrijednosti.
DECLARE
TYPE tip IS RECORD(
ime proizvodac.ime_proizvodac%TYPE,
broj NUMBER);
zapis tip;
BEGIN
SELECT p.ime_proizvodac, count(*)
INTO zapis FROM nalog n
JOIN proizvodac p ON p.id_proizvodac = n.proizvodac_id_proizvodac
WHERE p.id_proizvodac = 4 GROUP BY p.ime_proizvodac;
DBMS_OUTPUT.PUT_LINE('Za proizvoaa: ' || zapis.ime || ' je zaprimljeno ' || zapis.broj || ' ureaja');
END;
Za proizvoaa: Toshiba je zaprimljeno 367 ureaja
U gornjem primjeru je definiram tip podataka tip sa dva polja te varijabla tog tipa podataka. U
izvrnom dijelu bloka je pomou SELECT upita u varijablu zapisa upisano ime proizvoaa i
broj ureaja koji su zaprimljeni na servis. Za zapis se moraju spomenuti jo sljedee
mogunosti:
varijabla zapisa se moe upisati u drugu varijablu zapisa, pod uvjetom da imaju isti
broj polja i da su ona istog tipa podataka.
Zapis moe biti koriten kao parametar u funckiji
Zapis moe biti koriten kao izlazna vrijednost funkcije
Za provjeru da li je zapis null se moraju provjeriti sva njegova polja da li su null
Za usporedbu dva zapisa moraju se usporediti sva njegova polja pojedinano
41
11. Iznimke
U PL/SQL-u se mogu javiti dvije vrste iznimaka (eng. Exceptions) i to su iznimke koje se
javljaju kod kompajliranja samog koda i iznimke koje se javljaju kod izvoenja programa.
Iznimke kod kompajliranja se javljaju kad se pojavljuje pogreka u sintaksi. U ovom
poglavlju e se obraditi iznimke koje se javljaju kod izvoenja programa. Za takve iznimke
postoji poseban dio unutar PL/SQL bloka u kojem se one obrauju.40 Obrada podrazumijeva
naredbe koje se izvode u sluaju da doe do iznimke, te dio za obradu iznimaka izgleda kao:
EXCEPTION
WHEN ime_iznimke THEN
naredbe_za_izvriti_u_sluaju_greke
No za primjer prihvata i obrade jedne iznimke ispod je kod u kojem se upitom ne vraa ni
jedan redak za upis u varijablu. Zbog toga dolazi do iznimke NO_DATA_FOUND.
DECLARE
naziv VARCHAR2(20);
BEGIN
SELECT naziv_kvara INTO naziv
FROM kvar WHERE id_kvara = 30;
DBMS_OUTPUT.PUT_LINE('Kvar: ' || naziv);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Nema te kategorije kvara');
END;
Nema te kategorije kvara
No zato jer je kod pripremljen na mogunost da doe do te iznimke, on ga prihvaa i ispisuje
odgovarajuu poruku. Ovdje bi se primjerice mogao koristiti neki log u koji bi se upisivale
iznimke ili neka druga odgovarajua naredba. Da iznimka nije prihvaena, nakon nje bi se
kod prestao izvravati. Vano je za napomenuti da se nakon dijela za obradu iznimaka,
kontrola se ne vraa izvrnom dijelu nego blok zavrava. U PL/SQL-u postoje dvije vrste
iznimaka koje se mogu prihvatiti i obraditi:
ugraene iznimke (eng. Built-in Exceptions)
iznimke definirane od strane korisnika (eng. User-defined Exceptions)
40
Rosenzweig B., Rakhimov E. (2009) Oracle PL/SQL by Example Fourth Edition, str.165.
42
11.1. Ugraene iznimke
Oracle PL/SQL ima svoja pravila za koja se implicitno provjerava ispravnost tokom izvoenja
koda. Ako program prekri neko od tih pravila, implicitno se okida iznimka. Kod ugraenih
iznimaka zbog njihovog implicitnog okidanja, je potrebno samo definirati akcije koje se
izvravaju u tom sluaju. U prethodnom poglavlju je koritena iznimka NO_DATA_FOUND
koja se okida ako se ne vrati ni jedan redak. Takvih pravila ima vie te svako od njih ima
naziv koji se koristi na isti nain. Neke od PL/SQL ugraenih greaka su41:
ACCESS_INTO_NULL kada se null objektu dodjeljuje vrijednost
CASE_NOT_FOUND kada ni jedan WHEN u CASE selekciji nije odabran, a ne
postoji ELSE klauzula
COLLECTION_IS_NULL kada se pokua izvriti metoda kolekcije nad null
kolekcijom
CURSOR_ALREADY_OPEN kada se pokua otvoriti ve otvoreni kursor
DUP_VAL_ON_INDEX kod pokuavanja spremanja duplicirane vrijednosti u
kolumnu koja ima UNIQUE ogranienje nad sobom
INVALID_CURSOR kod nedoputenih operacija nad kursorom, primjerice
zatvaranje neotvorenog kursora
INVALID_NUMBER kod konverzije teksta u broj, ako tekst ne predstavlja ispravan
broj
LOGIN_DENIED kod pokuavanja spajanja na bazu s neispravnim imenom i
lozinkom
NO_DATA_FOUND kada SELECT naredba ne vrati ni jedan redak
NOT_LOGGED_ON kod poziva na bazu bez uspostavljene veze s bazom
PROGRAM_ERROR kod PL/SQL internih problema
ROWTYPE_MISMATCH kod FETCH-a iz kursora u varijablu nekomplatibilnog
tipa podataka
STORAGE_ERROR kod nedostatka ili greke u memoriji
TOO_MANY_ROWS kada SELECT INTO naredba vrati vie od jednog retka
VALUE_ERROR kod nedoputene operacije s varijablama, nedoputene konverzije
ili zapisivanja vrijednosti pogrene veliine
ZERO_DIVIDE kod pokuaja djeljenja s nulom
41
Oracle (2014) - Oracle Database PL/SQL Language Reference 11g Release 2, Predefined Exceptions, URL: http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/errors.htm#LNPLS00703, dostupno 14.06.2014.
43
11.2. Iznimke definirane od strane korisnika42
U svakom programu se mogu javiti specifine greke koje nisu pokrivene od strane PL/SQL-a
pa je tako potrebno definirati izminke koje se mogu pozivati u tim sluajevima. Isto kao i kod
ugraenih iznimaka, u dijelu za obradu iznimaka se definiraju akcije koje se izvravaju u tom
sluaju. Da se takva iznimka moe koristiti prvo se treba deklarirati u deklarativnom dijelu
PL/SQL bloka sljedeom sintaksom:
DECLARE
ime_iznimke EXCEPTION;
BEGIN
...
IF uvjet THEN
RAISE ime_iznimke;
END IF;
...
EXCEPTION
WHEN ime_iznimke THEN
naredbe_za_obradu_iznimaka
END;
Deklaracija iznimaka je veoma slina deklaraciji varijabli, samo to se nakon imena navodi
tip podataka nego kljuna rije EXCEPTION koja oznauje da se radi o iznimci. Uobiajena
praksa je za ime iznimke koristiti prefiks e_ kako bi se mogla razlikovati od ostalih varijabli.
Sljedei korak rada sa iznimkama definiranim od strane korisnika je okidanje same iznimke.
Za razliku od ugraenih iznimaka, ove je potrebno provjeriti da li je ispunjen uvjet za
okidanje iznimke. Ako je uvjet ispunjen, odnosno TRUE okinut e se iznimka kljunom rijei
RAISE te se ista prihvatiti u dijelu za obradu iznimaka.
DECLARE
broj_naloga NUMBER;
nema_prodaje EXCEPTION;
BEGIN
SELECT COUNT(*) INTO broj_naloga
FROM nalog WHERE zaposlenik_id_zap = 10;
IF broj_naloga = 0 THEN
RAISE nema_prodaje;
ELSE
UPDATE zaposlenik SET placa_zap = placa_zap * 1.1
WHERE id_zap = 10;
DBMS_OUTPUT.PUT_LINE('Plaa poveana'); END IF;
EXCEPTION
WHEN nema_prodaje THEN
UPDATE zaposlenik SET placa_zap = placa_zap * 0.9
WHERE id_zap = 10;
42
Rosenzweig B., Rakhimov E. (2009) Oracle PL/SQL by Example Fourth Edition, str.188.
44
DBMS_OUTPUT.PUT_LINE('Plaa smanjena'); WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Dolo je do greke'); END;
Plaa smanjena
Za potrebe gornjeg primjera u bazu je dodan novi zaposlenik koji nema ni jedan obraeni
nalog. Iz baze se za tog zaposlenika vadi broj obraenih naloga te ako nema ni jedan nalog,
dolazi do smanjenja plae. Odnosno ako je broj naloga 0, dolazi do okidanja iznimke koja
pokree naredbu koja smanjuje plau tom zaposleniku.
Vano je ovdje napomenuti jo nekoliko stvari, a to je da SELECT upiti s grupnim
funkcijama kao COUNT, MAX, SUM iako nema ni jednog retka ne okidaju ugraenu
iznimku NO_DATA_FOUND jer oni vraaju 0. Ovdje je meu iznimkama koritena iznimka
OTHERS koja prima sve iznimke koje nisu specifino definirane da budu prihvaene.43 to je
dobra praksa za ukljuiti u svaki PL/SQL blok, kako bi se osigurali od neoekivanih greaka.
DECLARE
radnik zaposlenik%ROWTYPE;
BEGIN
SELECT * INTO radnik
FROM zaposlenik WHERE id_zap = 11;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Greka '||SQLCODE||' - '||SQLERRM); END;
Greka 100 - ORA-01403: no data found
U primjeru iznad je kod dohvata zaposlenika dohvaeno 0 redaka odnosno okinuta je iznimka