Baze Podataka 2

May 7, 2017 | Author: Student | Category: N/A
Share Embed Donate


Short Description

Download Baze Podataka 2...

Description

VISOKA ŠKOLA ZA EKONOMIJU I INFORMATIKU PRIJEDOR

Boris Damjanović

BAZE PODATAKA II

Prijedor, 2011.god.

2

SADRŽAJ: 1

Uvod u relacioni model ....................................................................................................... 7 1.1 Relacije i relacione varijable...................................................................................... 11 1.2 Formalnija definicija relacije ..................................................................................... 12 1.3 Tabele ........................................................................................................................ 14 1.4 Slogovi, redovi i n-torke nasuprot kolona, atributa i polja ........................................ 14 1.5 Tabela i relacija ......................................................................................................... 15 1.6 Struktura relacionog modela...................................................................................... 15 1.6.1 Domeni relacije ................................................................................................... 18 1.6.2 Ključevi relacije .................................................................................................. 18 1.6.3 Šema relacione baze i relaciona baza podataka................................................... 19 1.7 Relaciona algebra....................................................................................................... 21 1.7.1 Konvencionalne skupovne operacije u relacionoj algebri ................................... 21 1.7.2 Specijalne relacione operacije ............................................................................. 23 1.7.3 Operacije održavanja baze podataka ................................................................... 26 1.7.4 Operacije sa nula vrijednostima .......................................................................... 27 2 Normalne forme – projktovanje relacija normalizacijom .................................................. 29 2.1 Funkcionalne zavisnosti - osnovne definicije i terminologija.................................... 30 2.2 Dekompozicija relacija bez gubljenja informacija..................................................... 32 2.3 Druga i Treća normalna forma................................................................................... 34 2.4 Boyce-Codd-ova normalna forma (BCNF) ............................................................... 37 2.5 Dekompozicija na zavisne i nezavisne projekcije...................................................... 38 2.6 Višenačne zavisnosti i Četvrta normalna forma ........................................................ 40 2.7 Zavisnosti spajanja i Peta normalna forma (5NF) ..................................................... 43 2.8 Normalna forma ključeva i domena........................................................................... 44 3 SQL (Structured Query Language).................................................................................... 46 3.1 Oracle Express DBMS - Instalacija i alati za administraciju ..................................... 47 3.2 Firebird DBMS - Instalacija i alati za administraciju ................................................ 49 3.3 Kreiranje i modifikacija tabela .................................................................................. 56 3.3.1 Uvod u kreiranje SQL tabela............................................................................... 56 3.3.1.1 Najčešće korišteni tipovi podataka ............................................................ 56 3.3.1.2 Kreiranje tabela – Nula (NULL) vrijednosti.............................................. 62 3.3.1.3 Kreiranje tabela – podrazumjevana (default) vrijednost kolone ................ 63 3.3.2 Mijenjanje strukture SQL tabela ......................................................................... 65 3.3.2.1 Dodavanje nove kolone postojećoj tabeli .................................................. 65 3.3.2.2 Modifikacija tipa kolone ............................................................................ 67 3.3.2.3 Uklanjanje podrazumjevane vrijednosti kolone......................................... 67 3.3.2.4 Uklanjanje kolone ...................................................................................... 67 3.3.2.5 Uklanjanje definicije tabele ....................................................................... 68 3.4 Uvod u SQL ograničenja ........................................................................................... 69 3.4.1 Ograničenje NOT NULL..................................................................................... 69 3.4.2 Ograničenje UNIQUE ......................................................................................... 70 3.4.3 Ograničenje PRIMARY KEY ............................................................................. 74 3.4.4 Ograničenje FOREIGN KEY .............................................................................. 78 3.4.5 Ograničenje CHECK........................................................................................... 82 3.5 Uvod u upite za preuzimanje podataka...................................................................... 84 3.5.1 Članovi (klauzule) SELECT i FROM ................................................................. 84 3.5.2 Upotreba člana (klauzule) WHERE .................................................................... 87 3.5.3 Upotreba člana (klauzule) GROUP BY............................................................... 90 3.5.4 Upotreba člana (klauzule) HAVING................................................................... 95 3.5.5 Upotreba člana (klauzule) ORDER BY i sortiranje rezultata.............................. 96 3.6 Upiti za modifikaciju podataka u tabelama................................................................ 98 3.6.1 Iskaz INSERT ..................................................................................................... 98

3

3.6.2 Iskaz UPDATE .................................................................................................. 101 3.6.3 Iskaz DELETE................................................................................................... 104 3.7 Upotreba SQL predikata .......................................................................................... 107 3.7.1 Prioritet operatora .............................................................................................. 107 3.7.2 Operator sastavljanja - || (concatention)............................................................. 107 3.7.3 Aritmetički operatori.......................................................................................... 108 3.7.4 Poređenje podataka ............................................................................................ 109 3.7.5 Operator BETWEEN ......................................................................................... 111 3.7.6 Operatori STARTING WITH, CONTAINING i LIKE ..................................... 111 3.7.6.1 Operator STARTING WITH.................................................................... 112 3.7.6.2 Operator CONTAINING.......................................................................... 112 3.7.6.3 Operator LIKE ......................................................................................... 113 3.7.7 Operator IN........................................................................................................ 115 3.7.8 IS [NOT] NULL predikat .................................................................................. 116 3.7.9 EXISTS predikat................................................................................................ 117 3.7.10 SOME i ANY predikati................................................................................. 118 3.7.11 ALL predikat................................................................................................. 120 3.7.12 Logički operatori........................................................................................... 121 3.8 Rad sa funkcijama i vrijednosnim izrazima ............................................................. 123 3.8.1 Agregatne funkcije COUNT, MIN, MAX, SUM i AVG................................... 123 3.8.2 Funkcije za konverziju podataka – CAST i EXTRACT .................................... 127 3.8.3 Funkcije za rad sa stringovima – SUBSTR ili SUBSTRING i UPPER............. 131 3.8.4 CREATE SEQUENCE iskaz............................................................................. 134 3.8.5 Ostale funkcije ................................................................................................... 137 3.9 Postavljanje upita nad više tabela............................................................................. 139 3.9.1 Dekartov proizvod i Ekvi-spajanje ................................................................... 140 3.9.1.1 Ekvi-spajanje više od dvije tabele ............................................................ 144 3.9.1.2 Ekvi-spajanje pomoću ključnih riječi CROSS JOIN................................ 144 3.9.1.3 Upit tipa SELF JOIN................................................................................ 145 3.9.1.4 Ekvi-spajanje pomoću ključnih riječi NATURAL JOIN i USING .......... 146 3.9.2 Unutrašnje i spoljno spajanje............................................................................. 147 3.9.2.1 Upit tipa INNER JOIN............................................................................. 147 3.9.2.2 Upit tipa OUTER JOIN............................................................................ 149 3.9.2.3 Upiti tipa UNION..................................................................................... 154 3.9.3 Podupiti (ugnježdeni upiti) ................................................................................ 155 3.10 Indeksi...................................................................................................................... 158 3.10.1 Automatski i korisnički definisani indeksi.................................................... 159 3.10.2 Plan izvođenja upita ...................................................................................... 162 3.10.3 Kada indeksi mogu pomoći........................................................................... 166 3.10.4 Pogledi (Views) ............................................................................................ 169 3.10.5 Kreiranje SQL rutina – Stored procedure i Trigeri ....................................... 173 3.10.5.1 Stored procedure ...................................................................................... 173 3.10.5.2 Oracle stored procedure ........................................................................... 173 3.10.5.3 Firebird stored procedure ......................................................................... 181 3.10.6 Trigeri (triggers)............................................................................................ 190 3.10.6.1 Oracle trigeri ............................................................................................ 190 3.10.6.2 Firebird trigeri .......................................................................................... 197 3.10.7 Upravljanje greškama ................................................................................... 204 3.10.7.1 Firebird Exceptions .................................................................................. 204 4 Upravljanje izvršenjem transakcija .................................................................................. 209 4.1 Osobine transakcija .................................................................................................. 210 4.1.1 Potreba za izolacijom transakcija....................................................................... 211 4.1.2 Implementacija COMMIT i ROLLBACK naredbi............................................ 211

4

4.1.3 Konkurentna i serijska obrada transakcija......................................................... 212 4.1.3.1 Problemi i anomalije pri konkurentnoj obradi transakcija ....................... 212 4.1.3.2 Konkurentna (uporedna) obrada transakcija ............................................ 213 4.1.3.3 Serijska obrada transakcija ...................................................................... 214 4.1.3.4 Protokoli za ostvarivanje serijabilnosti izvršenja skupa transakcija ........ 215 View - serijabilnost.................................................................................................. 216 4.1.3.5 Konflikt-serijabilnost ............................................................................... 217 4.1.3.6 Graf prethođenja i konflikt serijabilnost .................................................. 219 4.1.4 Protokoli zaključavanja ..................................................................................... 220 4.1.4.1 Dvofazni protokol zaključavanja ............................................................. 224 4.1.5 Nivoi izolovanosti transakcija ........................................................................... 227 Granularnost zaključavanja i hijerarhijsko zaključavanje........................................ 227 4.1.6 Oracle nivoi izolacije......................................................................................... 228 4.1.7 Firebirdovi nivoi izolacije ................................................................................. 231 4.1.7.1 READ COMMITTED nivo izolacije....................................................... 231 4.1.7.2 SNAPSHOT (Concurrency)..................................................................... 232 4.1.7.3 SNAPSHOT TABLE STABILITY (Consistency) .................................. 232 5 Napredni SQL tipovi podataka ........................................................................................ 233 5.1 Predefinisani tipovi podataka................................................................................... 233 5.1.1 Tekstualni nizovi podataka (Stringovi) ............................................................. 233 5.1.2 Skupovi karaktera i sortiranje............................................................................ 235 5.1.3 Binarni nizovi podataka..................................................................................... 236 5.1.4 Numerički tipovi podataka ................................................................................ 238 5.1.4.1 Egzaktni (tačni) tipovi podataka .............................................................. 238 5.1.4.2 Približni (approximate) tipovi podataka .................................................. 241 5.1.5 Predstavljanje datuma i vremena....................................................................... 241 5.1.6 Domeni - Konstruisani tipovi podataka............................................................. 242 5.1.7 Korisnički definisani tipovi podataka................................................................ 243 6 Literatura ......................................................................................................................... 244

5

6

1

Uvod u relacioni model

SQL sistemi danas dominiraju na DBMS tržištu, a jedan on najvažnijih razloga za to je da su takvi sistemi bazirani na relacionom modelu podataka. Pored toga, većina naučnih istraživanja tokom posljednjih 40 godina su bila bazirana (ponekad i indirektno) na relacionom modelu. Od svog predstavljanja 1969. godine (E.F.Codd), relacioni model predstavlja najvažniji događaj u razvoju baza podataka. Činjenica je da relacioni model ima najčvršću podlogu u logici i matematici i stoga osigurava idealno sredstvo za nastavu i učenje temelja i principa vezanih za baze podataka. U ovako ranoj fazi knjige, moguće je dati samo približan odgovor na pitanje šta je relacioni sistem. Slobodnije (i vrlo usko) tumačenje bilo bi: •

Podaci se korisniku predstavljaju preko tabela (i samo preko tabela)



Operatori koje korisnik ima na raspolaganju za npr. preuizimanje podataka, izvode „nove“ tabele iz „starih“ tabela. Npr. korisnicima na raspolaganju stoji operator restrikcije (u literaturi se često naziva i operator selekcije), koji je u stanju da izdvoji podskup redova neke tabele. Takođe, korisnici imaju na raspolaganju još jedan operator, koji se naziva projekcija, koji je u stanju da izdvoji podskup kolona neke tabele. Kako ćemo uskoro vidjeti, oba rezultirajuća podskupa – i podskup kolona i podskup redova se mogu posmatrati kao 1 tabele.

Ovakvi sistemi se nazivaju relacionim sistemima jer je relacija jednostavno matematički 2 izraz za tabelu . U stvari, termini relacija, tabela i ponekad relaciona tabela često se koriste kao sinonimi. Naravno, moramo voditi računa i o činjenici da u drugim modelima, poput ER (Entity Relationship) modela, riječ relacija može imati sasvim drugo značenje. Da bi ilustrovali predstavljanje podataka pomoću tabela, pogledaćemo sliku 1. Prikazani podaci su smješteni u jednu tabelu, koju smo nazvali VINSKI_PODRUM. Tabela: VINSKI_PODRUM: VINO

GODINA KOL_BOCA

Zinfandel 1999 2 Funic Blanc 2000 2 Pinot Noir 1997 3 Zinfandel 1998 9 Slika 1: Tabela VINSKI_PODRUM Nad ovakvim podacima ćemo primjeniti dva ranije navedena operatora restrikciju i projekciju. Restikcija, odnosno selekcija prikazana je na slici 2. Restrikcija: SELECT VINO, GODINA, KOL_BOCA FROM VINSKI_PODRUM WHERE GODINA > 1998 ; Rezultat: VINO

GODINA KOL_BOCA

Zinfandel

1999

1 2

2

C.J.Date, Introduction to database systhems, 8th edition C.J.Date, Introduction to database systhems, 8th edition

7

Funic Blanc 2000 2 Slika 2: Operator restrikcije (selekcije) Vidljivo je da je operator restrikcije iz kompletnog skupa podataka izdvojio redove koji zadovoljavaju navedeni uslov (vina proizvedena nakon 1998. godine). Još važnije je da je rezultat ovakve operacije ponovo prestavljen kao tabela. Na slici 3. vidljiv je način djelovanja operatora projekcije, koji je kombinovan sa selekcijom: Projekcija (sa selekcijom) SELECT VINO, KOL_BOCA FROM VINSKI_PODRUM ; Rezultat: VINO

KOL_BOCA

Zinfandel 2 Funic Blanc 2 Pinot Noir 3 Zinfandel 9 Slika 3: Operator projekcije Operator projekcije (u primjeru kombinovan sa operatorom selekcije) izdvaja tražene kolone (VINO, KOL_BOCA) iz tabele VINSKI_PODRUM i prikazuje ih ponovo u formi tabele. Bitno je primjetiti da djelovanjem navedenih operatora podaci u originalnoj tabeli neće biti izmjenjeni – navedena dva operatora samo nam predstavljaju odgovarajući podskup originalnog skupa podataka. Kako smo već rekli, u relacionom sistemu, korisnik vidi tabele i ništa drugo osim tabela. U nekom ne-relacionom sistemu, korisnik bi mogao vidjeti i ostale strukture podataka umjesto tabela ili pored njih. Te ostale strukture zahtjevaju dodatne operatore da bi im pristupili. Npr. u hijerarhijskom sistemu kakav je IBM-ov Information Management System (IMS), podaci su korisniku predstavljeni u formi drveta (tree). Korisnici moraju da koriste određene operatore da bi pristupili takvim podacima, da koriste odgovarajuće pointere (pokazivače) pomoću kojih se kreću gore-dole po nekom drvetu itd. Iz prethodno rečenog, može se zaključiti da se različiti sistemi (modeli) podataka mogu kategorisati prema strukturama podataka i operatorima koji će biti vidljivi korisniku. Za relacioni model kaže se da ima slijedeća tri aspekta: 1. Aspekt strukture: Podaci u tabelama su korisnicima predstavljeni pomoću tabela (i samo pomoću tabela); 2. Aspekt Integriteta: Ove tabele zadovoljavaju određena pravila integriteta; 3. Aspekt manipulacije: Operatori koji korisnicima stoje na raspolaganju za manipulisanje tim tabelama izvode tabele iz tabela. Na slici je data jednostavna baza podataka pod imenom Odjeljenja_Radnici. Kako je sa slike vidljivo, baza podataka je zaista predstavljena pomoću tabela. Odjeljenja_Radnici ODJELJENJA ODJ# IME_ODJ O1 O2 O3

8

BUDZET

Marketing 10M Razvoj 12M Istraživanje 5M

RADNICI RAD# IME_RAD ODJ# ZARADA R1 IVAN O1 40k R2 ANA O1 42k R3 ZORAN O2 30k R4 BOJAN O2 35k Slika 4: Baza podataka Odjeljenja_Radnici Slijedeća slika prikazuje rezultate primjene operatora restrikcije, projekcije i spajanja (Join) nad ovakvom bazom podataka. Restrikcija:

Rezultat:

Odjeljenja gdje je BUDZET > 8M

BUDGET ODJ# IME_ODJ O1 Marketing 10M O2 Istraživanje 12M Rezultat:

Projekcija: Odjeljenja preko polja ODJ#, BUDZET

ODJ# O1 O2 O3

BUDZET 10M 12M 5M

Spajanje: ODJELJENJA i RADNICI preko ODJELJENJA (ODJ#) Rezultat: ODJ # IME_ODJ BUDZET RAD# IME_RAD ZARADA O1 Marketing 10M R1 IVAN 40K O1 Marketing 10M R2 ANA 42K O2 Istraživanje 12M R3 ZORAN 30K O2 Istraživanje 12M R4 BOJAN 35K Slika 5: Restrikcija, projekcija i spajanje Određeni red iz tabele ODJELJENJA će biti spojen sa nekim redom iz tabele RADNICI samo ako ta dva reda imaju istu vrijednost u koloni ODJ#. Npr. redovi: ODJ# IME_ODJ

BUDZET

RAD# IME_RAD ODJ# ZARADA

O1 Marketing 10M R1 IVAN O1 40k Slika 6: Spajanje dvije tabele će biti spojeni na osnovu identične vrijednosti (O1) koja se nalazi u obje tabele u koloni ODJ# u : ODJ# IME_ODJ BUDZET RAD# IME_RAD ZARADA O1 Marketing 10M R1 IVAN 40K Slika 7: Rezultat spajanja

9

Treba primjetiti da se kolone zajedničke za obje tabele (ODJ#) pojavljuju samo jednom u rezultirajućoj tabeli. Rezultat ovakvog spajanja (join) sadržavaće sve moguće redove koji mogu biti dobijeni na ovakav način. Treba primjetiti i da ni jedan radnik iz tabele RADNICI nema u koloni ODJ# vrijednost D3 – znači da ni jedan radnik trenutno nije dodjeljen tom odjeljenju. Zbog toga se u rezultatu spajanja odjeljenje D3 ne pojavljuje ni jednom, iako ono postoji u tabeli ODJELJENJA. Prethodna diskusija jasno pokazuje da je rezultat svake od prikazanih operacija nad tabelama neka nova tabela – operatori zaista izvode tabele iz tabela. Ovo je veoma važna osobina relacionih sistema. Pošto je izlaz iz neke operacije objekat iste vrste kao i onaj na ulazu (svi su tabele), ova osobina nam daje mogućnost da izlaz iz jedne operacije postane ulaz u neku drugu operaciju. Ovo nam daje mogućnost da npr. uzmemo projekciju od rezultata spajanja ili da spojimo dvije restrikcije. Drugim riječima, moguće je pisati ugnježdene (nested) relacione izraze, odnosno izraze čiji su argumenti neki drugi relacioni izrazi, a ne samo imena tabela. Kada kažemo da je izlaz neke prikazane operacije tabela, važno je shvatiti da je to ispravno sa konceptualne tačke gledišta. Ovo ne znači da sistem treba da materijalizuje rezultat svake individualne operacije. Relacioni model je samo model – on nema ništa sa načinom implementacije pojedinih operacija. Na primjer, pretpostavimo da ćemo pokušati da izračunamo restrikciju od nekog spajanja (join). Čim se neki red operacije spajanja formira, sistem može takav red odmah da testira da bi utvrdio da li on pripada finalnom rezultatu restrikcije ida po potrebi odbaci takav red. Dakle, međurezultat koji je nastao spajanjem (join) možda nikada neće biti formiran kao kompletna tabela. Sistem će, radi performansi, pokušati da izvrši navedene dvije operacije bez materijalizacije međurezultata. Ovakva strategija izračunavanja (implementacija), tokom koje se međurezultati daju slijedećoj operaciji dio po dio naziva se cjevovod (pipelined evaluation). Ako se međurezultati materijalizuju, takav način izračunavanja naziva se materijalizovana evaluacija. Da ne bude zabune, sve prikazane operacije na svom izlazu daju skupove redova, odnosno tabele (a ne redove). Svaka rezultirajuća tabela može sadržavati skup redova, samo jedan red ili niti jedan red – sve su to regularni rezultati. Npr. operacija spajanja (join) sa slike 5 operiše nad tabelama koje imaju tri i četiri reda svaka, a vraća rezultirajuću tabelu koja se sastoji od četiri reda. Za razliku od relacionog modela, nerelacioni sistemi tipično obrađuju podatke na nivou reda ili sloga. Konceptualni pristup obradi podataka je osnovna razlika između relacionih i ne-relacionih sistema. Ako se na trenutak vratimo na sliku 4, koja prikazuje tabele ODJELJENJA i RADNICI, možemo iznijeti još par dodatnih zapažanja:

10



Relacioni sistemi zahtjevaju samo da baza podataka korisniku bude predstavljena u vidu tabela. Tabele su u relacionom modelu logička struktura – ne fizička. Na fizičkom nivou, proizvođači sistema su slobodni da smještaju podatke na način koji im odgovara – korištenjem sekvencijalnih datoteka, indeksiranjem, heširanjem, nizovima pointera, kompresijom ili korištenjem bilo kog drugog načina koji im odgovara – dok god su u stanju da preusmjere tako sačuvane podatke u tabele na logičkom nivou. Drugim riječima, tabele su apstraktan način predstavljanja fizički sačuvanih podataka. Na ovaj način, od korisnika su sakriveni detalji implementacije – način smještanja slogova (recodrs) i njihov redoslijed, strukture koje ubrzavaju pristup (popud indeksa) isl. i svi oni se mogu razlikovati od implementacije do implementacije.



Relacione baze podataka se pridružavaju informacionog principa „The Information Principle“ – cjelokupan informacioni sadržaj baze podataka se predstavlja samo na jedan način i to kao eksplicitne vrijednosti na

3

pozicijama kolona i redova tabele. Ovaj metod je jedini metod koji se koristi za predstavljanje podataka na logičkom nivou u nekom relacionom sistemu. Ako nam je potrebno da povežemo dvije (ili više) tabela, to nećemo uraditi npr. pokazivačima (pointerima), već vrijednostima koje se nalaze u odgovarajućim kolonama tabela. U primjeru koji je prikazan na slici 5, tabele RADNICI i ODJELJENJA su povezane pomoću vrijednosti koje se nalaze u odgovarajućim kolonama ODJ# u obje tabele. U ne-relacionim sistemima kakav je ranije pomenuti IMS, ovakva veza nekom vrstom pokazivača koja je eksplicitno vidljiva korisniku. Ovim bi mogli zaokružiti strukturalni i manipulativni dio izlaganja o relacionom modelu. Da bi objasnili aspekt integriteta, ponovo ćemo se vratiti na sliku 5 koja opisuje bazu podataka Odjeljenja_Radnici. U praksi, ovakva baza podataka potencijalno bi morala da zadovolji veći broj različitih ograničenja – npr. budžeti dodjeljeni odjeljenjima moraju biti od 1M-1.5M, plate radnika moraju biti između 25k i 95k itd. Međutim, postoje i posebna ograničenja, koja imaju mnogo veći značaj: •

Svaki red u tabeli ODJELJENJA mora imati jedinstvenu vrijednost u koloni ODJ# dok svaki red u tabeli RADNICI mora imati jedinstvenu vrijednost i koloni RAD#. Mogli bi, pojednostavljeno reći da svaka stavka u koloni ODJ# predstavlja primarni ključ tabele ODJELJENJA i da svaka stavka u koloni RAD# predstavlja primarni kjuč tabele RADNICI.



U tabeli RADNICI nalazi se i kolona ODJ# koja istovremeno mora postojati i u tabeli ODJELJENJA, da bi opisala činjenicu da svaki radnik mora biti raspoređen u neko odjeljenje. Ponovo bi mogli reći da kolona ODJ# koja se nalazi u tabeli RADNICI predstavlja spoljni ključ koji dalje upućuje na primarni ključ tabele ODJELJENJA.

1.1

Relacije i relacione varijable

Već smo spominjali da je relacija u stvari matematički izraz za tabelu ali, kako ćemo vidjeti, tabelu posebne vrste. Zbog toga bi mogli reći da se u bazi Odjeljenja_Radnici nalaze dvije relacije: ODJELJENJA i RADNICI. 1968. godine, u doba kada je E.F.Codd shvatio da teorija skupova i predikatska logika mogu da budu iskorištene da se oblasti upravljanja bazama podataka dodaju solidne teoretske osnove, u IT krugovima su korišteni dosta zamagljeni i često neprecizni termini koji su opisivali navedenu oblast. Na primjer, termin slog (record) ponekad je korišten da bi se opisale vrijednosti koje se u datom slogu pojavljuju, tipovi podataka u tom slogu, logički i fizički slog (zapis) itd. Relacioni model zbog toga ne koristi termin slog (record) – umjesto njega koristi termin n-torka (tuple). Za sada ćemo usvojiti da termin n-torka približno odgovara terminu red (kao što smo usvojili da termin relacija približno odgovara tabeli). Relacioni model takođe ne koristi termin polje (field) već umjesto njega koristi termin atribut, za kojeg ćemo, za sada, usvojiti konvenciju da on približno odgovara nekoj koloni tabele. Da bi istakli još jednu važnu osobinu relacionog modela, ponovo ćemo se vratiti na bazu podataka Odjeljenja_Radnici prikazanu na slici 4. ODJELJENJA i RADNICI koji su prikazani na slici u stvari predstavljaju relacione varijable, koje u određenim trenucima vremena imaju određene vrijednosti. Pretpostavimo da trenutno relaciona varijabla

3

http://alas.matf.bg.ac.rs/~mi06085/zadatak1.html

11

RADNICI ima relacionu vrijednost prikazanu na slici 4, i da obrišemo (delete) pojavljivanje n-torke (reda) R4 (Bojan). DELETE EMP WHERE EMP# = 'R4' ; Rezultat ove operacije prikazan je na slijedećoj slici: RADNICI RAD# IME_RAD ODJ# ZARADA R1 IVAN O1 40k R2 ANA O1 42k R3 ZORAN O2 30k Slika 8: Relaciona vrijednost (relacija) RADNICI nakon brisanja Mogli bi reći da je kompletna stara relaciona vrijednost zamjenjena novom vrijednošću. 4 Operacija brisanja mogla bi se prikazati pomoću operatora dodjele vrijednosti RADNICI := RADNICI WHERE NOT ( RAD# = 'R4' ) ; Slika 9: Relacionoj varijabli RADNICI dodjeljujemo vrijednost izraza Kao i pri bilo kojoj dodjeli vrijednosti, ono što se zaista dešava je da se najprije izračuna izraz na desnoj strani, a zatim se dobijeni rezultat dodjeli varijabli na lijevoj strani. Na sličan način, pomoću operatora dodjele vrijednosti mogli bi opisati i relacione operacije INSERT i UPDATE, za umetanje nove n-torke i izmjenu postojeće. Zbog svega navedenog, uvešćemo i konvenciju kojom ćemo pokušati da odvojimo termine relacija odnosno relaciona vrijednost kakva je prikazana na slici 8 od termina relaciona varijabla, kakvu koristimo u prethodno prikazanoj formuli na slici 9. Bilo koju relacionu varijablu ćemo skraćeno nazivati relvar.

1.2

Formalnija definicija relacije

Može se reći da se relacioni model sastoji od slijedećih 5 komponentata: 1. otvorenog skupa skalarnih tipova (koji uključuje i tip logičkih vrijednosti boolean) – tipovi podataka, 2. generatora relacionih tipova i njihove odgovarajuće interpretacije – izvedeni tipovi, 3. mogućnosti definisanja relacionih promjenjivih za generisane relacione tipove – definisanje tabela, 4. operacije relacione dodjele kojom se dodjeljuju relacione vrijednosti definisanim relacionim promjenjivim – dodjela vrijednosti promjenjivim, 5. otvorenog skupa opštih relacionih operatora ("relaciona algebra") za izvođenje relacionih vrijednosti iz drugih relacionih vrijednosti. Ako obratimo pažnju na prvu komponentu (otvoreni skup tipova), činjenica da je ovakav skup otvoren znači da će korisnici biti u stanju i da definišu vlastite tipove podataka, kao i da koriste sistemski obezbjeđene (ugrađene) tipove podataka. Ako bi predstavili atribute i njima odgovarajuće tipove, imali bi: Type RAD_ID RAD# ; Type IMENA IME_RAD ; itd. Slika 10: Tipovi atributa 4

Operator dodjele vrijednosti (:=) treba razlikovati od znaka jednakosti

12

Zbog toga, tip podatka RAD# možemo posmatrati kao skup svih mogućih šifara zaposlenih (domen), tip IME_RAD kao skup svih mogućih imena zaposlenih itd. Zbog toga se svaki atribut relacije može predstaviti iz dva dijela: 1. Naziv-kolone:Tip (u zaglavlju) 2. Skup redova koji zadovoljavaju takvo zaglavlje. Iako u praksi često ignorišemo dio koji se odnosi na tip podatka, treba imati u vidu da je on uvjek tu. RAD# : RAD# IME_RAD : IMENA ODJ# : ODJ# ZARADA : NOVAC R1 IVAN O1 40k R2 ANA O1 42k R3 ZORAN O2 30k R4 BOJAN O2 35k Slika 11: Relacija sa prikazanim tipovima podataka Ono što je veoma važno i što se mora primjetiti je da se zaglavlje neke relacije može posmatrati kao iskaz (predikat), a svaki iskaz može da bude istinit ili neistinit. Ako ponovo pogledamo relacionu vrijednost RADNIK koja je data na slici 4, primjetićemo da se svaka n-torka (red) može posmatrati kao iskaz (predikat): Zaposleni RAD# koji se zove IME_RAD radi u odjeljenju ODJ# i zarađuje ZARADA. Slika 12: Iskaz Parametri ovog iskaza (ili njegovi ulazni argumenti, ako ga posmatramo kao funkciju) su RAD#, IME_RAD, ODJ#, ZARADA. Iskaz koji daje tačnu vrijednost nastao bi uvrštavanjem četvorke (R1, IVAN, O1, 40K) kao parametara ovog iskaza: Zaposleni R1 koji se zove IVAN radi u odjeljenju O1 i zarađuje 40K. RAD# IME_RAD ODJ# ZARADA R1 IVAN O1 40k ... ... ... ... Slika 13: Tačan iskaz i relacija iz koje je nastao Ako svaka n-torku u prikazanoj tabeli posmatramo kao iskaz, takav iskaz će sigurno biti tačan. Međutim, ako posmatramo ranije prikazanu operaciju spajanja relacija RADNICI i ODLJELJENJA preko ODJENJENJA(ODJ#), vidićemo da ne mora svaki rezultirajući iskaz biti istinit. Kako ni jedan radnik još uvjek nije dodjeljen odjeljenju (O3, Istraživanje), pokušaj spajanja bilo kog radnika sa navedenim odjeljenjem doveo bi do netačnog iskaza: ODJELJENJA ODJ# IME_ODJ O3

RADNICI BUDZET

Istraživanje 5M

RAD# IME_RAD ODJ# ZARADA R1 R2 R3 R4

IVAN ANA ZORAN BOJAN

O1 O1 O2 O2

40k 42k 30k 35k

Slika 14: Netačan iskaz

13

1.3

Tabele 5

Kako smo ranije naučili , tabela (Table) je osnovni tip objekta u bazi i predstavlja izvor podataka. Ovdje bi mogli dodati da pored izvora, tabela predstavlja osnovni elemenat za skladištenje podataka. Svaka tabela sastoji se od polja (Fields) i slogova (Records). Kako smo već spominjali, relacioni sistemi se ovako nazivaju jer je relacija jednostavno 6 matematički izraz za tabelu .

1.4

Slogovi, redovi i n-torke nasuprot kolona, atributa i polja

Termini slog, red, n-torka (Record, Row, Tupple) u neformalnom smislu znače istu 7 stvar – jedan zapis ili jedan red u tabeli . Neka tabela može imati proizvoljan broj redova i jednu ili više kolona. Skup kolona u tabeli formira strukturu određenog reda u tabeli. Na drugoj strani, termini polje, kolona i atribut (Field, Column, Attribute) neformalno imaju isto značenje. Polje određuje strukturu i definiše određeni skup podataka iz reda u red. Ako bi ove termine koristili običan korisnik, modelar i programer, onda bi u 8 razgovoru svaki od njih koristio slijedeću terminologiju: Korisnik:

Modelar:

Programer:

Red (Row)

N-torka (Tuple)

Slog, Zapis (Record)

Kolona (Column)

Atribut (Attribute)

Polje (Field)

Tabela (Table)

Relacija (Relation)

Tabela

Međutim, relaciona algebra i relacioni račun n-torki, koji daju čvrstu matematičku podlogu relacionom modelu, zahtjevaju mnogo rigidnije nazive – n-torka, atribut, relacija. Ključne osobine relacionog modela su: 1. Svaki red u tabeli naziva se n-torka; 2. Svaka kolona u tabeli naziva se atribut; 3. Na presjeku reda i kolone nalazi se vrijednost nekog podatka; 4. U relacionom modelu, redovi mogu biti složeni bilo kojim redoslijedom; 5. U relacionom modelu, atributi mogu biti složeni bilo kojim redom; 6. Po definiciji, svi redovi u relaciji su različiti. Dva reda ne smiju imati iste vrijednosti; 7. Relacije moraju imati ključ. Ključevi mogu biti skupovi atributa. 8. Za svaku kolonu (atribut) u tabeli, postoji skup mogućih vrijednosti koji se naziva domen kolone ili domen atributa. Domen sadrži sve moguće vrijednosti koje se mogu pojaviti u toj koloni. 9. Domen je skup važećih vrijednosti jednog atributa; 10. Stepen relacije je broj atributa (kolona) u datoj relaciji; 5

L.Roljić, Z.Novaković – Baze podataka, Visoka škola za ekonomiju i informatiku - Prijedor C.J.Date, Introduction to database systhems, 8th edition 7 G.Powell - Beggining Database Design 8 S.Sumathi, S. Esakkirajan – Fundamentals of Relational DBMS 6

14

11. Kardinalnost relacije je broj n-torki (redova) u relaciji.

1.5

Tabela i relacija

U uvodnom izlaganju smo, radi jednostavnosti, poistovjetili pojmove tabela i relacija. Međutim, kako smo se u određenoj mjeri već upoznali sa relacionim modelom, naše znanje ćemo proširiti određenim pravilima koja podvlače razlike između ova dva pojma. Da bi neka tabela bila relacija, ona mora da zadovolji slijedeća pravila: 1. Dva reda u tabeli ne smiju biti identična (pri čemu njihov redoslijed nije od značaja); 2. Svaka kolona mora imati jedinstveno ime (pri čemu redoslijed kolona nije od značaja); 3. Na presjeku jednog reda i jedne kolone mora se nalaziti samo jedna vrijednost (atomska vrijednost); 4. Sva pojavljivanja podataka u jednoj koloni moraju biti istog tipa.

1.6

9

Struktura relacionog modela

Za formalnu definiciju relacionog modela, koriste se slijedeći matematički pojmovi: Skup. Pojam skupa je osnovni pojam u matematici i on se kao takav formalno ne definiše. Neformalno se može reći da je skup „objedinjavanje nekog mnoštva 10 elemenata u cjelinu“. Skup se može shvatiti kao bilo koja kolekcija različitih objekata posmatranih kao cjelina. Skup elemenata x, y, z, ..., v se može označiti sa S = {x, y, z, S, v}. Ovakav opis skupa, u kom se navode svi njegovi elementi naziva se ekstenzija skupa i može se primjeniti samo na skupove sa konačnim brojem elemenata. Skup se može opisati i navođenjem osobina koje svaki njegov elemenat mora da zadovolji. Ovakav opis skupa naziva se intenzija skupa i piše se:

S = {x | P(x)}, Gdje je P(x) – uslov koji elementi treba da zadovolje. Prethodno prikazanu definiciju skupa mogli bi čitati kao „x takav da zadovoljava P(x)“ ili „skup svih x za koje je uslov P(x) = True“ Kartezijanski (Dekartov) proizvod skupova. Neka je data kolekcija skupova D1, D2, . . . , Dn (ne neophodno različitih). Kartezijanski proizvod ovih n skupova D1 x D2 x ... x Dn je skup svi mogućih uređenih n-torki (d1, d2, ..., dn), tako da je d1 ∈ D1, d2 ∈ D2, ..., dn ∈ Dn.

9

S.Sumathi, S. Esakkirajan – Fundamentals of Relational DBMS B.Lazarević, Z.Marjanović, N.Aničić,S.Babarogić, Baze podataka, FON, Beograd 2008.

10

15

PRIMJER 1: Pretpostavimo da imamo dva skupa A i B sa slijedećim elementima: A = {1, 2, 3, 4}, B = {4, 6, 8} Dekartov proizvod ova dva skupa bio bi AxB= {(1,4), (1,6), (1,8), (2,4), (2,6), (2,8), (3,4), (3,6), (3,8), (4,4), (4,6), (4,8)}. Relacija. Relacija definisana na n skupova je podskup Dekartovog proizvoda tih n skupova. R ⊆ D1 x D2 x ... x Dn Podskup sadrži one n-torke Dekatrovog proizvoda koje zadovoljavaju zadatu relaciju. PRIMJER 2: Neka je na skupovima A i B iz Primjera 1 zadata relacija R: A x B={(a,b)  a=b/2} Dakle, relaciju čine uređeni parovi (a, b) takvi da zadovoljavaju uslov a=b/2., odnosno R = {(2,4), (3,6), (4,8)} Domen relacije. Skupovi D1, D2, ..., Dn se nazivaju domenima relacije R. Stepen relacije. Broj domena na kojima je definisana neka relacija se naziva stepen relacije. Razlikujemo unarne (na jednom domenu), binarne (na dva domena) i n-arne relacije. Kardinalnost relacije je broj n-torki u relaciji. Atribut relacije se formalno može definisati kao par (naziv domena, vrijednost domena). Atributi relacije STUDENT su BRIND, IME i STAROST. Atribut relacije. Kako je Dekartov proizvod skup uređenih n-torki, redoslijed elemenata u jednoj n-torki je bitan. Na primjer, ako na domenima BrInd = {001, 007, 035}, Ime = {Miloš, Ana}, Starost = {19, 22} definišemo relaciju R R ⊆ BrInd x Ime x Starost = {(001, Miloš, 19), {(007, Ana, 19), (035, Ana, 22)}, u njoj je bitno da prvi elemenat trojke uzima vrijednost iz prvog, drugi iz drugog, a treći iz trećeg skupa. Međutim, ako vrijednostima elemenata u n-torkama pridružimo imena domena (semantička, da bismo interpetirali odgovarajuće podatke, dajući sa istim ciljem i ime relaciji), redoslijed elemenata u n-torkama više neće bit značajan. STUDENT ⊆ BRIND x IME x STAROST = { (BRIND:001, IME:Miloš, STAROST:19), (IME: Ana, BRIND: 007, STAROST:19), (BRIND: 035, STAROST: 22, IME: Ana) }

16

Koncept atributa omogućuje predstavljanje relacije kao tabele. Relacija STUDENT se može predstaviti sa:

BrInd 001 007 035

Ime Miloš Ana Ana

Starost 19 19 22

Tabela 1: Relacija Student Pošto je relacija skup, a svaka tabela nije, definišu se slijedeći uslovi koje tabela mora da zadovolji da bi bila relacija: (1) Ne postoje duplikati redova (vrsta) tabele; (2) Redoslijed vrsta nije značajan; (3) Redoslijed kolona nije značajan. Pored toga, da bi se mogao definisati jednostavan skup operacija nad relacijama, definiše se slijedeći dodatni uslov: (4) Sve vrijednosti atributa u relacijama su atomske, Drugim riječima, nisu dozvoljeni atributi ili grupe atributa "sa ponavljanjem", odnosno nije dozvoljeno da vrijednosti nekih atributa u relaciji budu relacije (nisu dozvoljene "tabele u tabeli"). Ako relacija zadovoljava uslov (4) tada je ona u Prvoj normalnoj formi. Svaka relacija u relacionom modelu mora biti u prvoj normalnoj formi. Termin "normalizovana relacija" se koristi za relacije u prvoj normalnoj formi. (Za ostale normalne forme mora se precizirati o kojoj normalnoj formi se radi.) PRIMJER 3: Tabela Prijava, zapisana u slijedećem obliku, nije normalizovana, jer su NAZIVPRED i OCJENA "grupa sa ponavljanjem"

BrInd Ime NazivPred 001 Miloš Baze podataka Matematika Fizika 007 Ana Fizika Matematika

Ocjena 9 7 10 7 9

Tabela 2: Tabela Prijava Tabela Prijava se može dovesti u prvu normalnu formu na slijedeći način (uvodeći redundansu podataka):

BrInd 001 001 001 007 007

Ime Miloš Miloš Miloš Ana Ana

NazivPred Baze podataka Matematika Fizika Fizika Matematika

Ocjena 9 7 10 7 9 17

Tabela 3: Relacija Prijava Uobičajeno je da se relacije predstavljaju na način koji se naziva šema relacije: Student(BrInd, Ime, Starost) Prijava(BrInd, NazivPred, Ime, Ocjena)

1.6.1

Domeni relacije

Domeni se mogu definisati i kao skupovi iz kojih atributi relacije uzimaju svoje vrijednosti. Uobičajeno je da se domeni dijele na: •

Predefinisane domene ili domene koji postoje u jezicima baza podataka. Predefinisani domeni su ekvivalentni predefinisanim (ugrađenim) tipovima podataka (Integer, String, DoubleS).



Semantičke domene, koje korisnik definiše nad predefinisanim ili prethodno kreiranim semantičkom domenima, na način da u njihovu definiciju ugradi neko ograničenje i na taj način im da određeno značenje.

1.6.2

Ključevi relacije

Činjenica da su sve n-torke u relaciji različite, govori da postoji jedan atribut ili više atributa zajedno (u krajnjem slučaju svi zajedno) čije vrijednosti jedinstveno identifikuju jednu n-torku u relaciji (jednu vrstu u tabeli). Taj atribut ili ta grupa atributa se nazivaju ključem relacije (jedan atribut - prost ključ, grupa atributa - složen ključ). Student(BrInd, Ime, Starost) Prijava(BrInd, NazivPred, Ime, Ocjena) Na primjer, u relaciji STUDENT, ključ je BRIND (prost ključ), dok je u relaciji Prijava ključ grupa BRIND, NAZIVPRED (složen ključ). Ključ relacije se formalno definiše na slijedeći način: Ključ relacije R je takva kolekcija K njenih atributa koja zadovoljava slijedeća dva uslova: •

Osobinu jedinstvenosti. Ne postoje bilo koje dvije n-torke sa istom vrijednošću K.



Osobina neredundantnosti. Ako se bilo koji atribut izostavi iz K, gubi se 11 osobina jedinstvenosti.

Ona kolekcija atributa K koja zadovoljava samo osobinu jedinstvenosti naziva se nadključ relacije. Npr., grupa atributa BrInd, NazivPred, Ocjena je nadključ relacije Prijava, jer zadovoljava samo uslov jedinstvenosti. Atribut Ocjena se može izostaviti a da se osobina jedinstvenosti ne izgubi. U jednoj relaciji može postojati više različitih kolekcija K atributa koje zadovoljavaju definiciju ključa. (Na primjer, ako u relaciju STUDENT dodamo atribut JMBG jedinstveni matični broj, i on će, pored BRIND, zadovoljavati definiciju ključa). Sve takve kolekcije se nazivaju kandidati za ključ. Jedan od kandidata koji se izabere da praktično služi za identifikaciju n-torke relacije se tada naziva primarni ključ. Ostali (neizabrani) kandidati se tada nazivaju alternativnim ključevima.

11

B.Lazarević, Z.Marjanović, N.Aničić,S.Babarogić, Baze podataka, FON, Beograd 2008.

18

Atributi koji učestvuju u ključevima (koji su dio kandidata za ključ) nazivaju se ključnim atributima. Ostali atributi u realciji su neključni (ili sporedni) atributi. Primarni ključ se u prikazu relacije (šemi relacije) podvlači: Student(BrInd, Ime, Starost) Prijava(BrInd, NazivPred, Ime, Ocjena) Spoljni ključ je atribut (ili grupa atributa) u relaciji R1 čija se vrijednost koristi za povezivanje sa vrijednošću primarnog ključa u nekoj relaciji R2. Spoljnji ključ i njemu odgovarajući primarni ključ moraju biti definisani nad istim domenom. Spoljni ključevi služe da uspostave veze između relacija u relacionoj bazi podataka. Na primjer, u relaciji PRIJAVA, BRIND je spoljni ključ, preko koga se ova relacija može povezati sa relacijom STUDENT.

1.6.3

Šema relacione baze i relaciona baza podataka 12

Relaciona baza podataka je kolekcija vremenski promjenljivih relacija. Termin vremenski promjenljiva ovdje naglašava činjenicu da se vrijednosti atributa relacija u bazi podataka mijenjaju. Šema relacione baze podataka definiše strukturu baze. Za neki studentski informacioni sistem, šema relacione baze podataka bi mogla da se predstavi na slijedeći način: Student(BrInd, MLB, Ime, Starost, ŠifSmjera), Predmet(ŠifPred, NazivPred, BrojČasova), Prijava(BrInd, ŠifPred, DatumPol, Ocjena ) Smjer(ŠifSmjera, NazivSmjera, ŠifNast) Nastavnik(ŠifNast, ImeNast, Zvanje, ŠifPred) Sama baza podataka predstavlja skup tabela čije su strukture opisane u šemi baze. U tim tabelama se čuvaju podaci o odgovarajućim objektima. Primjer fakultetske baze podataka mogao bi biti:

BrInd 152/10 233/09 021/08 429/10 003/10

JMBG 1603991161113 2505989150002 0102990183322 1911991190012 0906991180023

Ime Ana Mirko Zoran Denis Miloš

Starost 19 21 20 ? 22

ŠifSmjera 01 01 ? 02 01

Tabela 4: Relacija Student

ŠifPred P1 P2 P3

NazivPred Baze podataka Matematika Mikroekonomija

BrojČasova 6 4 ?

Tabela 5: Relacija Predmet

12

B.Lazarević, Z.Marjanović, N.Aničić,S.Babarogić, Baze podataka, FON, Beograd 2008.

19

ŠifSmjera NazivSmjera ŠifNast 01 Informacioni sistemi nn4 02 Menadžment nn3 Tabela 6: Relacija Smjer

BrInd 152/10 152/10 021/08 003/10 021/08

ŠifPred P1 P2 P1 P3 P3

DatumPol 18.03.10 21.04.10 ? 30.05.10 01.07.10

Ocjena 9 8 10 6 10

Tabela 7: Relacija Prijava

ŠifNast nn1 nn2 nn3 nn4

ImeNast Boris Mirjana Petar Zoran

Zvanje Mr Dr Dr Mr

ŠifPred P1 P2 P3 ?

Tabela 8: Relacija Nastavnik Relacije se u nekoj bazi podataka mogu podjeliti na „bazne” i „izvedene”. Izvedena relacija (pogled) je relacija koja se može izvesti iz skupa datih baznih i izvedenih 13 relacija, preko operacija koje se definišu nad relacijama. Na primjer, može se izvesti relacija DobriStudenti(BrInd, Ime, NazivSmjera, NazivPred, Ocjena) U kojoj se nalaze svi studenti koji su sve svoje ispite položili sa ocjenama većim ili jednakim 8.

BrInd 152/10 152/10 021/08 021/08

Ime Ana Ana Zoran Zoran

NazivSmjera Informacioni sistemi Informacioni sistemi ? ?

NazivPred Baze podataka Matematika Baze podataka Mikroekonimija

Ocjena 8 9 10 10

Tabela 9: Izvedena relacija DobriStudenti Bazna relacija je relacija koja se ne može izvesti iz ostalih relacija u relacionoj bazi podataka.

13

B.Lazarević, Z.Marjanović, N.Aničić,S.Babarogić, Baze podataka, FON, Beograd 2008.

20

1.7

Relaciona algebra

Algebra se najopštije definiše kao skup snabdjeven sa kolekcijom operacija. Elementi skupa nad kojima je definisana algebra su operandi u operacijama algebre. Na osnovu ovako uopštene definicije, relaciona algebra se definiše kao skup relacija sa 14 kolekcijom operacija nad njima. •

Operacije nad relacijama mogu da se grupišu u:



Konvencionalne skupovne operacije – unija, presjek, razlika i Dekartov proizvod,



Specijalne relacione operacije – selekcija, projekcija, spajanje i dijeljenje.



Operacije ažuriranja baze



Operacije u prisustvu nula vrijednosti.

Skup relacionih operatora treba da bude zatvoren: rezultat koji se dobija primjenom nekog operatora je takođe relacija (tabela). Takav rezultat može ponovo da bude argument operacija relacione algebre.

1.7.1

Konvencionalne skupovne operacije u relacionoj algebri

Relacija n-tog stepena se definiše kao podskup Dekartovog proizvoda skupova i može se tretirati kao skup n-torki. Zbog toga su osnovne skupovne operacije i operacije relacione algebre. Međutim, očigledno je da se operacije unije, presjeka i diferencije ne mogu primjeniti, (ili preciznije, nemaju semantički značaj) na bilo koje dvije relacije. (Na primjer, unija relacija ORGANIZACIJA i PROJEKAT formalno treba da dâ relaciju čije su n-torke elementi bilo relacije ORGANIZACIJA bilo relacije PROJEKAT, a tako dobijen rezultat nije relacija u smislu u kome su relacije ovde definisane). Zbog toga se definiše slijedeći uslov kompatibilnosti relacija R1 i R2 za izvođenje operacija unije, presjeka i diferencije: Relacije R1 i R2 moraju imati isti broj atributa (isti stepen), a odgovarajući atributi moraju biti definisani nad istim domenima da bi se nad njima mogle 15 vršiti operacije unije, presjeka i diferencije . U literaturi se ovakve relacije nazivaju relacije kompatibilne za uniju (union compatible relations) ili samo kompatibilne relacije. Primjere operacija unije, presjeka i diferencije prikazaćemo na slijedećim relacijama:

BrInd 152/10 233/09 021/08

JMBG 1603991161113 2505989150002 0102990183322

Ime Ana Mirko Zoran

Starost 19 21 20

ŠifSmjera 01 01 ?

Tabela 10: Relacija S1

14 15

B.Lazarević, Z.Marjanović, N.Aničić,S.Babarogić, Baze podataka, FON, Beograd 2008. B.Lazarević, Z.Marjanović, N.Aničić,S.Babarogić, Baze podataka, FON, Beograd 2008.

21

BrInd 233/09 021/08 003/10

JMBG 2505989150002 0102990183322 0906991180023

Ime Mirko Zoran Miloš

Starost 21 20 22

ŠifSmjera 01 ? 01

Tabela 11: Relacija S2 1. Unija. Date su relacije R1 i R2 koje zadovoljavaju navedeni uslov kompatibilnosti. Rezultat operacije unije R3 = R1 ∪ R2 je relacija R3 koja sadrži sve n-torke koje se pojavljuju bilo u R1 bilo u R2. Eventualni duplikati n-torki automatski se uklanjaju iz unije. Primjer: S3 = S1 ∪ S2

BrInd 152/10 233/09 021/08 003/10

JMBG 1603991161113 2505989150002 0102990183322 0906991180023

Ime Ana Mirko Zoran Miloš

Starost 19 21 20 22

ŠifSmjera 01 01 ? 01

Tabela 12: Relacija S3 2. Diferencija. Date su relacije R1 i R2 koje zadovoljavaju navedeni uslov kompatibilnosti. Rezultat operacije diferencije R3 = R1 - R2 su n-torke relacije R1 koje nisu istovremeno i n-torke relacije R2. Primjer: S4 = S1 - S2

BrInd JMBG Ime Starost ŠifSmjera 152/10 1603991161113 Ana 19 01 Tabela 13: Relacija S4 3. Presjek. Date su relacije R1 i R2 koje zadovoljavaju navedeni uslov kompatibilnosti. Rezultat operacije presjeka R3 =R1 ∩ R2 je relacija R3 koja sadrži n-torke koje se pojavljuju u obje relacije R1 i R2. Primjer: R5 = R1 ∩ R2

BrInd JMBG Ime Starost ŠifSmjera 233/09 2505989150002 Mirko 21 01 021/08 0102990183322 Zoran 20 ? Tabela 14: Relacija S1 4. Dekartov proizvod. Dekartov proizvod se može primjeniti na bilo koje dvije relacije. Rezultat ove operacije R3 = R1 x R2 je relacija R3 čije su n-torke svi "parovi" koje čine jedna n-torka relacije R1 i jedna ntorka relacije R2. Primjer: S6 = S1 x S2

22

BrInd 152/10 233/09 021/08

Ime Ana Mirko Zoran

Tabela 15: Relacija S1

BrInd 233/09 021/08 003/10

Ime Mirko Zoran Miloš

Tabela 16: Relacija S2

BrInd 152/10 233/09 021/08 152/10 233/09 021/08 152/10 233/09 021/08

Ime Ana Mirko Zoran Ana Mirko Zoran Ana Mirko Zoran

BrInd 233/09 233/09 233/09 021/08 021/08 021/08 003/10 003/10 003/10

Ime Mirko Mirko Mirko Zoran Zoran Zoran Miloš Miloš Miloš

Tabela 17: Relacija S6

1.7.2

Specijalne relacione operacije

Pored skupovnih operacija u relacionom modelu se definišu i slijedeće specifične operacije: 5. Projekcija. Operacija projekcije je unarna operacija koja iz neke relacije selektuje skup navedenih atributa, odnosno "vadi" vertikalni podskup iz odgovarajuće tabele. Formalno se može definisati na slijedeći način: Neka je R(A1, A2, ..., An) relacija, a X podskup njenih atributa. Označimo sa Y komplement: Y = R - X = {A1, A2, ..., An} - X Rezultat operacije projekcije relacije R po atributima X je

ΠX(R) = {x  ∃ y, ∈ R}, ili manje formalno ΠX(R) = {x takvo da postoji y za koje je ∈ R}. Gdje je x - atributi podskupa X relacije R y - atributi komplementa Y (takođe podskupa relacije R) Primjer: Pretpostavimo da imamo relaciju STUDENTI

BrInd JMBG Ime 152/10 1603991161113 Ana

Starost ŠifSmjera 19 01 23

233/09 2505989150002 Mirko 21 021/08 0102990183322 Zoran 20 999/10 9999991161113 Ana 19

01 ? 01

Tabela 18: Relacija STUDENTI Projekcija Pr1 ove relacije po atributima IME i STAROST bila bi:

Pr1 = ΠIme, Starost(STUDENTI) Ime Ana Mirko Zoran Ana

Starost 19 21 20 19

Tabela 19: Relacija PR1 Kada se iz neke relacije selektuje podskup atributa preko operacije projekcije u rezultatu se mogu pojaviti duplikati n-torki. Operacija projekcije podrazumjeva da se ovi duplikati eliminišu, kako je to u navedenom primjeru i urađeno. 6. Selekcija (Restrikcija). Selekcija je takođe unarna operacija koja iz date relacije selektuje n-torke koje zadovoljavaju zadati uslov ("vadi" horizontalni podskup tabele). Formalno se definiše na slijedeći način: Data je relacija R(A1, A2, ..., An) i predikat Θ definisan nad njenim atributima. Rezultat operacije selekcije δΘ(R) = {x  x ∈ R AND Θ (x)} ili manje formalno δΘ(R) = {x takvo da je x ∈ R i da zadovoljava uslov Θ (x)} Gdje je x – n-torka relacije R Θ (teta) – uslov (predikat) koji n-torke moraju da zadovolje δ (sigma) – operator selekcije Primjer: U relaciji STUDENTI selektovati one koji su stariji od 19 godina:

BrInd 152/10 233/09 021/08

JMBG 1603991161113 2505989150002 0102990183322

Ime Ana Mirko Zoran

Starost 19 21 20

ŠifSmjera 01 01 ?

Tabela 20: Relacija STUDENTI

SEL = δ Starost > 19 (STUDENTI) BrInd JMBG Ime Starost ŠifSmjera 233/09 2505989150002 Mirko 21 01 021/08 0102990183322 Zoran 20 ? Tabela 21: Relacija SEL

24

7. Spajanje (Join). Spajanje je binarna operacija koja spaja dvije relacije na način da se u rezultatu pojavljuju oni parovi n-torki jedne i druge relacije koji zadovoljavaju uslov zadat nad njihovim atributima. Formalno se definiše na slijedeći način: Date su relacije R1(A1, A2, ..., An) i R2(B1,B2, ..., Bm) i predikat Θ definisan nad njihovim atributima. Obilježimo sa X i Y skupove atributa relacija R1 i R2, respektivno. Rezultat operacije spajanja ovih relacija (tzv. teta spajanje) je R1[xΘ]R2 = { (x ∈ R1) AND (y ∈ R2) AND Θ(x,y) }, ili neformalno R1[xΘ]R2 = { takvih da je (x ∈ R1) i da je (y ∈ R2) i da vrijedi Θ(x,y) } Gdje su x, y – n-torke relacija R1 i R2, respektivno, xΘ – Dekartov proizvod po Teta uslovu. Oznaka xΘ za operaciju spajanja ukazuje na činjenicu, očiglednu iz definicije teta spajanja, da ova operacija nije primitivna operacija relacione algebre, već se može izvesti uzastopnom primjenom operacije Dekartovog proizvoda (x) i selekcije po predikatu Θ iz tako dobijene relacije. Ako je predikat Θ definisan sa Ak = Bj, s tim da su i atributi Ak i Bj definisani nad istim domenima, tada se takvo spajanje naziva ekvispajanje. Slijedeći primjer ilustruje ekvispajanje: Primjer: Date su relacije STUDENT i GRAĐANIN. Izvršiti njihovo spajanje po atributu JMBG.

BrInd 152/10 233/09 021/08

JMBG 1603991161113 2505989150002 0102990183322

ŠifSmjera 01 01 ?

Tabela 22: Relacija STUDENT

JMBG 1603991161113 2505989150002 0102990183322

Ime Ana Mirko Zoran

Starost 19 21 20

Tabela 23: Relacija GRAĐANIN JOIN = GRAĐANIN [GRAĐANIN.JMBG = STUDENT.JMBG ] STUDENT

BrInd 152/10 233/09 021/08

JMBG 1603991161113 2505989150002 0102990183322

ŠifSmjera 01 01 ?

JMBG 1603991161113 2505989150002 0102990183322

Ime Ana Mirko Zoran

Starost 19 21 20

Tabela 24: Relacija JOIN Očigledno je da se u rezultatu ekvispajanja uvjek pojavljuju dvije iste kolone. Ako se jedna od te dvije kolone izbaci, takvo spajanje se naziva prirodno spajanje. Uobičajeno je da se prirodno spajanje označava sa *. JOIN_NATURAL = GRAĐANIN [GRAĐANIN.JMBG * STUDENT.JMBG ] STUDENT

25

BrInd 152/10 233/09 021/08

JMBG 1603991161113 2505989150002 0102990183322

ŠifSmjera 01 01 ?

Ime Ana Mirko Zoran

Starost 19 21 20

Tabela 25: Relacija JOIN_NATURAL Relaciona algebra je proceduralni jezik. Pomoću operacija relacione algebre sačinjava se procedura koja dovodi do odgovora na postavljeni upit. Iako je proceduralni jezik, relaciona algebra je znatno moćnija od klasičnih programskih jezika koji su takođe proceduralni. Razlog za to je što je operand relacione algebre relacija (cijela tabela), a operand operacija sa datotekama u klasičnim jezicima je rekord – jedan red tabele. Može se pokazati da se bilo koja relacija (bilo koji upit), izvodljiva iz skupa datih relacija, može dobiti procedurom (algoritmom) od tri koraka: (1) Dekartov proizvod svih relacija koje se koriste. (2) Selekcija n-torki za koje se predikat selekcije sračunava u T. (3) Projekcija rezultata po atributima koji se prikazuju. Ova procedura se može iskazati jednim opštim izrazom relacione algebre P[A1, A2, ..., An] (S[P] (R1 x R2 x ... x Rm)). Međutim, ovakvo izvođenje operacija bilo bi veoma "skupo" jer bi rezultat Dekartovog proizvoda relacija R1, R2, ..., Rm bio relacija sa K1 x K2 x ... x Km n-torki, gde su sa Ki označene kardinalnosti odgovarajućih relacija. Zbog toga se i definiše operacija spajanja koja istovremeno obavlja Dekartov proizvod i selekciju, smanjujući na taj način broj n-torki koji se pretražuje. Pored toga očigledno je da su algoritmi sa više koraka, u kojima bi se prvo vršile sve selekcije koje se mogu izvesti na pojedinačnim relacijama, zatim projekcije, pa tek onda spajanja, znatno efikasniji.

1.7.3

Operacije održavanja baze podataka

Operacije održavanja (ažuriranja) baze podataka treba da omoguće dodavanje n-torke u neku relaciju, izbacivanje n-torke iz relacije ili promjenu vrijednosti atributa relacije. Ako je definisana operacija dodavanja n-torke u relaciju, ta operacija se može izvršiti preko operacije unije na slijedeći način: Student := Student ∪ (, )

,

,

Ako je relacija student prije ove operacije bila

BrInd 152/10 233/09 021/08

JMBG 1603991161113 2505989150002 0102990183322

Ime Ana Mirko Zoran

Starost 19 21 20

ŠifSmjera 01 01 ?

Ime

Starost ŠifSmjera

Tabela 26: Relacija Student Nakon operacije će biti:

BrInd 26

JMBG

,

152/10 233/09 021/08 003/10

1603991161113 2505989150002 0102990183322 0906991180023

Ana Mirko Zoran Miloš

19 21 20 22

01 01 ? 01

Tabela 27: Relacija Student nakon operacije unije Operaciju diferencije smo definisali kao R3 = R1 - R2 su n-torke relacije R1 koje nisu istovremeno i n-torke relacije R2. Operacija izbacivanja n-torke iz relacije se sada može definisati kao: Student := Student - (,

,

,

,

Operacija ažuriranja vrijednosti nekog atributa se obavlja tako da se prvo diferencijom izbace sve n-torke čiji se atribut mijenja, a zatim se vrate preko operacije unije, ali sa izmjenjenom vrijednošću atributa: Student := Student - (,

,

,

,

∪ (, , , , )

1.7.4

Operacije sa nula vrijednostima

Termin „nula vrijednosti” se koristi da označi “nedostatak informacija” u bazi, odnosno 16 „još nepoznatu vrijednost” . Ova vrijednost se u današnjim sistemima za upravljanje bazama podataka označava kao NULL vrijednost. Navedene operacije relacione algebre nisu uzimale u obzir nula vrijednosti koje mogu postojati u relacijama. Podrazumjevalo se da se vrijednosti predikata sračunavaju na osnovu standardnih, dvovrijednosnih tablica istinitosti. Isto tako, bez dvoumljenja je bilo moguće da se odrede duplikati n-torki, odnosno kardinalnost pojedinih skupova. Pojavljivanje nula vrijednosti u relacionoj bazi podataka zahtjeva da se proširi skup definisanih operacija koje bi na neki način uključile i nula vrijednosti. Osnovne postavke za operacije sa nula vrijednostima su slijedeće: (1) Tablice istinitosti trovrijednosne logike:

AND T ? F

T T ? F

? ? ? F

F F F F

OR T ? F

T T T T

? T ? ?

F T ? F

NOT T F ? ? F T

Tabela 28: Tablice istinitosti trovrijednosne logike gdje (?) predstavlja nula vrijednost, a može se unutar tablica istinitosti čitati i kao "možda"). (2) Sračunavanje aritmetičkih formula. Neka α označava neki od aritmetičkih operatora (+, -, *, /) i neka su x i y dvije numeričke vrijednosti. Vrijednost aritmetičkog 16

B.Lazarević, Z.Manojlović, N.Aničić, S.Babarogić – Baze podataka, FON, Beograd, 2008

27

izraza "x α y" je po definiciji nula vrijednost ako bilo x, bilo y, bilo oba dobiju nula vrijednost. (3) Skupovi sa nula vrijednostima. Posmatrajmo kolekciju {1, 2, 3, ?}. Da li je ova kolekcija skup? Ako je ova kolekcija skup, koja je njegova kardinalnost? Ako se prisjetimo definicije da se skup može shvatiti kao bilo koja kolekcija različitih objekata posmatranih kao cjelina, možemo zaključiti slijedeće: Ako ? uzme vrijednost 1, 2 ili 3 onda kolekcija nije skup, Ako ? nije ni 1, ni 2, ni 3 onda gornja kolekcija predstavlja skup sa kardinalnošću 4. To pokazuje da postoje različite nula vrijednosti, nula vrijednost koja nije 1, nula vrijednost koja nije 2, zatim nula vrijednost koja nije ni 1 ni 2 i tako dalje. Operacije koje bi uzele u obzir različitost nula vrijednosti bile bi veoma složene. Zbog toga se operacije definišu sa jednom vrstom nula vrijednosti, a ostale nula vrijednosti se tretiraju kao duplikati.

28

2

Normalne forme – projktovanje relacija normalizacijom

Normalizacija relacija je postupak razvoja relacionog konceptualnog modela u kome se svaka relacija relacionog modela svodi na odgovarajuću normalnu formu. Uobičajeno je da se postupak normalizacije tretira i kao postupak logičkog projektovanja baze podataka. Relacioni model zahtjeva da se sve relacije u modelu nalaze u Prvoj normalnoj formi. Prva normalna forma se definiše na slijedeći način: Relacija R je u Prvoj normalnoj formi 1NF, ako su sve vrijednosti njenih atributa 17 atomske. Kako je već navedeno, nisu dozvoljeni atributi ili grupe atributa sa ponavljanjem. Termin normalizovana relacija se koristi za relacije u Prvoj normalnoj formi. Ostale normalne forme relacija, o kojima će biti govora u nastavku, nisu zahtjev samog Relacionog modela. BrInd 21

Ime Zoran

Sem 5

ŠifSmj 01

NazivSmjera Inf.Sistemi

ImeRuk Zoran

77

Ana

7

01

Inf.Sistemi

Zoran

36

Pero

4

02

Menadžment

Petar

ŠifPred 121 323 056 056 121 323 456 442 121

NazivPred Matematika Baze podataka Programiranje Programiranje Matematika Baze podataka Mikroekonomija Menadžment Matematika

Ocjena 7 8 8 10 5 8 9 6 7

Tabela 29: Tabela Student nije u 1NF - vrijednosti atributa očito nisu atomske zbog grupa atributa sa ponavljanjem Uobičajeno je da se normalizacija tretira kao postupak u kojem se odstranjuju tzv. „anomalije u održavanju (ažuriranju)“ relacija do kojih dolazi zbog redundanse podataka. Anomalije u ažuriranju će biti objašnjene na primjeru slijedeće relacije koja se nalazi u 1NF: Student(BrInd, ŠifPred, Ime, Sem, ŠifSmj, NazivSmjera, ImeRuk, NazivPred, Ocjena); BrInd 21 21 21 77 77 36 36 36 36

ŠifPred 121 323 056 056 121 323 456 442 121

Ime Zoran Zoran Zoran Ana Ana Pero Pero Pero Pero

Sem 5 5 5 7 7 4 4 4 4

ŠifSmj 01 01 01 01 01 02 02 02 02

NazivSmjera Inf.Sistemi Inf.Sistemi Inf.Sistemi Inf.Sistemi Inf.Sistemi Menadžment Menadžment Menadžment Menadžment

ImeRuk Zoran Zoran Zoran Zoran Zoran Petar Petar Petar Petar

NazivPred Matematika Baze podataka Programiranje Programiranje Matematika Baze podataka Mikroekonomija Menadžment Matematika

Ocjena 7 8 8 10 5 8 9 6 7

Tabela 30: Tabela Student u Prvoj normalnoj formi Očigledna je redundansa podataka u gornjoj relaciji, a ona je osnovni uzrok slijedećih anomalija u održavanju: Anomalije u dodavanju su naziv za situaciju u kojoj u bazu podataka nije moguće ubaciti neki logički skup podataka, a da se pri tome, zbog strukture relacija, ne zahtjeva 17

B.Lazarević, Z.Marjanović, N.Aničić,S.Babarogić, Baze podataka, FON, Beograd 2008.

29

i ubacivanje nekih drugih podataka. Na prijmer, ako je u nastavnom planu definisan neki novi predmet, u gornju relaciju se ne mogu ubaciti podaci od tom predmetu dok ga neki student ne položi. Anomalije u izbacivanju su naziv za situaciju u kojoj izbacivanje nekog logičkog skupa iz baze prouzrokuje neželjeno izbacivanje nekih drugih podataka. Ako je jedan predmet (Menadžment, Mikroekonomija) položio samo jedan student (Pero), te ako se on ispiše sa fakulteta, odnosno ako se izbace odgovarajuće n-torke, gube se sve informacije o tim predmetima. Anomalije u promjeni sadržaja su situacija u kojoj promjena jednog podatka zahtjeva i promjenu nekih drugih podataka u bazi. Na primjer, ako se promjeni naziv nekog predmeta ili rukovodilac nekog smjera, to se mora učiniti na onoliko mjesta koliko je studenata položilo taj predmet. Već je rečeno da je redundansa podataka uzrok prikazanih anomalija. Međutim, isto tako se može reći da su anomalije u ažuriranju prouzrokovane činjenicom da relacija student predstavlja spoj (agregaciju) više različitih objekata sistema. Ona istovremeno predstavlja objekte STUDENT, PREDMET, SMJER, PRIJAVA i njihove međusobne veze. Ako bi se relacija Student dekomponovala, na ove pojedinačne relacije, imali bi oblik: Student(BrInd, Ime, Sem, ŠifSmjera), Predmet(ŠifPred, NazivPred), Smjer(ŠifSmjera, NazivSmjera, ImeRuk) Prijava(BrInd, ŠifPred, Ocjena ) U ovakvom slučaju, redundansa podataka bi se minimalizovala i izbjegle bi se sve anomalije.

2.1

Funkcionalne zavisnosti - osnovne definicije i terminologija

Definicije Druge, Treće i Boyce-Codd-ove normalne forme zasnivaju se na konceptu funkcionalne zavisnosti atributa relacije, koja se definiše na slijedeći način: Data je relacija R sa atributima X i Y, moguće složenim. Atribut Y je funkcionalno zavisan od atributa X (ili X funkcionalno određuje Y), R.X -> R.Y, 18

ako i samo ako svakoj vrijednosti X odgovara jedna i samo jedna vrijednost Y. Na primjer u relaciji Student

Student(BrInd, ŠifPred, Ime, Sem, ŠifSmj, NazivSmjera, ImeRuk, NazivPred, Ocjena) postoje slijedeće funkcionalne zavisnosti: BrInd, ŠifPred -> Ime, Sem, ŠifSmj, NazivSmjera, ImeRuk, NazivPred, Ocjena BrInd -> Ime, Sem, ŠifSmj, NazivSmjera, ImeRuk ŠifSmj -> NazivSmjera, ImeRuk ŠifPred -> NazivPred, 18

B.Lazarević, Z.Marjanović, N.Aničić,S.Babarogić, Baze podataka, FON, Beograd 2008.

30

Koncept potpune funkcionalne zavisnosti se definiše na slijedeći način: Atribut Y relacije R je potpuno funkcionalno zavisan od atributa X relacije R ako je funkcionalno zavisan od atributa X, a nije funkcionalno zavisan ni od jednog 19 pravog podskupa atributa X. Primjere potpune i nepotpune funkcionalne zavisnosti možemo pokazati na relaciji PRIJAVA: Prijava(BrInd, ŠifPred, Ocjena, NazivPred) (a) Pošto važi slijedeće: BrInd, ŠifPred --->

Ocjena

BrInd

-/->

Ocjena

ŠifPred

-/->

Ocjena

atribut OCJENA je potpuno funkcionalno zavisnan od složenog atributa BRIND, ŠIFPRED. (b) Pošto važi slijedeće: BrInd, ŠifPred --->

NazivPred

BrInd

-/->

NazivPred

ŠifPred

--->

NazivPred

atribut NAZIVPRED je nepotpuno funkcionalno zavisan od složenog atributa BRIND, ŠIFPRED, jer je funkcionalno zavisan i od njega i od jednog njegovog dijela, od ŠPRED. Koncept tranzitivne funkcionalne zavisnosti se definiše na slijedeći način: Data je relacija R sa atributima A, B i C, moguće složenim. Ako u relaciji R važi: A

--->

B

B

--->

C

A

--->

C

B

-/->

A

C

-/->

A

atribut C je tranzitivno funkcionalno zavisan od atributa A.

20

Jednostavnije rečeno, atribut C je tranzitivno funkcionalno zavisan od atributa A ako je funkcionalno zavisan od A i ako je funkcionalno zavisan od nekog atributa B koji je i sam funkcionalno zavisan od A. Očigledno je da je i tranzitivna funkcionalna zavisnost redundantna, jer se može dedukovati iz kompozicije funkcija koje je čine. Posmatrajmo relaciju: Student(BrInd, ŠifPred, Ime, Sem, ŠifSmj, NazivSmjera, ImeRuk, NazivPred, Ocjena) Iz zavisnosti: BrInd 19 20

--->

ŠifSmj

B.Lazarević, Z.Marjanović, N.Aničić,S.Babarogić, Baze podataka, FON, Beograd 2008. B.Lazarević, Z.Marjanović, N.Aničić,S.Babarogić, Baze podataka, FON, Beograd 2008.

31

ŠifSmj

--->

NazivSmjera

ŠifSmj

--->

ImeRuk

Slijedi da BrInd funkcionalno određuje NazivSmjera BrInd

--->

NazivSmjera

i da BrInd funkcionalno određuje ImeRuk BrInd

--->

ImeRuk

Zbog toga, naziv smjera i ime rukovodioca možemo izdvojiti u posebnu relaciju.

2.2

Dekompozicija relacija bez gubljenja informacija

Kako je na priimjeru relacije STUDENT prikazano, svođenje relacija na normalne forme (drugu, treću...) zahtjeva dekompoziciju polazne relacije na njene projekcije. Postavlja se pitanje da li se pri takvoj dekompoziciji gubi neka informacija iz polazne relacije, odnosno postavlja se zahtjev da se ovakva dekompozicija vrši bez gubljenja informacija. Relacija R se dekomponuje u svoje projekcije bez gubljenja informacija ako 21 prirodno spajanje tako dobijenih projekcija dovodi do polazne relacije. Pokažimo na primjeru relacije PRIJAVA Prijava(BrInd, ŠifPred, NazivPred, Ocjena) da je formalno moguće dekomponovati relaciju i sa gubljenjem informacija i da se to gubljenje informacija ogleda, obično, u tome da se u relaciji koja se dobija prirodnim spajanjem projekcija pojavljuju i neke dodatne n-torke koje nisu postojale u polaznoj relaciji. BrInd 21 21 21 77 77 36 36 36 21

ŠifPred 121 323 056 056 121 323 456 442

NazivPred Matematika Baze podataka Programiranje Programiranje Matematika Baze podataka Mikroekonomija Menadžment

Ocjena 7 8 8 9 10 7 9 6

B.Lazarević, Z.Marjanović, N.Aničić,S.Babarogić, Baze podataka, FON, Beograd 2008.

32

36 121 Matematika 7 Tabela 31: Tabela Prijava Ako dekomponujmo ovu relaciju na projekcije R1(BrInd, ŠifPred, Ocjena) i R2(NazivPred, Ocjena). Imaćemo BrInd ŠifPred 21 121 21 323 21 056 77 056 77 121 36 323 36 456 36 442 36 121 Relacija R1

Ocjena 7 8 8 9 10 7 9 6 7

NazivPred Matematika Baze podataka Programiranje Programiranje Matematika Baze podataka Mikroekonomija Menadžment Matematika Relacija R2

Ocjena 7 8 8 9 10 7 9 6 7

Prirodno spajanje moguće je izvršiti samo po atributu OCJENA: R3 = R1[OJCENA * OCJENA] R2 daje: BrInd ŠifPred NazivPred Ocjena 21 121 Matematika 7 21 323 Baze podataka 8 21 056 Programiranje 8 77 056 Programiranje 10 77 121 Matematika 5 36 323 Baze podataka 8 36 456 Mikroekonomija 9 36 442 Menadžment 6 36 121 Matematika 7 ------- --------------21 121 Baze podataka 7 21 323 Programiranje 8 21 056 Baze podataka 8 77 056 Mikroekonomija 9 36 323 Matematika 7 36 456 Programiranje 9 36 121 Baze podataka 7 Tabela 32: Tabela R3- Rezultat dekompozicije i ponovnog prirodnog spajanja N-torke dopisane ispod crtkaste linije su rezultat spajanja, a nisu postojale u polaznoj relaciji PRIJAVA i one su uzrok gubljenja informacija u navedenoj dekompoziciji. Heath-ova teorema daje uslove pod kojima se može izvršiti dekompozicija relacije bez gubljenja informacija:

33

Relacija R(A,B,C), gde su A, B i C podskupovi atributa, u kojoj važi R.A --> R.B može se uvjek dekomponovati u svoje projekcije R1(A,B) i R2(A,C) bez gubljenja 22 informacija. Za navedeni primjer relacije PRIJAVA, dekompozicija bez gubljenja informacija bi bila dekompozicija u projekcije R1(BRIND, ŠIFPRED, OCJENA) i R2(ŠIFPRED, NAZIVPRED)

2.3

Druga i Treća normalna forma

BrInd ŠifPred NazivPred Ocjena 21 121 Matematika 7 21 323 Baze podataka 8 21 056 Programiranje 8 77 056 Programiranje 9 77 121 Matematika 10 36 323 Baze podataka 7 36 456 Mikroekonomija 9 36 442 Menadžment 6 36 121 Matematika 7 Tabela 33: Tabela Prijava Ako posmatramo relaciju PRIJAVA, očigledna je redundansa podataka u ovoj relaciji: NAZIVPRED, za isti predmet, se pojavljuje uz svakog studenta koji je taj predmet položio. Ponovo postoje slijedeće anomalije u održavanju BP: •

Ne mogu se dodati podaci o novom predmetu ako ga neki student nije položio.



Ako se iz baze podataka izbaci n-torka studenta koji je jedini položio neki predmet, gube se sve informacije i o tom predmetu.



Ako se promjeni naziv predmeta, to se mora učiniti na onoliko mjesta koliko je studenata položilo taj predmet.

Uzrok redundansi i anomalijama u održavanju je nepotpuna funkcionalna zavisnost atributa NAZPRED od složenog atributa BRIND, ŠIFRAPRED, za koju smo ranije pokazali da je redundantna funkcionalna zavisnost. Pošto važi slijedeće: BrInd, ŠifPred --->

NazivPred

BrInd

-/->

NazivPred

ŠifPred

--->

NazivPred

atribut NAZIVPRED je nepotpuno funkcionalno zavisan od složenog atributa BRIND, ŠIFPRED, jer je funkcionalno zavisan i od njega i od jednog njegovog dijela, od ŠPRED. Definicija Druge normalne forme zabranjuje postojanje ovakve zavisnosti. Relacija R je u Drugoj normalnoj formi (2NF) ako i samo ako je u 1NF i svi njeni 23 neključni atributi potpuno funkcionalno zavise od primarnog ključa.

22

B.Lazarević, Z.Marjanović, N.Aničić,S.Babarogić, Baze podataka, FON, Beograd 2008.

34

Neključni atributi (atributi koji nisu kandidati za ključ, niti dio kandidata za ključ) relacije prijava su NAZIVPRED i OCJENA, a primarni ključ je složeni atribut BRIND, ŠIFPRED. Kako je ranije pokazano atribut OCJENA je potpuno funkcionalno zavisan od primarnog ključa, a atribut NAZIVPRED nije. Zbog toga relacija PRIJAVA nije u 2NF. Svođenje na 2NF vrši se dekompozicijom na taj način što u jednoj projekciji ostavlja primarni ključ i svi atributi koji su potpuno funkcionalno zavisni od njega, a u drugim projekcijama se realizuju one funkcionalne zavisnosti koje su prouzrokovale nepotpune funkcionalne zavisnosti. Za navedeni primjer relacije PRIJAVA dekompozicija je: PRIJAVA1(BRIND, ŠIFRAPRED, OCJENA) PREDMET(ŠIFRAPRED, NAZIVPREDMETA) Iz definicije 2NF i definicije potpune funkcionalne zavisnosti očigledno je da je svaka relacija sa prostim primarnim ključem u 2NF, jer prosti ključ nema semantički moguć pravi podskup. Posmatrajmo relaciju STUDENT1(BRIND, IME, SEM, ŠIFSMJ, NAZIVSMJERA, IMERUK). BrInd Ime Sem ŠifSmj NazivSmjera ImeRuk 21 Zoran 5 01 Inf.Sistemi Zoran 21 Zoran 5 01 Inf.Sistemi Zoran 21 Zoran 5 01 Inf.Sistemi Zoran 77 Ana 7 01 Inf.Sistemi Zoran 77 Ana 7 01 Inf.Sistemi Zoran 36 Pero 4 02 Menadžment Petar 36 Pero 4 02 Menadžment Petar 36 Pero 4 02 Menadžment Petar 36 Pero 4 02 Menadžment Petar Tabela 34: Relacija Student1 Očigledno je da u ovoj relaciji postoji redundansa podataka (isto IMERUK i NAZIVSMJERA se pojavljuje uz svakog studenta upisanog na odgovarajući smjer) i da postoje anomalije u održavanju: •

Ne mogu se dodati informacije o novom smjeru dok ga neki student ne upiše.



Ako se iz relacije STUDENT1 izbaci student koji je jedini bio upisan na neki smjer, gube se informacije i o tom smjeru.



Ako se promjeni rukovodioc smjera atribut IMERUK treba promjeniti na onoliko mjesta koliko je studenata upisano na taj smjer.

Razlog za redundansu i anomalije u održavanju je postojanje tranzitivne funkcionalne zavisnosti (za koju smo pokazali da je redundantna) atributa IMERUK i NAZIVSMJERA od atributa BRIND. STUDENT1(BRIND, IME, SEM, ŠIFSMJ, NAZIVSMJERA, IMERUK). BrInd

--->

ŠifSmj

A

--->

B

ŠifSmj

--->

NazivSmjera

B

--->

C

BrInd

--->

NazivSmjera

A

--->

C

ŠifSmj

-/->

BrInd

B

-/->

A

23

B.Lazarević, Z.Marjanović, N.Aničić,S.Babarogić, Baze podataka, FON, Beograd 2008.

35

NazivSmjera

-/->

BrInd

C

-/->

A

i BrInd

--->

ŠifSmj

A

--->

B

ŠifSmj

--->

ImeRuk

B

--->

C

BrInd

--->

ImeRuk

A

--->

C

ŠifSmj

-/->

BrInd

B

-/->

A

ImeRuk

-/->

BrInd

C

-/->

A

Definicija Treće normalne forme zabranjuje postojanje ovakvih zavisnosti u relacijama. Definicija Treće normalne forme, je: Relacija R je u Trećoj normalnoj formi (3NF) ako i samo ako je u 2NF i ako svi njeni neključni atributi netranzitivno funkcionalno zavise od primarnog ključa. Zbog postojanja tranzitivne zavisnosti atributa IMERUK i NAZIVSMJERA od primarnog ključa BRIND relacija STUDENT1 nije u 3NF. Svođenje na 3NF vrši se dekompozicijom (bez gubljenja informacija) relacije u njene projekcije na taj način što se u jednoj projekciji ostavljaju primarni ključ i svi netranzitivno zavisni atributi, a u drugim projekcijama se realizuju funkcionalne zavisnosti koje su dovele do tranzitivnih zavisnosti. STUDENT2(BRIND, IME, SEM, ŠIFSMJ) SMJER(ŠIFSMJ, IMERUK, NAZIVSMJERA) U relaciji STUDENT1 atribut IMERUK zavisi i od atributa ŠIFSMJ, a ne samo od ključa BRIND. Tranzitivna zavisnost u nekoj relaciji postoji uvjek kada, osim funkcionalne zavisnosti atributa od ključa (jednoznačne činjenice o ključu), u njoj postoji i neka druga funkcionalna zavisnost između atributa (jednoznačne činjenice o nekom atributu koji nije ključ). Date neformalne definicije 2NF i 3NF otkrivaju suštinu postupka normalizacije. Naime, baza podataka je, kao što je rečeno, statički model realnog sistema. Samo ako se u njoj jasno prepoznaju objekti, veze i atributi objekata i veza u realnom sistemu, ona će biti pogodna za sve obrade podataka koje odgovaraju svim mogućim zahtjevima korisnika, odnosno neće prouzrokovati anomalije u održavanju, niti će dovoditi do problema u izradi programa za izvještavanje. Navedeni primjeri se očigledno odnose na realni sistem FAKULTET. U kontekstu datih primjera možemo reći da se sistem FAKULTET sastoji od objekata STUDENT2,

36

PREDMET, PRIJAVA1 i SMJER čija su svojstva opisana preko njima pripadajućih atributa. STUDENT2(BRIND, IME, SEM, ŠIFSMJ) SMJER(ŠIFSMJ, IMERUK, NAZIVSMJERA) PRIJAVA1(BRIND, ŠIFRAPRED, OCJENA) PREDMET(ŠIFRAPRED, NAZIVPREDMETA) Vidljivo je da su objekti PRIJAVA1 i PREDMET povezani atributom ŠIFRAPRED, te da su STUDENT2 i SMJER povezani atributom ŠIFSMJ. Objekti STUDENT2 i PREDMET su povezani vezom PRIJAVA1(atributima BRIND, ŠIFRAPRED). Ovako definisan sistem se jasno prepoznaje u modelu BP sa relacijama u 3NF (STUDENT2, PREDMET, SMJER i PRIJAVA1). Polazna relacija STUDENT, relacije STUDENT1 i PRIJAVA predstavljale su neku "mješavinu" objekata i veza realnog sistema, a ne posebne, jasno definisane objekte ili veze sa njima svojstvenim atributima. Postupak normalizacije svodi model BP na skup relacija od kojih svaka predstavlja neki osnovni objekat ili vezu u sistemu. Atributi takvih relacija su svojstveni atributi odgovarajućih objekata ili veza.

2.4

Boyce-Codd-ova normalna forma (BCNF)

Navedene definicije 2NF i 3NF je orginalno dao E.F.Codd, tvorac relacionog modela. Pokazalo se da ove definicije nisu dovoljno precizne (stroge), posebno u slučajevima kada relacija ima tzv "preklapajuće" kandidate za ključ (dva ili više složenih kandidata za ključ koji imaju barem jedan zajednički atribut). Analizirajmo ponovo relaciju PRIJAVA. PRIJAVA(BRIND, ŠIFRAPRED, NAZIVPREDMETA, OCJENA) U dosadašnjoj analizi ove relacije predpostavljali smo da važe slijedeće funkcionalne zavisnosti: BRIND, ŠIFRAPRED ---> NAZIVPREDMETA BRIND, ŠIFRAPRED ---> OCJENA ŠIFRAPRED ---> NAZIVPREDMETA) Jedini kandidat za ključ i primarni ključ je složeni atribut BRIND, ŠIFRAPRED. Neključni atributi su NAZIVPREDMETA i OCJENA. Pošto neključni atribut NAZIVPREDMETA nepotpuno funkcionalno zavisi od primarnog ključa, relacija PRIJAVA nije u 2NF. Međutim, pretpostavimo da sada postoji još i slijedeća funkcionalna zavisnost (da je NAZIVPREDMETA jednoznačan): NAZIVPREDMETA ---> ŠPRED U tom slučaju u relaciji PRIJAVA postoje dva složena i "preklapajuća" kandidata za ključ, BRIND, ŠIFRAPRED i BRIND, NAZIVPREDMETA. koji se preklapaju jer oba kandidata za ključ sadrže atribut BRIND.

37

Jedini neključni atribut bi sada bio OCJENA, pa pošto on potpuno funkcionalno zavisi od primarnog ključa (bilo koji od kandidata da je izabran), relacija PRIJAVA jeste u 2NF. BrInd ŠifPred NazivPred Ocjena 21 121 Matematika 7 21 323 Baze podataka 8 21 056 Programiranje 8 77 056 Programiranje 9 77 121 Matematika 10 36 323 Baze podataka 7 36 456 Mikroekonomija 9 36 442 Menadžment 6 36 121 Matematika 7 Tabela 35: Relacija Prijava jeste u 2NF ako je NAZIVPREDMETA jednoznačan Međutim, sve anomalije u ažuriranju i dalje ostaju! To znači da definicija 2NF (pa samim tim i 3NF) nije dovoljno precizna. Boyce-Codd-ova definicija uklanja te nepreciznosti. Za iskaz te definicije uvodi se i pojam determinante relacije. Determinanta relacije R je bilo koji atribut, prost ili složen, od koga neki drugi atribut u relaciji potpuno funkcionalno zavisi. Relacija R je u Boyce-Codd-ovoj normalnoj formi (BCNF) ako i samo ako su sve determinante u relaciji i kandidati za ključ. Označimo sve determinante (D) i sve kandidate za ključ (KK) relacije PRIJAVA (uz pretpostavku da važi i dodatno uvedena funkcionalna zavisnost NAZPRED ---> ŠPRED): BRIND, ŠIFRAPRED

---> NAZIVPREDMETA, OCJENA

(D)

(KK)

BRIND, NAZIVPREDMETA

---> ŠIFRAPRED, OCJENA

(D)

(KK)

ŠIFRAPRED

---> NAZIVPREDMETA

(D)

NAZIVPREDMETA

---> ŠIFRAPRED

(D)

Sve determinante nisu kandidati za ključ (npr. ŠIFRAPRED i NAZIVPREDMETA nisu kandidati) pa relacija nije u BCNF. Dekompozicijom, pri kojoj se iz relacije izvlače projekcije sa onim determinantama koje nisu kandidati za ključ, relacija se svodi na BCNF. PRIJAVA1(BRIND, ŠIFRAPRED, OCJENA) PREDMET(ŠIFRAPRED, NAZIVPREDMETA) Složeni, "preklapajući" kandidati za ključ su signal da relacija možda nije u BCNF. Međutim, može se pokazati da neka relacija i sa složenim, "preklapajućim" kandidatima za ključ može biti u BCNF.

2.5

Dekompozicija na zavisne i nezavisne projekcije

Dekompozicija relacije bez gubljenja informacija, sa ciljem da se ona svede na neku normalnu formu nije jednoznačan postupak. Na primjer, relaciju:

38

STUDENT1 (BRIND, IME, SEM, ŠIFSMJ, NAZIVSMJERA, IMERUK).

BrInd 21 21 21 77 77 36 36 36 36

Ime Zoran Zoran Zoran Ana Ana Pero Pero Pero Pero

Sem 5 5 5 7 7 4 4 4 4

ŠifSmj 01 01 01 01 01 02 02 02 02

NazivSmjera Inf.Sistemi Inf.Sistemi Inf.Sistemi Inf.Sistemi Inf.Sistemi Menadžment Menadžment Menadžment Menadžment

ImeRuk Zoran Zoran Zoran Zoran Zoran Petar Petar Petar Petar

Tabela 36: Relacija Student1 možemo svesti na 3NF na slijedeća dva načina: (a)

(b)

STUDENT2(BRIND, IME, SEM, ŠIFSMJ)

STUDENT2a(BRIND, IME, SEM, ŠIFSMJ)

SMJER(ŠIFSMJ, NAZIVSMJERA, IMERUK)

STUDSMJER(BRIND, IMERUK, NAZIVSMJERA) SMJER(ŠIFSMJ, IMERUK)

I relacije (a) i relacije (b) su u 3NF. (a.1.)

Svi neključni atributi relacije STUDENT2 netranzitivno funkcionalno zavise od ključnog atributa BRIND. BRIND ---> IME, IME -/-> SEM BRIND ---> IME, IME -/-> ŠIFSMJ BRIND ---> SEM, SEM -/-> ŠIFSMJ BRIND ---> SEM, SEM -/-> IME ...

(a.2.)

Svi neključni atributi relacije SMJER netranzitivno funkcionalno zavise od ključnog atributa ŠIFSMJ. ŠIFSMJ ---> NAZIVSMJERA, NAZIVSMJERA -/-> SEM ŠIFSMJ ---> SEM, SEM -/-> NAZIVSMJERA

(b.1.) Svi neključni atributi relacije STUDENT2a netranzitivno funkcionalno zavise od ključnog atributa BRIND. BRIND ---> IME, IME -/-> SEM BRIND ---> IME, IME -/-> ŠIFSMJ BRIND ---> SEM, SEM -/-> ŠIFSMJ BRIND ---> SEM, SEM -/-> IME ...

39

(b.2.) Svi neključni atributi relacije STUDSMJER netranzitivno funkcionalno zavise od ključnog atributa BRIND. BRIND ---> IMERUK, IMERUK -/-> NAZIVSMJERA BRIND ---> NAZIVSMJERA, NAZIVSMJERA -/-> IMERUK Međutim, projekcije (b) pokazuju određene anomalije u održavanju. Poseban problem predstavlja ažuriranje atributa IMERUK, odnosno promjena rukovodioca smjera. Za svaku vrijednost BRIND koja odgovara datoj vrijednosti ŠIFSMJ iz relacije STUDENT2a, mora se u relaciji STUDSMJER izvršiti ažuriranje atributa IMERUK. Projekcije (a) ne pokazuju te anomalije, održavanje se vrši nezavisno (posebno) u svakoj relaciji. Projekcije (a) se nazivaju nezavisne (ortogonalne) projekcije, a projekcije (b) su zavisne (povezane). Rissansen-ova teorema daje uslove pod kojima se neka relacija može dekomponovati na nezavisne projekcije. Projekcije R1 i R2 relacije R su nezavisne tada i samo tada kada: 1. Svaka funkcionalna zavisnost u R se može logički dedukovati iz funkcionalnih zavisnosti u R1 i R2 i 2. Zajednički atribut relacija R1 i R2 je kandidat za ključ barem u jednoj od 24 njih. Za projekcije (a) oba uslova Rissansen-ove teoreme su zadovoljena, a iz projekcije (b) u relaciji STUDSMJER se ne može dedukovati funkcionalna zavisnost ŠIFSMJ ---> IMERUK koja postoji u izvornoj relaciji STUDENT1.

2.6

Višenačne zavisnosti i Četvrta normalna forma

Do sada smo kao jedinu moguću zavisnost između atributa relacije tretirali razne vrste funkcionalnih zavisnosti. Međutim, postoje i mnoge druge zavisnosti između atributa u relaciji koje takođe mogu dovesti do anomalija u održavanju baze podataka. Najčešće se javljaju tzv. višeznačne zavisnosti. Posmatrajmo nenormalizovanu relaciju PROGRAM.

Predmet Inf.sistemi

Nastavnik Boris Zoran Sist.amaliza Mladen Zoran

Knjiga Martin Date DeMarco Sarson

Tabela 37: Tabela Program Semantika sistema je slijedeća: Jedan predmet predaje više nastavnika. Za jedan predmet se koristi više knjiga. Ne postoji nikakva veza između nastavnika i knjiga. (Ne zna se koji nastavnik koristi koje knjige, jednu ili više). Da bi se ova relacija dovela u 1NF i sačuvala semantika problema neophodno je da se u normalizovanoj relaciji nađu, za dati predmet i datog nastavnika, n-torke sa svim mogućim knjigama za taj predmet.

Predmet 24

Nastavnik Knjiga

B.Lazarević, Z.Marjanović, N.Aničić,S.Babarogić, Baze podataka, FON, Beograd 2008.

40

Inf.sistemi Inf.sistemi Inf.sistemi Inf.sistemi Sist.amaliza Sist.amaliza Sist.amaliza Sist.amaliza

Boris Boris Zoran Zoran Mladen Mladen Zoran Zoran

Martin Date Martin Date DeMarco Sarson DeMarco Sarson

Tabela 38: Relacija Program U obliku intenzije relacija PROGRAM se može napisati kao PROGRAM(PREDMET, NASTAVNIK, KNJIGA) Relacija PROGRAM je očigledno u BCNF (Zašto?). PREDMET, NASTAVNIK, KNJIGA

(D)

(KK)

Međutim, redundansa podataka je očigledna, pa samim tim postoje i anomalije u ažuriranju. Na primjer, ubacivanje informacije da se za predmet INF.SISTEMI koristi i knjiga ULLMAN, zahtjevalo bi ubacivanje tri nove n-torke, po jednu za svakog nastavnika koji predaje taj predmet. Očigledno je da relaciju PROGRAM treba dekomponovati na projekcije RASPORED I UDŽBENIK:

Predmet Inf.sistemi Inf.sistemi Sist.amaliza Sist.amaliza

Nastavnik Boris Zoran Mladen Zoran

Relacija Raspored

Predmet Inf.sistemi Inf.sistemi Sist.amaliza Sist.amaliza

Knjiga Martin Date DeMarco Sarson

Relacija Udžbenik

Dekompozicija je bez gubljenja informacija. Međutim, ona nije izvedena na bazi dosada datih pravila, relacija PROGRAM je u BCNF – u njoj postoji samo jedna kandidat za ključ a u njoj ne postoji ni jedna netrivijalna funkcionalna zavisnost. Veze koje postoje između atributa relacije PROGRAM nazivaju se višeznačnim vezama. Formalna definicija višeznačnih zavisnosti može se dati na slijedeći način: U relaciji R(A,B,C) postoji višeznačna zavisnost A ->-> B ako i samo ako kad god u njoj postoje n-torke i , postoje takođe i n-torke . Atributi A, B i C mogu biti složeni. Iz definicije višeznačne zavisnosti očigledno je da ako u relaciji R(A,B,C) postoji višeznačna zavisnost A ->-> B, tada pastoji i višeznačna zavisnost A ->-> C. Isto tako je očigledno da se višeznačna zavisnost može definisati u relaciji koja ima najmanje tri atributa. Da provjerimo relaciju Program:

25

B.Lazarević, Z.Marjanović, N.Aničić,S.Babarogić, Baze podataka, FON, Beograd 2008.

41

Ako postoji

Ako postoji

Predmet Nastavnik Knjiga Inf.sistemi Boris Martin



Predmet Nastavnik Knjiga Inf.sistemi Zoran Date



i

i

takođe postoji i

Predmet Nastavnik Knjiga Inf.sistemi Boris Date

takođe postoji i Tada A --> B

Dakle, Predmet --> Nastavnik

U navedenom primjeru relacije PROGRAM postoje slijedeće višeznačne zavisnosti: PREDMET -->--> NASTAVNIK i PREDMET -->--> KNJIGA Svaka funkcionalna zavisnost je istovremeno i višeznačna zavisnost, odnosno, funkcionalne zavisnosti su specijalan slučaj višeznačne zavisnosti u kome skup vrijednosti B za dati skup vrijednosti A ima tačno jednu vrijednost. Za praktičnu primenu može se dati i slijedeća, neformalna i nedovoljno precizna definicija 4NF: Relacija R je u 4NF ako u njoj nisu date dvije (ili više) nezavisne višeznačne 26 činjenice. Relacija PROGRAM nije u 4NF, jer u njoj postoje dvije nezavisne višeznačne činjenice. U njoj postoji višeznačna zavisnost PREDMET ->-> NASTAVNIK, a zavisnosti (PREDMET, NASTAVNIK) i (PREDMET, KNJIGA) nisu funkcionalne, odnosno atribut PREDMET nije nadključ relacije. Relacije RASPORED i UDŽBENIK su u 4NF jer u njima ne postoje višeznačne zavisnosti samim tim što su obje binarne relacije, odnosno obje sadrže samo po jednu višeznačnu činjenicu. Kako su višeznačne zavisnosti uopštenje funkcionalnih zavisnosti, svaka relacija koja je u 4NF je istovremeno i u BCNF. Obrnuto ne važi. Svođenje relacija u kojima postoje višeznačne zavisnosti na 4NF vrši se dekompozicijom ovih relacija bez gubljenja informacija. Fagin je dao uopštenje Heatove teoreme o dekompoziciji bez gubljenja informacija: Relacija R(A, B, C) može se bez gubljenja informacija dekomponovati na projekcije R1(A, B) i R2(A, C) ako i samo ako važi A ->-> B (što uključuje i A ->-> 27 C). 26 27

B.Lazarević, Z.Marjanović, N.Aničić,S.Babarogić, Baze podataka, FON, Beograd 2008. B.Lazarević, Z.Marjanović, N.Aničić,S.Babarogić, Baze podataka, FON, Beograd 2008.

42

2.7

Zavisnosti spajanja i Peta normalna forma (5NF)

Rečeno je da su višeznačne zavisnosti uopštenje funkcionalnih zavisnosti koje omogućuju predstavljanje semantički složenijih koncepata u modelu. Postoji još opštija forma zavisnosti, tzv. "zavisnost spajanja" (join dependency) koja u sebi obuhvata višeznačne, pa samim tim i funkcionalne zavisnosti. Ilustrovaćemo je na istom primjeru odnosa PREDMET, NASTAVNIK, KNJIGA, ali, sada, sa nešto izmjenjenom semantikom. Ranije smo pretpostavljali da u relaciji PROGRAM ne postoji nikakva veza između atributa NASTAVNIK i KNJIGA. Pretpostavimo sada da ova veza postoji, da jedan nastavnik može da koristi nula, jednu ili više knjiga i da se zna koji nastavnik koristi koje knjige (npr. na Informacionim sistemima BORIS koristi samo knjigu DATE, ZORAN i knjigu MARTIN i knjigu DATE, dok za Sistemsku analizu, ZORAN koristi samo knjigu SARSON, a MLADEN samo DEMARCO). Ekstenzija relacije PROGRAM u tom slučaju bi bila:

Predmet Inf.sistemi Inf.sistemi Inf.sistemi Sist.amaliza Sist.amaliza

Nastavnik Boris Zoran Zoran Mladen Zoran

Knjiga Date Martin Date DeMarco Sarson

Tabela 39: Relacija Program Relacija PROGRAM i sada ima isti oblik intenzije PROGRAM(PREDMET, NASTAVNIK, KNJIGA) ali sada jeste u 4NF, jer u njoj ne postoje višeznačne zavisnosti (Jedan PREDMET predaje više NASTAVNIKA, za jedan PREDMET se koristi više KNJIGA, ali sada KNJIGE zavise od NASTAVNIKA). Međutim, redundansa podataka i anomalije u ažuriranju i dalje postoje. Npr. promjana imena nastavnika ZORAN bi zahtjevala ažuriranje više redova tabele. Da bi se izbegla redundansa i istovremeno sačuvala nova semantika relacije PROGRAM očigledno je da je treba dekomponovati, bez gubljenja informacija, u slijedeće tri projekcije: RASPORED(PREDMET, NASTAVNIK) UDŽBENIK(PREDMET, KNJIGA) NAST-KNJ(NASTAVNIK, KNJIGA)

Predmet Inf.sistemi Inf.sistemi Sist.amaliz a Sist.amaliz a

Nastavni k Boris Zoran Mladen Zoran

Relacija Raspored

Predmet Inf.sistemi Inf.sistemi Sist.amaliz a Sist.amaliz a

Knjiga Martin Date DeMarc o Sarson

Relacija Udžbenik

Nastavni k Boris Zoran Zoran Mladen Zoran

Knjiga Date Martin Date DeMarc o Sarson

Relacija Nast-Knj

43

Specifična vrsta zavisnosti koja postoji u novoj verziji relacije PROGRAM se naziva zavisnost spajanja. Kažemo da su u relaciji PROGRAM atributi PREDMET, NASTAVNIK, KNJIGA vezani preko zavisnosti spajanja. U relaciji R(X, Y, ..., Z) postoji zavisnost spajanja ako i samo ako relacija R rezultuje iz prirodnog spajanja njenih projekcija po X,Y, ..., Z, gde su X,Y, ..., Z podskupovi atributa relacije R. Relacija R je u Petoj normalnoj formi ako i samo ako se svaka zavisnost spajanja može pripisati kandidatu za ključ. Relacija PROGRAM se može rekonstruisati iz njenih projekcija prirodnim spajanjem relacija NAST-KNJ i UDŽBENIK po atributu KNJIGA, a zatim prirodnim spajanjem tako dobijenog rezultata sa relacijom RASPORED po atributu NASTAVNIK. Kako atributi spajanja KNJIGA i NASTAVNIK nisu i kandidati za ključ relacije PROGRAM ona nije u 5NF. Kako je višeznačna zavisnost specijalan slučaj zavisnosti spajanja, ako je relacija u 5NF ona je sigurno i u 4NF, pa samim tim i u svim ostalim. Obrnuto ne važi. 5NF se često naziva i "projekcija-spajanje normalna forma".

2.8

Normalna forma ključeva i domena

Normalne forme su istorijski postepeno uvođene u teoriju relacionih baza podataka, počev od prve tri koje je definisao Codd, 1972. godine, preko Boyce-Godd-ove, 4NF u kojoj su funkcionalne zavisnosti uopštene u višeznačne do 5NF u kojoj su višeznačne zavisnosti uopštene u zavisnosti spajanja. Postavilo se pitanje postoje li dalja uopštenja zavisnosti atributa u relacijama i da li se može definisati neka nova (šesta, sedma, ...) normalna forma. R.Fagin je 1981. dao najopštiju definiciju normalne forme ključeva i domena (DK/NF) i pokazao je da relacija koja je u DK/NF ne prouzrokuje anomalije u održavanju, i obrnuto, da se relacija, koja ne prouzrokuje anomalije u ažuriranju, nalazi u DK/NF. Time je isključio potrebu za definisanjem novih normalnih formi. Međutim, koje se relacije mogu svesti na DK/NF i koji je opšti postupak tog svođenja, još je uvjek otvoreno pitanje. Relacija je u DK/NF ako je svako ograničenje na vrijednosti njenih atributa posljedica definicije ključeva i domena. Ilustrujmo primenu ove definicije na nekoliko primjera: (1) Relacija STUDENT1 nije u DK/NF zato što je u njoj definisano ograničenje da jedan smjer ima jednog rukovodioca (funkcionalna zavisnost ŠIFSMJ --> IMERUK), a to nije posljedica definicije ključa ove relacije niti nekog njenog domena.

BrInd 21 21 21 77 77 36 44

Ime Zoran Zoran Zoran Ana Ana Pero

Sem 5 5 5 7 7 4

ŠifSmj 01 01 01 01 01 02

NazivSmjera Inf.Sistemi Inf.Sistemi Inf.Sistemi Inf.Sistemi Inf.Sistemi Menadžment

ImeRuk Zoran Zoran Zoran Zoran Zoran Petar

36 36 36

Pero Pero Pero

4 4 4

02 02 02

Menadžment Petar Menadžment Petar Menadžment Petar

Tabela 40: Relacija Student1 (2) Relacija PRIJAVA nije u DK/NF zato što je u njoj definisano ograničenje da jedan predmet ima jedan naziv (funkcionalna zavisnost ŠPRED --> NAZPRED), a to nije posljedica definicije ključa ove relacije (BI, ŠPRED).

BrInd 21 21 21 77 77 36 36 36 36

ŠifPred 121 323 056 056 121 323 456 442 121

NazivPred Matematika Baze podataka Programiranje Programiranje Matematika Baze podataka Mikroekonomija Menadžment Matematika

Ocjena 7 8 8 9 10 7 9 6 7

Tabela 41: Tabela Prijava (3) Relacija PROGRAM nije u DK/NF jer zavisnost spajanja koja u njoj postoji nije posljedica definicije ključa ove relacije.

Predmet Inf.sistemi Inf.sistemi Inf.sistemi Sist.amaliza Sist.amaliza

Nastavnik Boris Zoran Zoran Mladen Zoran

Knjiga Date Martin Date DeMarco Sarson

Tabela 42: Relacija Program Ako je relacija u DK/NF ona je sigurno u svim ostalim. Međutim, direktna primjena ove definicije praktično nije moguća, jer otkrivanje "ograničenja" u relacijama zahtjeva, u osnovi, otkrivanje funkcionalnih, višeznačnih i zavisnosti spajanja, a to praktično znači primjenu svih navedenih definicija.

45

3

SQL (Structured Query Language)

SQL je najčešće i najšire implementiran jezik relacionih baza podataka. On omogućava ne samo upravljanje i manipulisanje podacima u okviru jedne baze podataka, već i upravljanje samom bazom podataka. SQL je 1986 godine postao američki nacionalni standard (ANSI X3:135 - 1986), a od 1987 godine postao je međunarodni ISO standard. Počeo je da se razvija u IBM-u, ranih sedamdesetih godina, pod imenom SEQUEL. (Structured English Query Language) i mnogi još i danas skraćenicu SQL izgovaraju kao "sequel". Zbog toga što je postao standard, danas je SQL jezik koji se koristi u velikoj većini relacionih baza podataka. Od svog nastanka do danas, ovaj standard je prošao kroz 3 velike i nekoliko manjih revizija, tokom kojih su mu dodavana poboljšanja i različite nove mogućnosti. Ranije je bilo uobičajeno da se revizije ovog jezika obilježavaju godinama nastanka ili nadimcima, a pojedini autori i proizvođači umjesto nadimka koriste izraz dijalekt. Godina

Naziv

Nadimak

Dijalekt

1986

SQL-86

SQL-87 (zbog ISO standarda)

SQL-1

1989

SQL-89

FIPS 127-1

1992

SQL-92

SQL2

SQL-2

1999

SQL-99

SQL3

SQL-3

2003

SQL:2003

2006

SQL:2006

2008

SQL:2008

Tabela 43: Istorijski razvoj SQL-a SQL je homogeno relacioni jezik, što znači da može da se koristi i interaktivno, sa terminala i u okviru standardnih programskih jezika (COBOL, PL/I i drugih), za komunikaciju sa bazom podataka. Pored konstrukcija analognih relacionoj algebri ili relacionom računu (koje su osnove jezika za rukovanje podacima) SQL sadrži i konstrukcije za opisivanje baze podataka (jezik za opis podataka), operacije koje omogućuju vezivanje SQL-a sa nekim standardnim jezikom (CURSOR operacije), kao i kontrolne konstrukcije za upravljanje konkurentnim obradama, oporavak baze podataka, definisanje zaštite podataka i integriteta baze podataka. Važno je napomenuti da pomenuti standard i njegove revizije proizvođači posmatraju više kao preporuku nego kao pravilo. Proizvođači imaju slobodu da implementiraju unapređenja koja standard još nije propisao. S druge strane, proizvođači često u nekoj verziji proizvoda neće obuhvatiti sve preporuke nekog konkretnog standarda, već će proizvod poboljšavati i usklađivati sa standardima u etapama, iz verzije u verziju svoga proizvoda. Zbog toga proizvođači najčešće pri navođenju karakteristika nekog DBMS-a navode izraze poput „bisko prijanja uz standard SQL-92”, „implementira brojne mogućnosti usklađene sa standardom SQL-1999” isl. Međutim, mora se voditi računa o činjenici da ni jedan proizvođač ne poštuje standard u potpunosti – ako naučite da koristite Oracleov SQL, ne znači da ćete odmah znati da koristite i Firebird ili MySQL.

46

3.1

Oracle Express DBMS - Instalacija i alati za administraciju

Oracle Database 10g Express Edition (Oracle Database XE, često i Oracle Express ili samo Oracle XE) je smanjeno izdanje Oracle Database 10g sistema. Međutim, ovo izdanje je potpuno besplatno, a može biti instalirano na bilo koju mašinu na kojoj se nalazi 32-bitna verzija Windows (Windows 2000, Windows server 2003 ili Windows XP sa SP1) ili Linux operativnog sistema. Kako se radi o smanjenom izdanju, u njega su ugrađena određena ograničenja. Konkretno, u ovom izdanju na raspolaganju nam stoji prostor veličine do 4GB korisničkih podataka. Slijedeća dva ograničenja odnose se na ograničavanje brzine rada ovakvog sistema, jer će on koristiti maksimalno do 1GB RAM memorije (čak i ako na računaru/serveru imate mnogo više) i pri tome će koristiti samo jedan procesor. Velike prednosti korištenja Oracle XE 10g leže u činjenici da potpuno besplatno dobijamo Oracle sistem u malom, koji je kompatibilan sa komercijalnom verzijom istog proizvođača. Kako je Oracle Database XE izgrađen na istom izvornom kodu kao i komercijalna verzija Oracle Database 10g Release 2, aplikacije razvijene na ovoj platformi mogu jednostavno biti prenesene na neko od komercijalnih izdanja. Instalaciju ovog RDBMS-a moguće je preuzeti sa lokacije http://www.oracle.com/technetwork/database/express-edition/downloads/index.html. Prilikom instalacije servera, postupak je u slučaju operativnog sistenma Windows prilično jednostavan. Instalaciona procedura će Vam ponuditi podrazumjevane (default) vrijednosti koje je, u ranoj fazi upoznavanja sa ovim alatom najbolje prihvatiti. Prilikom instalacije, instalaciona procedura će Vam tražiti da unesete administratorski PASSWORD koji ćete koristiti za pristup sistemu (za naloge SYS i SYSTEM), koji morate upamtiti ili zapisati. Nakon instalacije, administracija sistema se vrši putem interfejsa nekog od čitača weba, poput Internet Explorera ili Mozilla Firefoxa. U adresnu traku dovoljno je upisati http://127.0.0.1:8080/apex ili http:// localhost:8080/apex. Web interfejsu možemo pristupiti i pomoću Windowsowog Satrt Menija: Start -> Oracle Database 10g Express Edition -> Go To Database Home Page.

47

Da bi se prijavili na sistem, koristićemo nalog SYS i lozinku (PASSWORD) koju smo prijavili (i zapamtili) tokom instalacije. Nakon što ispravno unesemo korisničko ime i lozinku, doći ćemo do osnovne stranice (Home Page) Oracle Expressa.

Prvo pokretanje tek instaliranog Oracle Expressa ćemo iskoristiti da se upoznamo sa administracijom Oracle Expressa. Nalozi SYS i SYSTEM su posebni nalozi koji služe samo za administraciju sistema. Da bi kreirali vlastite aplikacije, u Oracle Expressu se moramo prijaviti kao “običan” korisnik. Tek instaliran Oracle XE dolazi sa instaliranim jednim, podrazumjevanim korisnikom pod nazivom HR. Nalog HR se instalira sa vlastitom šemom u kojoj se nalazi određeni broje tablela koje mogu da posluže kao primjeri kreiranja i manipulacije podacima. Međutim, ovaj nalog se zbog sigurnosnih razloga, instalira kao „zaključan”. Za otključavanje podrazumjevanog naloga HR, potrebno je kliknuti na ikonu Administration, a zatim na ikonu Database Users. U prozoru Manage Database Users, nalazi se jedino ikona naloga HR, jer je to jedini nalog koji je u ovom momentu kreiran.

Ako kliknemo na ikonu naloga HR, dolazimo do prozora User, koji nam omogućava unošenje PASSWORDA i otključavanje navedenog naloga:

48

Za lozinku bi, kao u Oracle-ovim tutorijalima, mogli odabrati „hr” (malim slovima), i unijeti u oba polja za unos lozinke istu lozinku. Zatim u drop-down box-u Account Status moramo odabrati Unlocked i potom pritisnuti dugme Alter User. U ovom momentu nećemo obrađivati ostale opcije koje su nam dostupne za administraciju nekog naloga. Kako smo u ovom momentu prijavljeni kao poseban nalog SYS, da bi mogli da počnemo da radimo na kreiranju i manipulaciji podacima, najprije ćemo se odjaviti sa sistema, pomoću ikone Logout.

Pri slijedećem prijavljivanju na sistem, koristićemo nalog HR i njemu dodjeljenu lozinku.

3.2

Firebird DBMS - Instalacija i alati za administraciju

Firebird je open source relacioni sistem za upravljanje bazama podataka koji je moguće 28 instalirati na Linux, Windows i brojne Unix platforme. Ovaj RDBMS je nastao iz Borlandovog InterBase-a 2000. godine, kada je Borland objavio izvorni kod InterBasea. U februaru 2004. godine, objavljena je verzija 1.5 ovog servera, koja je počela da se

28

Relational Database Management System

49

sve više odvaja od Borlandovog Interbase-a. Trenutno stabilna verzija (oktobar 2010.) Firebirdovog servera je 2.5. Instalaciju ovog RDBMS-a moguće je preuzeti sa lokacije http://www.firebirdsql.org/. Sama instalacija je u slučaju operativnog sistenma Windows vrlo jednostavna. Firebirdova instalaciona procedura će Vam ponuditi podrazumjevane (default) vrijednosti koje je, u ranoj fazi upoznavanja sa ovim alatom najbolje prihvatiti. Što se alata za administraciju tiče, uz Firebirdovu instalaciju isporučuju se samo programi koji rade u konzoli, poput GSEC programa za administraciju korisnika ili ISQL konzole za kreiranje tabela i upita. Prva nešto bolja alternativa ovom programu je FSQL i njegova Windows varijanta WFSQL, koji su besplatno dostupni sa adrese http://www.volny.cz/iprenosil/interbase/fsql.htm. Mnogo ugodniji rad u grafičkom radnom okruženju može nam pružiti FlameRobin koji se besplatno može preuzeti sa adrese http://www.flamerobin.org/. FlameRobin je alat za administraciju Firebird RDBMS-a koji je implementiran za Linux, Windows, Mac OS X, FreeBSD i Solaris platforme. Među komercijalnim alatima koji su namjenjeni za administraciju ovog RDBMS-a, izdvojićemo IBExpert kompanije HK-Software i EMS SQL Manager for InterBase/Firebird Freeware. Personalne verzije ograničenih mogućnosti ovih alata mogu se besplatno preuzeti sa adrese http://ibexpert.net/ibe/ i http://www.sqlmanager.net/products/ibfb/manager. Nakon instalacije Firebird RDBMS-a, podrazumjevani korisnik - administrator je sysdba, dok je njegova lozinka (password) masterkey (odnosno masterke). Da bi se osigurali od neovlaštenog pristupa podacima, najbolje je odmah nakon instalacije izmjeniti podrazumjevanu lozinku pomoću programa GSEC koji se izvršava u komandnoj liniji: C:\Firebird_2_1\bin> gsec –user sysdba -password masterkey GSEC> modify SYSDBA -pw NEW_PASS Primjer 1: Izmjena lozinke administratora sysdba pomoću programa GSEC Kreiranje novog korisnika vrši se pomoću komande add: GSEC> add elvis -pw presley Primjer 2: Kreiranje korisnika pomoću programa GSEC Da bi dobili listu korisnika, koristimo komandu display: GSEC> display user_name uid gid full name ---------------------------------------------SYSDBA 0 0 Sql Server Administrator ELVIS 0 0 Primjer 3: Lista korisnika u programu GSEC Kako vidimo, pored korisničkog imena (user_name) prikazana su polja uid, gid i full name. Polja uid i gid nisu obavezna, a predstavljaju Unix-ov korisnički ID i broj korisničke grupe koji se može koristiti na nekim Posix platformama. Kolona full name je izvedena kolona, koja se formira od vlastitog imena (fname), srednjeg imena (mname) i prezimena (lname): GSEC> add mirko -pw mirkan -fname Mirko -mname S. -lname Kojotovski GSEC> display user_name uid gid full name ---------------------------------------------SYSDBA 0 0 Sql Server Administrator

50

ELVIS 0 0 mirko 0 0 Mirko S. Kojotovski Primjer 4: Korisnici prikazani pomoću programa GSEC Podatake o jednom korisniku možemo dobiti pomoću komande display ime_korisnika: GSEC> display elvis user_name uid gid full name ---------------------------------------------ELVIS 0 0 Primjer 5: Display ime_korisnika u programu GSEC Izmjena podataka o nekom korisniku moguća je pomoću komande mo[dify]: GSEC> modify elvis -fname Elvis -pw vegas display elvis user_name uid gid full name ---------------------------------------------ELVIS 0 0 Elvis Primjer 6: Izmjena korisnika u programu GSEC Uslužni program ISQL možemo pokrenuti iz Firebirdovog menija (ako se radi o Windows XP operativnom sistemu, Start->Program files->FirebirdXX) ili iz komandne linije, iz bin direktorijuma u kojem se nalazi instalacija Firebirda. Da bi kreirali našu prvu bazu podataka, koristićemo uslužni program ISQL i iskaz CREATE DATABASE: C:\Firebird_2_1\bin> ISQL -u sysdba -p masterkey Use CONNECT or CREATE DATABASE to specify a database SQL> create database ‘c:\test.fdb’; Primjer 7: Kreiranje baze podataka pod imenom Test.fdb pomoću programa ISQL.exe Kako je iz navedenog iskaza vidljivo, nova baza podataka pod imenom test.fdb nalazi se u korjenskom (root) direktorijumu c diska. Bitno je primjetiti da se Firebirdove baze podataka mogu nalaziti bilo gdje u stablu direktorijuma. Npr. iskaz create database ‘c: \BazePodataka\test.fdb’; kreirao bi bazu u (postojećem) direktorijumu BazePodataka na C disku. Da bi završili rad u uslužnom programu ISQL, unijećemo komandu quit: C:\Firebird_2_1\bin> ISQL -u sysdba -p masterkey Use CONNECT or CREATE DATABASE to specify a database SQL> quit; C:\Firebird_2_1\bin> Primjer 8: Kraj rada u uslužnom programu ISQL FlameRobin je open source projekat koji se razvija nezavisno od Firebird projekta. Iako je ISQL jedini alat za administraciju baza podataka koji se isporučuje uz samu instalaciju Firebirda, na Web stranici projekta se preporučuje kao „gotovo” zvanični alat za administraciju. Nakon preuzimanja, instalacija ovoga alata je vrlo jednostavna i dovoljno intuitivna, tako je nećemo posebno objašnjavati. Nakon pokretanja, dobijamo osnovni prozor ovog programa:

51

Slika 15: Osnovni prozor alata FlameRobin Kreiranje nove baze podataka u radnom okruženju FlameRobina počinje izborom stavke Create new database iz menija database:

Slika 16: FlameRobin – kreiranje nove baze podataka Nakon ovoga, pojavljuje se novi dijalog u kojem u polje Database path unosimo ime i putanju do novokreirane baze podataka i njeno ime, u polje Display name ime preko kojeg ćemo pristupati bazi iz Flame Robina.

52

Slika 17: Kreiranje nove baze podataka – FlameRobin Iako program FlameRobin može da verifikuje pristup na nekoliko različitih načina, prilikom kreiranja nove baze podataka moramo mu dati korisničko ime i password (Authentication: Use saved user name and password). Nakon toga, u polje User name unosimo nekog korisnika (npr. elvis) a u polje Password njegovu lozinku (npr. vegas). Nakon što kliknemo na dugme Create, baza pod imenom Test2.fdb će biti kreirana u odabranom direktorijumu i istovremeno će biti registrovana i postaće vidljiva u osnovnom prozoru FlameRobina.

Slika 18: Baza test2 u osnovnom prozoru FlameRobina Da bi se povezali na novonapravljenu bazu podataka, dovoljno je da dvokliknemo na njeno simboličko ime u osnovnom prozoru FlameRobina.

53

Slika 19: Osnovni prozor FlameRobina povezan na bazu Kako smo već napomenuli, postoje brojni drugi programi za administraciju ovog SUBPa koji imaju veoma dobar grafički interfejs i brojne napredne mogućnosti. Međutim, da bi se što bolje upoznali sa osnovama SQL-a, za početak ćemo koristiti FlameRobin i njegov SQL editor koji se nalazi u meniju Database-Run a query....

Slika 20: Meni Database – Run a query

54

Nakon što izaberemo ovu stavku, dobićemo novi prozor u koji možemo unostiti različite SQL upite. A da bi mogli da počnemo sa unosom upita, moramo se upoznati sa SQL jezikom.

55

3.3

Kreiranje i modifikacija tabela

U svakom SQL okruženju, tabele su osnovna jedinica upravljanja podacima. Prije bilo koje operacije nad nekom tabelom, ta tabela mora biti kreirana. SQL standard (zaključno sa verzijom 2006) obezbjeđuje nam 3 komande za kreiranje, mijenjanje i brisanje tabela. Tabelu možemo kreirati pomoću iskaza CREATE TABLE, da bi izmjenili njenu definiciju možemo koristiti iskaz ALTER TABLE, a za njeno brisanje predviđen je iskaz DROP TABLE. Među nabrojanim iskazima, daleko najkomplikovaniju sintaksu ima iskaz CREATE TABLE – kako zbog brojnih tipova tabela koje su podržane od SQL-a, tako i zbog činjenice da definicija neke tabele može uključivati brojne elemente. Međutim, bez obzira na navedenu kompleksnost, kada jednom savladamo postupak, kreiranje neke tabele je prilično jednostavan posao.

3.3.1

Uvod u kreiranje SQL tabela

SQL podržava tri tipa tabela: bazne tabele, izvedene tabele i tabele nastale iz pogleda (view). Većina osnovnih tabela su objekti baze podataka koji drže podatke. Osnovni oblik iskaza za kreiranje bazne tabele je: CREATE TABLE ime-bazne-tabele ( kolona_1 tip_kolone_1 {,kolona_n tip_kolone_n} [, def_prim_kljuca] [, def_spolj_kljuca_1 {, def_spolj_kljuca_n}]) Sintaksa 1: Jednostavna sintaksa iskaza CREATE TABLE Prikazana sintaksa predstavlja samo osnovu iskaza CREATE TABLE. Ovaj iskaz je inače mnogo komplikovaniji – u standardu SQL:2006 on zauzima oko 38 strana. Prva linija prikazanog iskaza služi za imenovanje tabele – podacima koji će kasnije biti smješteni u ovakvoj tabeli ćemo pristupati isključivo preko njenog imena. U drugoj liniji u prikazanoj u sintaksi navodimo kolone i odgovarajuće tipove podataka od kojih će tabela biti sastavljena. PRIMJER 4: Slijedećim upitom kreiraćemo novu tabelu pod imenom ODJELJENJE CREATE TABLE ODJELJENJE ( ODJELJENJE_ID integer, NAZIV char(20), GRAD char(20) ); Kod 1: Jednostavan primjer kreiranja tabele U prikazanom primjeru tabeli smo dali ime ODJELJENJE. Njenoj koloni ODJELJENJE_ID dodjelili smo tip podatka integer, dok smo kolonama NAZIV i GRAD dodjelili tip podatka char(20). Da bi mogli da nastavimo sa diskusijom vezanom za kreiranje tabela, moraćemo se upoznati sa osnovnim SQL tipovima podataka.

3.3.1.1 Najčešće korišteni tipovi podataka Iako ćemo se u narednim poglavljima podrobnije upoznati sa SQL tipovima podataka, ovdje ćemo se ukratko upoznati sa najčešće korištenim SQL tipovima podataka. INTEGER ili INT, 32-bitni cijeli broj; SMALLINT, 16-bitni cijeli broj; BIGINT, 64-bitni cijeli broj;

56

DECIMAL(p,q) ili DEC(p,q), broj predstavljen u fiksnom zarezu; p je ukupni broj cifara decimalnog broja, dok je q broj cifara razlomljenog dijela (1 Veće od >= Veće ili jednako < Manje od 1986 Kod 43: Jednostavan SELECT upit sa WHERE klauzulom Rezultirajuća tabela bi bila: IME_UMJETNIKA NAZIV_CDA GODINA_KOPIRAJTA Bobby McFerrin Dont Worry, Be Happy 1988 Tabela 59: Rezultirajuća tabela U prethodnom primjeru smo vidjeli uticaj operatora veće od (>) u uslovu (predikatu) WHERE klauzule. Već smo naveli da se u WHERE klauzuli može kombinovati i po nekoliko uslova koji se tada odvajaju operatorima AND i OR. Takođe, dozvoljeno je i korištenje operatora NOT nad bilo kojim uslovom u WHERE klauzuli. PRIMJER 25: Ponovo ćemo posmatrati tabelu CD_INVENTAR u kojoj se nalaze slijedeći podaci: IME_UMJETNIKA NAZIV_CDA GODINA_KOPIRAJTA Bobby McFerrin Dont Worry, Be Happy 1988 Chris De Burgh Various - The Greatest Hits Of 1986 1986 Double Various - The Greatest Hits Of 1986 1986 Tina Turner Private Dancer 1984

88

Tabela 60: Podaci u tabeli CD_INVENTAR Ako bi postavili upit select * from CD_INVENTAR WHERE (GODINA_KOPIRAJTA < 1986) OR (GODINA_KOPIRAJTA > 1987) Kod 44: SELECT upit sa više uslova povezanih OR operatorom Rezultirajuća tabela bi bila: IME_UMJETNIKA NAZIV_CDA GODINA_KOPIRAJTA Bobby McFerrin Dont Worry, Be Happy 1988 Tina Turner Private Dancer 1984 Tabela 61: Rezultirajuća tabela Ako bi nad tabelom sa prikazanim podacima postavili slijedeći upit: select * from CD_INVENTAR WHERE NOT (GODINA_KOPIRAJTA = 1986) Kod 45: SELECT upit sa NOT operatorom Rezultirajuća tabela bi bila: IME_UMJETNIKA NAZIV_CDA GODINA_KOPIRAJTA Bobby McFerrin Dont Worry, Be Happy 1988 Tina Turner Private Dancer 1984 Tabela 62: Rezultirajuća tabela U prethodnim primjerima vidjeli smo da na svaki red tabele možemo gledati kao na izraz Bulove algebre koji vraća vrijednosti tačno (T) ili netačno (F). Međutim, u prethodnim primjerima nismo spominjali NULL vrijednost - koncept kojim označavamo nedostatak vrijednosti ili još nepoznatu vrijednost. Da bi objasnili uticaj NULL vrijednosti, pogledaćemo slijedeći primjer: PRIMJER 26: Ponovo ćemo posmatrati tabelu CD_INVENTAR u kojoj se nalaze npr. slijedeći podaci: IME_UMJETNIKA NAZIV_CDA GODINA_KOPIRAJTA Bobby McFerrin Dont Worry, Be Happy 1988 Chris De Burgh Various - The Greatest Hits Of 1986 1986 Double Various - The Greatest Hits Of 1986 1986 Tina Turner Private Dancer 1984 Lou Reed New York NULL Tabela 63: Podaci u tabeli CD_INVENTAR Ako bi postavili upit select * from CD_INVENTAR WHERE NOT (GODINA_KOPIRAJTA = 1986) Kod 46: SELECT upit sa NOT operatorom Rezultirajuća tabela bi bila: IME_UMJETNIKA NAZIV_CDA GODINA_KOPIRAJTA Bobby McFerrin Dont Worry, Be Happy 1988 Tina Turner Private Dancer 1984 Tabela 64: Rezultirajuća tabela Zadatak upita u prethodnom primjeru bio je da eliminiše sve redove tabele u kojima je kao godina kopirajta navedena 1986. godina. Za prva četiri prikazana reda, rezultati su jednostavni. Osnovno pitanje je na koji način NULL vrijednost (još nepoznata

89

vrijednost) učestvuje u Bulovoj algebri? Zbog toga ćemo ranije prikazanu tabelu sa izračunavanjem uslova proširiti na slijedeći način: IME_UMJETNIKA

NAZIV_CDA

GODINA_KOPIRAJTA

Bobby McFerrin

Don't Worry, Be Happy Various - The Greatest Hits Of 1986 Various - The Greatest Hits Of 1986 Private Dancer New York

Chris De Burgh Double Tina Turner Lou Reed

1988

REZ1 Godina=1986 F

REZ2 NOT REZ1 T

1986

T

F

1986

T

F

F Nepoznato

T Nepoznato

1984 NULL

Tabela 65: Izračunavanje uslova Svaki red rezultirajuće tabele formira se obradom uslova u dva koraka: najprije se testira da li je vrijednost kolone GODINA_KOPIRAJTA jednaka 1986, pa se onda robijeni međurezultat (REZ_1) komplementira da bi se dobio konačni rezultat REZ_2. Kako se za donji red (Lou Reed, New York, NULL) u međurezultatu dobija nepoznata vriojednost (NULL), njenim komplementiranjem dobijamo ponovo nepoznatu vrijednost. Kako ova vrijednost nije logička jedinica (T), ovaj red se neće pojaviti u rezultirajućoj tabeli. Generalno, tabela istinitosti Bulovog NOT operatora u SQL-u ima nešto drugačiju formu nego tabela koju smo upoznali u npr. Predmetu Arhitektura i funkcija računara:

A 0 1 NULL

NOT A 1 0 NULL

Tabela 66: Tabela istinitosti za NOT operator Slijede i tabele istinitosti za operacije AND i OR:

A 0 0 1 1 NULL 0 1 NULL

B 0 1 0 1 0 NULL NULL 1

AND 0 0 0 1 NULL NULL NULL NULL

Tabela 67: Tabela istinitosti za AND operator34

3.5.3

A 0 0 1 1 NULL 0 NULL 1

B 0 1 0 1 0 NULL 1 NULL

OR 0 1 1 1 NULL NULL NULL NULL

Tabela 68: Tabela istinitosti za OR operator

Upotreba člana (klauzule) GROUP BY

Slijedeća klauzula u SELECT iskazu je GROUP BY klauzula. Funkcija ove klauzule je da grupiše podatke u rezultatu upita da bi omogućila sumarni pregled podataka. Klauzula GROUP BY može biti uključena u SELECT iskaz bez obzira da li je u njemu specificirana WHERE klauzula. Pojednostavljena sintaksa GROUP BY klauzule je: 34

A.Oppel, R.Sheldon, A begginers guide for ANSI SQL 2006, McGraw Hill, 2009

90

SELECT FROM [WHERE...] GROUP BY [, < stavka_za_grupisanje [..]]; Sintaksa 16: Sintaksa GROUP BY klauzule GROUP BY klauzula zahtjeva particionisanje redova u skupove sa jednakim vrijednostima po stavkama_za_grupisanje. Grupa se formira grupisanjem (agregacijom) podataka navedene tabele koji se u tabeli potencijalno ponavljaju i koji se mogu 35 grupisati po određenom kriterijumu. Kriterijum grupisanja se navodi nakon ključne riječi GROUP BY stavkama za grupisanje. Particionisanje redova u skupove zahtjeva da lista polja navedena nakon SELECT klauzule bude jednaka listi navedenoj nakon GROUP BY klauzule ili se moraju koristiti agregatne funkcije. Da bi shvatili ponašanje GRUOP BY klauzule, prodiskutovaćemo je kroz slijedeći primjer. PRIMJER 27: Ponovo ćemo posmatrati tabelu CD_INVENTAR u kojoj se nalaze slijedeći podaci: IME_UMJETNIKA NAZIV_CDA GODINA_KOPIRAJTA Bobby McFerrin Dont Worry, Be Happy 1988 Chris De Burgh Various - The Greatest Hits Of 1986 1986 Double Various - The Greatest Hits Of 1986 1986 Tina Turner Private Dancer 1984 Lou Reed New York NULL Tabela 69: Podaci u tabeli CD_INVENTAR Ako bi postavili upit select GODINA_KOPIRAJTA from CD_INVENTAR GROUP BY GODINA_KOPIRAJTA Kod 47: Jednostavan primjer GROUP BY klauzule Rezultirajuća tabela bi bila: GODINA_KOPIRAJTA NULL 1984 1986 1988 Tabela 70: Rezultirajuća tabela Međutim, ako bi pokušali namjerno da postavimo slijedeći pogrešan upit: select GODINA_KOPIRAJTA, IME_UMJETNIKA from CD_INVENTAR GROUP BY GODINA_KOPIRAJTA Kod 48: Pogrešno postavljen upit sa GROUP BY klauzulom U slučaju prethodnog, namjerno pogrešno postavljenog upita, od DBMS-a bi dobili poruku o grešci: /* Oracle Express 10g*/ ORA-00979: not a GROUP BY expression /* Firebird 2.1 */ Invalid token. 35

H.Borrie, The Firebird Book: A Reference for Database Developers, H. Borrie and IBPhoenix, 2004

91

Dynamic SQL Error. SQL error code = -104. Invalid expression in the select list (not contained in either an aggregate function or the GROUP BY clause). Kod 49: Pogrešno postavljen upit sa GROUP BY klauzulom Navedena greška je rezultat činjenice da smo u okviru SELECT klauzule naveli naslove dvije kolone, dok smo kao uslov grupisanja naveli samo kolonu GODINA_KOPIRAJTA. Da bi mogli da navedemo više kolona u okviru SELECT klauzule, morali bi da koristimo neku od agregatnih funkcija. Da bi demonstrirali ispravan način pisanja ovakvog upita, tabelu CDISKOVI ćemo najprije isprazniti pomoću iskaza DELETE, a zatim ćemo unijeti slijedeće podatke delete from CDISKOVI; /* najprije brisemo sve redove iz tabele */ insert into CDISKOVI values(1, 'Tina Turns the Country On', 1, 5); insert into CDISKOVI values(2, 'Acid Queen', 2, 6); insert into CDISKOVI values(3, 'Unchain My Heart', 2, 8); insert into CDISKOVI values(4, 'Tina Turns the Country On', 2, 2); Kod 50: Popunjavanje tabele CDISKOVI podacima Iskaz DELETE ćemo detaljnije upoznati nešto kasnije. Za sada je dovoljno da upamtimo da prvi upit vbriše sve redove tabele CDISKOVI. Sadržaj tabele CDISKOVI sada je: CDISK_ID NAZIV_CDISKA ID_IZDAVACA 1 Tina Turns the Country On 1 2 Acid Queen 2 3 Unchain My Heart 2 4 Tina Turns the Country On 2 Tabela 71: Tabela CDISKOVI sa podacima Ako bi postavili upit:

ZALIHA 5 6 8 2

select NASLOV_CDISKA, Sum(ZALIHA) as TOTAL from CDISKOVI GROUP BY NASLOV_CDISKA Kod 51: Primjer GROUP BY klauzule Rezultat prethodnog upita bio bi: NAZIV_CDISKA TOTAL Acid Queen 6 Tina Turns the Country On 7 Unchain My Heart 8 Tabela 72: Rezultirajuća tabela Primjenom agregatne funkcije SUM dobili smo sume svih albuma koje se nalaze na zalihama čak i ako su albumi objavljeni od strane različitih izvođača, pri čemu je kao kriterijum grupisanja odabran naslov albuma.

92

U agregatne funkcije spadaju SUM, koja daje ukupan zbir po određenoj koloni, zatim MAX i MIN, koji vraćaju najveću i najmanju vrijednost u koloni, respektivno. Kompletnom listom agregatnih funkcija pozabavićemo se nešto kasnije. Generalno, treba usvojiti slijedeća pravila pri pisanju GROUP BY klauzule: •

Kolona ili izraz koji nisu u sastavu nekog agregata ne mogu biti navedene u listi kolona nakon SELECT klauzule, ako nisu istovremeno navedene nakon GROUP BY klauzule,



Agregat koji operiše nad bilo kojom kolonom baze podataka može biti naveden u listi kolona nakon SELECT klauzule, čak i ako nije naveden nakon GROUP BY klauzule.

Radi potpunijeg uvida u način funkcionisanja GROUP BY klauzule, pogledajmo slijedeći primjer: PRIMJER 28: Kreiraćemo novu tabelu pod nazivom ZALIHA_DISKOVA: create Table ZALIHA_DISKOVA ( KOMPAKT_DISK Varchar(60), KATEGORIJA Varchar(20), CIJENA Numeric(5,2), KOMADA integer ); Kod 52: Kreiranje tabele ZALIHA_DISKOVA Korištenjem iskaza INSERT INTO kojeg smo ranije upoznali, popunićemo tabelu određenim podacima: insert into ZALIHA_DISKOVA (KOMPAKT_DISK, KATEGORIJA, CIJENA, KOMADA) values ('Negativ', 'Vokal', 16.99, 13); insert into ZALIHA_DISKOVA (KOMPAKT_DISK, KATEGORIJA, CIJENA, KOMADA) values ('Jednoj zeni', 'Instrumental', 20.00, 42); insert into ZALIHA_DISKOVA (KOMPAKT_DISK, KATEGORIJA, CIJENA, KOMADA) values ('The Slim Shady', 'Vokal', 14.99, 22); insert into ZALIHA_DISKOVA (KOMPAKT_DISK, KATEGORIJA, CIJENA, KOMADA) values ('Sheryl Crow', 'Vokal', 15.99, 17); insert into ZALIHA_DISKOVA (KOMPAKT_DISK, KATEGORIJA, CIJENA, KOMADA) values ('Ja ti priznajem', 'Vokal', 16.99, 6); insert into ZALIHA_DISKOVA (KOMPAKT_DISK, KATEGORIJA, CIJENA, KOMADA)

93

values ('Ljubav nije za nas', 'Vokal', 14.99, 8); insert into ZALIHA_DISKOVA (KOMPAKT_DISK, KATEGORIJA, CIJENA, KOMADA) values ('Peter Gun', 'Instrumental', 14.99, 32); Kod 53: Popunjavenje tabele pomoću iskaza insert into Kompletno popunjena tabela trebala bi da izgleda ovako: KOMPAKT_DISK KATEGORIJA CIJENA KOMADA Negativ Vokal 16.99 13 Jednoj zeni Instrumental 20.00 42 The Slim Shady Vokal 14.99 22 Sheryl Crow Vokal 15.99 17 Ja ti priznajem Vokal 16.99 6 Ljubav nije za nas Vokal 14.99 8 Peter Gunn Instrumental 14.99 32 Tabela 73: Tabela ZALIHA_DISKOVA sa podacima Pretpostavimo da želimo da saznamo ukupan broj komada kompakt diskova koji se nalaze na zalihama, ali tako da ih grupišemo po kategorijama. Upit: select KATEGORIJA, Sum(KOMADA) AS TOTAL from ZALIHA_DISKOVA group by KATEGORIJA; Kod 54: Upit sa GROUP BY klauzulom Bi rezultirao slijedećom tabelom:

KATEGORIJA TOTAL Instrumental 74 Vokal 66 U prethodnom upitu smo ponovo koristili koncept aliasa ili pseudonima. Bilo kojoj koloni ili izrazu koji se nalazi u okviru SELECT iskaza možemo promjeniti naslov u rezultirjućoj tabeli koristeći ključnu riječ AS. U prethodnom primjeru, koristeći ovaj koncept, koloni Sum(KOMADA) smo dali pseudonim TOTAL. Pretpostavimo da sada želimo da posmatramo samo stanje zaliha jeftinijih kompakt diskova, čija je cijena manja od 15.00 KM. Dobijeni podaci treba ponovo da budu grupisani po kategorijama - vokal ili instrumental. Tada bi upit: select KATEGORIJA, SUM(KOMADA) AS TOTAL from ZALIHA_DISKOVA where CIJENA Veće od ...where NA_STANJU < 26 < Manje od ...where NA_STANJU >= 26 >= Veće ili jednako (~>, ^>) Nije veće od ...where NA_STANJU !< 26 !< (~ 'Bijelo Dugme: Veliki hitovi' Kod 85: SELECT upit – operator veće od i tekstualni podaci Nakon izvršenja ovog upita, u rezultatu će se naći slijedeći podaci: NAZIV_CDA MUZICKI_ZANR IZDAVAC NA_STANJU Zdravko Colic: Najveci hitovi Pop City Records 1010 Toto: Africa NULL MC Records 150 Tabela 103: Rezultat SELECT upita U prethodnom primjeru smo koristili isključivo punu tekstualnu vrijednost koja se nalazi u nekoj koloni. Međutim, dozvoljeno je porediti i samo dio tekstualne vrijednosti – npr. NAZIV_CDA > ‘B‘, kao u slijedećem primjeru: PRIMJER 44: Nad ranije definisanom tabelom CD_INVENTAR, izvršićemo slijedeći upit: select * from CD_INVENTAR where NAZIV_CDA > 'B' Kod 86: SELECT upit – operator jednako je i tekstualni podaci Nakon izvršenja ovog upita, u rezultatu će se naći slijedeći podaci: NAZIV_CDA MUZICKI_ZANR Zdravko Colic: Najveci hitovi Pop Toto: Africa NULL Bijelo Dugme: Veliki hitovi NULL Tabela 104: Rezultat SELECT upita

110

IZDAVAC City Records MC Records Star Records

NA_STANJU 1010 150 5

Moramo primjetiti da rezultati poređenja tekstualnih podataka zavise od tipa podatka koji je iskorišten pri definisanju tabele. Najjednostavniji slučaj imamo ako se radi o ASCII skupu podataka. Tada je položaj svakog slova određen njegovim položajem u tabeli, zbog čega je npr. ‘A’ < ‘a’ jer je 65 < 97, ‘B’ < ‘b’ jer je 66 < 98 itd. Ako se radi o nekom od nacionalnih skupova karaktera, situacija se razlikuje od SUBPa do SUBP-a i od načina implementacije pojedinog nacionalnog kodnog rasporeda.

3.7.5

Operator BETWEEN

Iako po SQL standardu iz 2006. godine operator BETWEEN nije operator poređenja, njegova funkcija je veoma slična kombinaciji Veće ili jednako (>=) i Manje ili jednako (= CIJENA) or (CIJENA 30 group by IME_UMJETNIKA Kod 122: Upit sa MAX funkcijom Rezultat upita bio bi: IME_UMJETNIKA MAX_PRODATIH Eminem 34 Toto 45 Vanna 54 Tabela 147: Rezultat upita Dakle, prethodni primjer proizveo bi grešku da smo kao uslov gripisanja naveli npr. group by MAX_PRODATIH ili MAX(BROJ_PRODATIH). Funkcije SUM() i AVG() uzimaju argument koji mora biti kolona u kojoj se nalaze brojčani podaci. Argumentu može da prethodi ključna riječ DISTINCT, koja ukazuje na 39 eliminaciju duplikata u koloni-argumentu prije same primjene neke od funkcija . Argumentu može da prethodi i ključna riječ ALL, ali se ona najčešće ne navodi jer je podrazumjevano (default) ponašanje ovih funkcija da operišu nad svim ne-NULL vrijednostima u navedenoj koloni. Funkcija SUM() vrši sumiranje svih ne-NULL vrijednosti koje se nalaze u datoj koloni. Funkcija AVG() pronalazi aritmetičku sredinu na osnovu svih ne-NULL vrijednosti koje se nalaze u navedenoj koloni. PRIMJER 63: Ako bi nad tabelom UMJETNIK_ALBUM pokrenuli upit: 39

G.Pavlović-Lažetć, Uvod u relacione baze podataka, PMF, Beograd

126

select IME_UMJETNIKA, sum(BROJ_PRODATIH) as SUM_PRODATIH from UMJETNIK_ALBUM where BROJ_PRODATIH > 30 group by IME_UMJETNIKA Kod 123: Upit sa SUM funkcijom Rezultat upita bio bi: IME_UMJETNIKA MAX_PRODATIH Eminem 34 Toto 79 Vanna 54 Tabela 148: Rezultat upita S druge strane, upit za pronalaženje srednje vrijednosti prodatih albuma bi bio: select IME_UMJETNIKA, avg(BROJ_PRODATIH) as SUM_PRODATIH from UMJETNIK_ALBUM where BROJ_PRODATIH > 30 group by IME_UMJETNIKA Kod 124: Upit sa SUM funkcijom Rezultat upita bio bi: IME_UMJETNIKA MAX_PRODATIH Eminem 34 Toto 39 Vanna 54 Tabela 149: Rezultat upita

3.8.2

Funkcije za konverziju podataka – CAST i EXTRACT

Funkcije za konverziju transformišu podatke iz jednog tipa u drugi kompatibilan tip podataka. Ove funkcije su u stanju da npr. izvrše mijenjanje ranga i preciznosti podatka ili da destiliraju dio neki atribut iz cjelovitog podatka. Funkcija CAST() omogućava da izraz nekog tipa bude konvertovan ili tretiran kao 40 podatak drugog tipa. Sintaksa CAST funkcije je: cast (IZRAZ as TIP_PODATKA) Sintaksa 20: Sintaksa CAST() funkcije Iz donekle šture definicije nije vidljiva ogromna snaga ove funkcije. Zbog toga ćemo je obraditi putem slijedećeg primjera: PRIMJER 64: Ako bi nad tabelom UMJETNIK_ALBUM pokrenuli upit: /* Oracle Express 10g*/ select 'Datum izvjestaja: ', (cast('14-02-2011' as date)) as DATUM, IME_UMJETNIKA, BROJ_PRODATIH from UMJETNIK_ALBUM /* Firebird 2.1 */ select 'Datum izvjestaja: ', (cast('2011-02-14' as date)) as DATUM, IME_UMJETNIKA, BROJ_PRODATIH from UMJETNIK_ALBUM 40

H.Borrie, The Firebird Book: A Reference for Database Developers, H.Borrie and IBPhoenix, 2004

127

Kod 125: Upit sa CAST funkcijom Rezultat upita bio bi: NASLOV DATUM IME_UMJETNIKA BROJ_PRODATIH Datum izvjestaja: 14.2.2011 Ivana 23 Datum izvjestaja: 14.2.2011 Toto 34 Datum izvjestaja: 14.2.2011 Toto 45 Datum izvjestaja: 14.2.2011 Zlatko Manojlovic 12 Datum izvjestaja: 14.2.2011 Eminem 34 Datum izvjestaja: 14.2.2011 Vanna 54 Datum izvjestaja: 14.2.2011 Regina 23 Datum izvjestaja: 14.2.2011 Art OF Noise 20 Datum izvjestaja: 14.2.2011 Bijelo Dugme 29 Tabela 150: Rezultat upita Prethodni upit je koristio CAST() funkciju da pretvori tekstualni podatak '14-022011' odnosno '2011-02-14' u tip podatka DATE. Treba primjetiti da smo Firebird-u zadali da se tekstualni podaci koji opisuju datum navode u formatu YYYY-MM-DD, dok smo u Oracle Express-u koristili masku DD-MM-YYYY. Način zadavanja tekstualnih podataka koji opisuju datum često zavisi i od regionalnih podešavanja operativnog sistema i od podešavanja samog SUBPa. Cast operatorom (u Oracle Expressu CAST funkcijom) podatke možemo konvertovati prema slijedećoj tabeli: Iz tipa

U tip

Numeric types

[VAR]CHAR BLOB DATE TIME

TIMESTAMP

Numeric types [VAR]CHAR BLOB [VAR]CHAR BLOB Numeric types DATE TIME TIMESTAMP [VAR]CHAR BLOB TIMESTAMP [VAR]CHAR BLOB DATE TIME

Rad sa Date/Time/Timestamp tipovima podataka zahtjeva poznavanje sistema za upravljanje bazama podataka na kojem radimo. Zbog toga ćemo pogledati slijedeći primjer: PRIMJER 65: Pretpostavimo da imamo tabelu CD_UMJETNICI sa slijedećim podacima: ID_UMJETNIKA IME_UMJETNIKA MJESTO_RODJENJA 1001 Tina Turner NULL 1002 Lou Reed New York Tabela 151: Tabela CD_UMJETNICI

128

Tabelu CD_UMJETNICI ćemo proširiti za jedno novo polje tipa TIMESTAMP: alter table CD_UMJETNICI add DATUM_RODJENJA timestamp; /* mijenjamo definiciju tabele*/

/* Oracle Express 10g */ /* Mijenjamo podatke*/ update CD_UMJETNICI set DATUM_RODJENJA = to_date('26.11.1939 05:35', 'dd.mm.yyyy hh24:mi:ss') where ID_UMJETNIKA = 1001; update CD_UMJETNICI set DATUM_RODJENJA = to_date('02.03.1942 15:26:31', 'dd.mm.yyyy hh24:mi:ss') where ID_UMJETNIKA = 1002;

/* Firebird 2.1 */ update CD_UMJETNICI set DATUM_RODJENJA = '26.11.1939 05:35:00' where ID_UMJETNIKA = 1001; update CD_UMJETNICI set DATUM_RODJENJA = '02.03.1942 15:26:31' where ID_UMJETNIKA = 1002;

Kod 126: Mijenjanje i dodavanje podataka u tabelu CD_UMJETNICI U tabeli se sada nalaze slijedeći podaci: ID_UMJETNIKA 1001 1002

IME_UMJETNIKA Tina Turner Lou Reed

MJESTO_RODJENJA NULL New York

DATUM_RODJENJA 26.11.1939 5:35 2.3.1942 15:26

Tabela 152: Tabela CD_UMJETNICI U prethodnom primjeru smo za Oracle Express koristili funkciju TO_DATE koja uzima dva argumenta – string koji treba da pretvori u datum/vrijeme i fromat datuma u koji dajemo u slijedećem skraćenom obliku: Element Značenje DD Dan u mjesecu (1-31) MM Mjesec (01-12. Jan= 12) YYYY Godina YYY Godina zadana pomoću 3, 2 ili jednog karaketra YY Y HH Sati u danu (1-12) HH12 Sati u danu (1-12) HH24 Sati u danu (0-24) MI Minuta (0-59) SS Sekunda (0-59) Tabela 153: Isječak iz Oracle-ove tabele sa maskama formata za TO_DATE funkciju Treba primjetiti da je prikazana tabela sa različitim formatima maski u velikoj mjeri skraćena. Korištenje ove funkcije se preporučuje zbog činjenice da se u Oracle-u format datuma/vremena može podešavati unutar servera. Da bi

129

saznali ovaj format, ali i brojne druge regionalne podatke, trebamo provjeriti varijable stanje nls_session_parameters. /* Oracle Express 10g */ select * from nls_session_parameters; Kod 127: Provjera stanja nls_session_parameters varijable S druge strane, Firebird koristi nešto drugačini pristup, jer se oslanja na regionalna podešavanja operativnog sistema. Funkcija EXTRACT() omogućava da iz izraza tipa DATE, TIME ili TIMESTAMP 41 izdvojimo pojedine dijelove u formi brojčanog podatka. Sintaksa EXTRACT funkcije je: extract (DIO from POLJE) Sintaksa 21: Sintaksa EXTRACT() funkcije Gdje DIO može biti: YEAR | MONTH | DAY | HOUR | MINUTE | SECOND | WEEKDAY | YEARDAY

Da bi obradili EXTRACT funkciju, iskoristićemo slijedeći primjer: PRIMJER 66: Pretpostavimo da imamo tabelu CD_UMJETNICI sa slijedećim podacima: ID_UMJETNIKA 1001 1002

IME_UMJETNIKA Tina Turner Lou Reed

MJESTO_RODJENJA NULL New York

DATUM_RODJENJA 26.11.1939 5:35 2.3.1942 15:26

Tabela 154: Tabela CD_UMJETNICI Da bi pomoću EXTRACT funkcije izdvojili samo dan iz kompletnog TIMESTAMP podatka, mogli bi koristiti slijedeći upit: select IME_UMJETNIKA, ' je rodjen/a ', extract(day from DATUM_RODJENJA), ' dana u mjesecu. ' from CD_UMJETNICI

Kod 128: Upit sa funkcijom EXTRACT Rezultat ovog upita bio bi: IME_UMJETNIKA CONSTANT EXTRACT CONSTANT1 Tina Turner je rodjen/a 26 dana u mjesecu. Lou Reed je rodjen/a 2 dana u mjesecu. Tabela 155: Rezultat upita Da bi pomoću funkcije EXTRACT izdvojili sat i minut rođenja iz kompletnog TIMESTAMP podatka, mogli bi koristiti slijedeći upit: select IME_UMJETNIKA, ' je rodjen/a u ', extract(hour from DATUM_RODJENJA), ' casova i ', extract(minute from DATUM_RODJENJA), ' minuta.' from CD_UMJETNICI Kod 129: Upit sa funkcijom EXTRACT Rezultat ovog upita bio bi: IME_UMJETNIKA Tina Turner Lou Reed 41

CONSTANT je rodjen/a u je rodjen/a u

EXTRACT 5 15

CONSTANT1 casova i casova i

EXTRACT1 35 26

CONSTANT2 minuta. minuta.

H.Borrie, The Firebird Book: A Reference for Database Developers, H.Borrie and IBPhoenix, 2004

130

Tabela 156: Rezultat upita

3.8.3

Funkcije za rad sa stringovima – SUBSTR ili SUBSTRING i UPPER

Funkcija SUBSTRING je interna funkcija koja implementira istoimenu ANSI SQL funkciju. Sintaksa ove funkcije je: SUBSTRING(VRIJEDNOST from STARTNA_POZICIJA [for DUZINA]) Sintaksa 22: Sintaksa SUBSTRING() funkcije Gdje je vrijednost kolona, varijabla ili izraz koji se izračunava u tekstualni podatak. Ako se kao argument funkcije zada samo STARTNA_POZICIJA, ova funkcija će vratiti tekstualni podatak koji počinje od navedene pozicije a završava sa krajem stringa. Ako se kao argument zada i opcioni argument [for DUZINA], tada funkcija vraća ili string dužine DUZINA ili string koji završava zadnjim alfanumerikom podatka, ako STARTNA_POZICIJA + DUZINA veća od dužine podatka. Funkcija vraća vrijednost tipa string (char ili varchar). Funkcija može da operiše nad vrijednostima tipa: •

Bilo koji string, (var)char ili tekstualni BLOB argument, nezavisno od upotrebljenog skupa karaktera (character set-a ili charset-a);



Tipa BLOB podtipa 0 (binarni BLOB). PRIMJER 67: Da iz kolone IME_UMJETNIKA tabele CD_UMJETNICI izvučemo samo dio imena koji počinje od šestog slova, mogli bi koristiti slijedeći upit: /* Oracle Express 10g */ select SUBSTR( IME_UMJETNIKA, 6) from CD_UMJETNICI; /* Firebird 2.1 */ select SUBSTRING( IME_UMJETNIKA from 6) from CD_UMJETNICI; Kod 130: Upit sa funkcijom SUBSTRING Prethodni upit bi vratio slijedeći rezuiltat:

SUBSTRING Turner eed Tabela 157: Rezultat upita Funkcija SUBSTRING svoju pravu vrijednost pokazuje pri radu sa podacima koji imaju tačno definisanu strukturu kakav je JMBG (jedinstveni matični broj građanina). Npr. na početku (prvih 7 karaktera) ovako strukturiranog podatka nalazi se datum rođenja u formatu DDMMYYY. PRIMJER 68: Za vježbu, samostalno kreirati tabelu pod nazivom TEST. Tabela TEST treba da ima samo jednu kolonu JMBG tipa char(13) i unijeti vlastiti matični broj građanina. Slijedeći fragment koda će iz kolone JMBG tabele TEST izvući pojedinačne dijelove jedinstvenog matičnog broja koji čine datum Vašeg rođenja: /* Oracle Express 10g */ select SUBSTR(JMBG, 1, 2) as DAN, SUBSTR(JMBG, 3, 2) as MJESEC, SUBSTR(JMBG, 5, 3) as GODINA from TEST2

131

/* Firebird 2.1 */ select SUBSTRING(JMBG from 1 for 2) as DAN, SUBSTRING(JMBG from 3 for 2) as MJESEC, SUBSTRING(JMBG from 5 for 3) as GODINA from TEST Kod 131: Upit sa funkcijom SUBSTRING U okviru nekog upita moguće je kombinovati različite funkcije, sve dok u takvim upitima zadovoljavamo sintaksu upotrebljenih funkcija. PRIMJER 69: Slijedeći fragment koda će kolonu DATUM_RODJENJA tabele CD_UMJETNICI najprije predstaviti kao tekstualni podatak tipa char(30)za oracle ili char(24) za firebird, a zatim iz takvog tekstualnog podatka izvući alfanumerike koji pripadaju godini rođenja umjetnika: /* Oracle Express 10g */ select substr (cast(DATUM_RODJENJA as char(30)), 8, 2) as GODINA from CD_UMJETNICI

/* Firebird 2.1 */ select substring( cast(DATUM_RODJENJA as char(24)) from 1 for 4) as GODINA from CD_UMJETNICI

Kod 132: Upit sa funkcijama CAST i SUBSTRING GODINA (Oracle) GODINA (Firebird) 39 1939 42 1942 Tabela 158: Rezultat upita Upite smo morali postaviti na način koji poštuje lokalna podešavanja SUBP-a i regionalna podešavanja operativnog sistema. U konkretnom slučaju, za Oracle Express to je „DD-MMM-YY“, dok je u Firebirdu datum imao masku „DD.MM.YYYY“. Takođe, treba primjetiti da Oracle pri podrazumjevanim podešavanjima koristi više karaktera za prikaz datuma u tekstualnom obliku, jer podrazumjevano prikazuje dijelove sekunde sa 6 decimala, nakon čega daje oznaku dijela dana (AM ili PM) dok Firebird sa regionalnim podešavanjima Serbian(Latin, Bosnia and Herzegovina) prikazuje dijelove sekunde sa četiri decimale, kao u slijedećim upitima: /* Oracle Express 10g */ select cast(DATUM_RODJENJA as char(30)) as GODINA from CD_UMJETNICI

/* Firebird 2.1 */ select cast(DATUM_RODJENJA as char(24)) as GODINA from CD_UMJETNICI

Kod 133: Upit sa funkcijama CAST i predstavljanje datuma/vremena Funkcije UPPER() i LOWER() prevode ulazni argument u velika odnosno mala slova, respektivno. Sintaksa ove dvije funkcije je:

132

UPPER(VRIJEDNOST) i LOWER(VRIJEDNOST) Sintaksa 23: Sintaksa UPPER() i LOWER funkcija Gdje je vrijednost kolona, varijabla ili izraz koji se izračunava u tekstualni podatak. PRIMJER 70: Slijedeći fragment koda će kolonu IME_UMJETNIKA tabele CD_UMJETNICI prikazati velikim slovima: select upper(IME_UMJETNIKA) as IME from CD_UMJETNICI Kod 134: Upit sa funkcijom UPPER IME TINA TURNER LOU REED Tabela 159: Rezultat upita S druge strane, slijedeći upit će kolonu IME_UMJETNIKA tabele CD_UMJETNICI prikazati malim slovima: select lower(IME_UMJETNIKA) as IME from CD_UMJETNICI Kod 135: Upit sa funkcijom LOWER IME tina turner lou reed Tabela 160: Rezultat upita Funkcija TRIM() uklanja vodeće ili prateće praznine (space) ili opciono druge stringove iz ulaznog argumenta. Sintaksa ove funkcije je: TRIM ([] string) Sintaksa 24: Sintaksa TRIM() funkcije Gdje je: - opcioni argument koji se sastoji od polja {[gdje] [šta]} FROM gdje - može biti: BOTH – uklanja sa obje strane (podrazumjevana vrijednost) LEADING – uklanja sa početka stringa, TRAILING – uklanja sa kraja stringa. šta – Podstring koji se uklanja (i ako se ponavlja). Podrazumjevana vrijednost koja se uklanja je praznina ' ' (space). PRIMJER 71: SELECT upit možemo realizovati i bez pozivanja bilo koje kolone tabele. Slijedeći upit demonstrira TRIM() funkciju na ovakav način: select trim (' Ne trosi prostor ') from CD_UMJETNICI Kod 136: Upit sa funkcijom TRIM TRIM Ne trosi prostor Ne trosi prostor

133

Tabela 161: Rezultat upita Ovo je podrazumjevano ponašanje funkcije TRIM() – u primjeru su iz stringa ' Ne trosi prostor ' uklonjene vodeće i prateće praznine. Ako bi htjeli da uklonimo samo vodeće praznine, mogli bi upotrebiti slijedeći upit: select trim (leading from ' from CD_UMJETNICI Kod 137: Upit sa funkcijom TRIM

Ne trosi prostor

')

TRIM

'Ne trosi prostor ' 'Ne trosi prostor ' Tabela 162: Rezultat upita U slijedećem upitu, uklonićemo prateće uzvičnike iz stringa 'U pomoc!!!!': select trim (trailing '!' from 'U pomoc!!!!') from CD_UMJETNICI Kod 138: Upit sa funkcijom TRIM TRIM

'U pomoc' 'U pomoc' Tabela 163: Rezultat upita U okviru TRIM funkcije možemo zadavati uklanjanje podstringa sa više karaktera: /* Samo Firebird 2.1 */ select trim ('la' from 'lalala volim te Ela') from CD_UMJETNICI Kod 139: Upit sa funkcijom TRIM TRIM

'volim te E' 'volim te E' Tabela 164: Rezultat upita Prethodni upit nije moguće izvršiti u Oracle Expressu, jer on prihvata samo po jedan trim karakter kao argument funkcije, dok Firebird prihvata i kompletan string kao argument funkcije Trim.

3.8.4

CREATE SEQUENCE iskaz

Za razliku od Microsoftovog SQL Servera, Oracle i Firebird ne poznaju tip podatka Autonumber. Da bi formirali ovakav tip podatka, Oracle i Firebird koriste SQL standardom definisani iskaz CREATE SEQUENCE. Pomoću ovog iskaza definiše se postojanje novog generatora sekvenci, koji će se ponašati na sličan način Autonumber tipu podataka. Podaci Autonumber tipa se u Oracle-u i Firebirdu nazivaju još i sekvence ili generatori. Sintaksa ovog iskaza je:

134

/* Oracle Express 10g*/ create sequence ime_sekvence MINVALUE value MAXVALUE value START WITH value INCREMENT BY value CACHE value; /* Firebird 2.1 */ create sequence ime_sekvence; Sintaksa 25: Sintaksa CREATE SEQUENCE iskaza Za izmjenu sekvence, koristi se ALTER SEQUENCE iskaz: /* Oracle Express 10g*/ alter sequence ime_sekvence MINVALUE value MAXVALUE value START WITH value INCREMENT BY value CACHE value; /* Firebird 2.1 */ create sequence ime_sekvence restart with ;; Sintaksa 26: Sintaksa ALTER SEQUENCE iskaza Kako vidimo, Oracle u oba slučaja (CREATE i ALTER SEQUENCE) daje mnogo veći izbor podešavanja, koja uključuju zadavanje minimalne i maksimalne vrijednosti generatora (MINVALUE i MAXVALUE), početne vrijednosti (START WITH), veličine za koju će se sekvenca inkrementirati (INCREMENT BY) te koliko će vrijednosti keširati radi bržeg pristupa (CACHE 100 znači 100 vrijednosti). Za izbacivanje sekvence (generatora) iz šeme baze podataka, koristi se iskaz DROP SEQUENCE: /* Oracle Express 10g*/ drop sequence ime_sekvence; /* Firebird 2.1 */ drop sequence ime_sekvence; Sintaksa 27: Sintaksa DROP SEQUENCE iskaza Da bi zaista generisali neku novu vrijednost, Oracle i Firebird koriste drugačije pristupe. Oracle koristi iskaz SELECT IME_SEKVENCE.NEXTVAL u kom poziva posebnu tabelu pod nazivom DUAL: /* Oracle Express 10g*/ select ime_sekvence.nextval from dual; Sintaksa 28: Sintaksa generisanja slijedeće vrijednosti sekvence u Oracle-u Firebird koristi iskaz SELECT NEXT VALUE FOR IME_SEKVENCE i drugu posebnu tabelu pod nazivom RDB$DATABASE: /* Firebird 2.1 */ select next value for ime_sekvence from RDB$DATABASE; Sintaksa 29: Sintaksa generisanja slijedeće vrijednosti sekvence u Firebird-u

135

PRIMJER 72: Da bi kreirali sekvencu (generator) u Oracle Expressu, koristićemo slijedeći iskaz: /* Samo Oracle Express 10g*/ create sequence prvi_generator Kod 140: Kreiranje sekvence Da bi mogli da koristimo prethodno kreiranu sekvencu, moramo se upoznati sa još jednom tabelom koja se nalazi u šemi Oracle-ove baze podataka. Oraclova šema baze podataka posjeduje jednu posebnu tabelu pod imenom DUAL. Ova tabela posjeduje tačno jednu kolonu pod nazivom DUMMY i samo jedan red u kojem se nalazi vrijednost X. Ova tabela se često koristi različitim u upitima koji ne treba da vraćaju stvarne podatke iz tabele. Npr. ako bi željeli da saznamo sistemsko vrijeme sa servera, koristili bi : /* Samo Oracle Express 10g*/ select sysdate from dual Kod 141: Sistemski datum sa servera Postojanje ove tabele koristi se i za generisanje slijedeće vrijednosti sekvence, kao u primjeru koji slijedi: /* Samo Oracle Express 10g*/ select prvi_generator.nextval from dual; Kod 142: Upit za generisanja slijedeće vrijednosti sekvence NEXTVAL 1 Tabela 165: Rezultat upita PRIMJER 73: Da bi kreirali sekvencu (generator) u Firebird-u, koristićemo slijedeći iskaz: /* Samo Firebird 2.1 */ create sequence prvi_generator Kod 143: Kreiranje sekvence Da bi mogli da koristimo prethodno kreiranu sekvencu, moramo se upoznati sa još jednom tabelom posebnom koja se nalazi u šemi Firebirdove baze podataka, pod nazivom RDB$DATABASE. Kao i u prethodnom primjeru, i ova tabela se koristi za „lažne“ upite koji treba da vrate samo jednu izračunatu vrijednost ili kontekst varijablu. Ova tabela se koristi na vrlo sličan način na koji se koristi tabela DUAL u Oracle-u.42 Npr. ako bi željeli da saznamo sistemsko vrijeme sa servera, koristili bi : /* Samo Firebird 2.1 */ select CURRENT_DATE from RDB$DATABASE; Kod 144: Sistemski datum sa servera Postojanje ove tabele koristi se i za generisanje slijedeće vrijednosti generatora, kao u primjeru koji slijedi: /* Samo Firebird 2.1 */ select next value for PRVI_GENERATOR from RDB$DATABASE; Kod 145: Upit za generisanja slijedeće vrijednosti sekvence GEN_ID 42

H.Borrie, The Firebird Book: A Reference for Database Developers, H.Borrie and IBPhoenix, 2004

136

1 Tabela 166: Rezultat upita Firebird posjeduje jednu posebnu funkciju za generisanje vrijednosti sekvenci. Funkcija GEN_ID() nije standardna SQL funkcija. Ova funkcija omogućava implementaciju auto-inkrementirajućih polja u ključevima. Auto-inkrementirajući ključevi u Firebird SUBP-u zavise od generatora (sekvenci). Sintaksa GEN_ID() funkcije je: GEN_ID(IME_GENERATORA, VRIJEDNOST) Sintaksa 30: Sintaksa GEN_ID() funkcije Gdje su: IME_GENERATORA : identifikator nekog postojećeg generatora, VRIJEDNOST: vrijednost koraka, navodi za koliko se uvećava sadržaj generatora. Funkcija GEN_ID() vraća podatak tipa BIGINT.

3.8.5

Ostale funkcije

U ovom poglavlju su obrađene samo najčešće korištene interne funkcije. Međutim, kompletna lista ugrađenih (internih) funkcija oba SUBP-a je mnogo veća: Slijedi kompletna lista internih funkcija Oracle Expressa: OBJECT_NAME(), REMAINDER(), ROUND(), SUBSTRC(), SYS_LITERALTODSINTERVAL(), TO_BINARY_DOUBLE(), LENGTH(), LEVEL(), LTRIM(), NCHARTOROWID(), NEXT_DAY(), NHEXTORAW(), NLS_CHARSET_ID(), CONCAT(), CONVERT(), DBTIMEZONE(), GROUPING(), INSTR(), LEAST(), LEAST_UB(), TO_NUMBER(), TO_YMINTERVAL(), SYS$STANDARD_CHR(), SYS$STANDARD_TRIM(), ROWIDTONCHAR(), SUBSTR2(), SYS_AT_TIME_ZONE(), NUMTOYMINTERVAL(), TO_LABEL(), CHR(), COALESCE(), COMMIT(), COMPOSE(), DECODE(), DECOMPOSE(), ISNCHAR(), TO_SINGLE_BYTE(), UID(), UPPER(), ATAN(), REPLACE(), RPAD(), SINH(), SUBSTRB(), SYS_LITERALTOTZTIME(), LOCALTIMESTAMP(), NLSSORT(), NULLFN(), TO_MULTI_BYTE(), CHARTOROWID(), COMMIT_CM(), COSH(), EMPTY_CLOB(), FLOOR(), GREATEST(), GREATEST_LB(), HEXTORAW(), TZ_OFFSET(), USERENV(), VSIZE(), ACOS(), ASCIISTR(), ROWNUM(), SAVEPOINT(), SIGN(), SIN(), SQRT(), SYS_CONTEXT(), SYS_LITERALTOTZTIMESTAMP(), TAN(), TO_BLOB(), LENGTH4(), LN(), LOG(), NANVL(), NLS_CHARSET_DECL_LEN(), NULLIF(), REGEXP_LIKE(), TO_DATE(), TO_NCLOB(), CURRENT_DATE(), CURRENT_TIMESTAMP(), DEREF(), EMPTY_BLOB(), EXP(), INSTR4(), INSTRB(), TO_TIMESTAMP(), TO_TIME_TZ(), TRANSLATE(), VALUE(), ADD_MONTHS(), SET(), SET_TRANSACTION_USE(), SYSTIMESTAMP(), TO_ANYLOB(), LENGTHC(), LOCALTIME(), NLS_CHARSET_NAME(), RAWTOHEX(), RAWTONHEX(), COS(), CURRENT_TIME(), EXISTS(), FROM_TZ(), TO_RAW(), USER(), SYS$EXTRACT_STRING_FROM(), SYS$YMINTERVALSUBTRACT(), ABS(), ASCII(), ASIN(), BFILENAME(), ROLLBACK_SV(), ROWID (), ROWIDTOCHAR(), ROWLABEL(), RTRIM(), SOUNDEX(), SQLERRM(), SUBSTR(), SYS_EXTRACT_UTC(), SYS_GUID(), SYS_LITERALTOTIME(), SYS_LITERALTOTIMESTAMP(), TO_BINARY_FLOAT(), LPAD(), NUMTODSINTERVAL(), TO_CLOB(), DUMP(), INITCAP(), INSTRC(), TO_TIME(), SYS$EXTRACT_FROM(), SYS$STANDARD_TRANSLATE(), BITAND(), ROLLBACK_NR(), ROLLUP(), SUBSTR4(), SYS_LITERALTODATE(), LOWER(), NEW_TIME(), NLS_INITCAP(), POWER(), REGEXP_REPLACE(), TO_NCHAR(), CARDINALITY(), CEIL(), INSTR2(), LAST_DAY(), TRUNC(), UNISTR(),

137

SYS$DSINTERVALSUBTRACT(), ATAN2(), REGEXP_SUBSTR(), SESSIONTIMEZONE(), SQLCODE(), SYS$LOB_REPLICATION(), SYSDATE(), SYS_LITERALTOYMINTERVAL(), TANH(), LENGTH2(), LENGTHB(), LUB(), MONTHS_BETWEEN(), NCHR(), NLS_LOWER(), NLS_UPPER(), NVL(), REF(), REGEXP_INSTR(), TO_CHAR(), TO_DSINTERVAL(), CUBE(), GLB(), TO_TIMESTAMP_TZ(), TRIM(), UROWID (), XOR(). Listu internih funkcija Oracle Expressa možemo dobiti pomoću slijedećeg upita: /* Samo Oracle Express */ select distinct object_name from all_arguments where package_name = 'STANDARD'; Kod 146: Upit za dobijanje kompletne liste funkcija Kompletan skup funkcija koje posjeduje Firebird SUBP u verziji 2.1. je dat u nastavku: ACOS(), ASCII_CHAR(), ASCII_VAL(), ASIN(), ATAN(), ATAN2(), BIN_AND(), BIN_OR(), BIN_SHL(), BIN_SHR(), BIN_XOR(), BIT_LENGTH(), CAST(), CEIL(), CEILING(), CHAR_LENGTH(), CHARACTER_LENGTH(), COALESCE(), COS(), COSH(), COT(), DATEADD(), DATEDIFF(), DECODE(), EXP(), EXTRACT(), FLOOR(), GEN_ID(), GEN_UUID(), HASH(), IIF(), LEFT(), LN(), LOG(), LOG10(), LOWER(), LPAD(), MAXVALUE(), MINVALUE(), MOD(), NULLIF(), OCTET_LENGTH(), OVERLAY(), PI(), POSITION(), POWER(), RAND(), RDB$GET_CONTEXT(), RDB$SET_CONTEXT(), REPLACE(), REVERSE(), RIGHT(), ROUND(), RPAD(), SIGN(), SIN(), SINH(), SQRT(), SUBSTRING(), TAN(), TANH(), TRIM(), TRUNC(), UPPER(). Treba reći i da ovakav skup funkcija vjerovatno nije konačan – moguće je da će se u nekoj od narednih verzija ovaj skup internih funkcija još proširivati. Do sada prikazane funkcije smo u prethodnoj diskusiji nazivali interne. Specijalitet Firebird SUBP-a je da on posjeduje mogućnost pisanja eksternih funkcija. Ovakve, vanjske funkcije se pod operativnim sistemom Windows pišu u vidu DLL-a – dinamičkih biblioteka funkcija. U Firebird SUBP-u ovakve funkcije se nazivaju korisnički definisane funkcije - UDF ili User Defined Functions. Pri instalaciji SUBP-a, u datotekama ib_udf i fbudf instalira se i podrazumjevani skup UDF funkcija: Abs, acos, addDay, addHour, addMilliSecond, addMinute, addMonth, addSecond, addWeek, addYear, ascii_char, ascii_val, asin, atan, atan2, bin_and, bin_or, bin_xor, ceiling, cos, cosh, cot, dow, dpower, floor, getExactTimestamp, i64round, i64truncate, ln, log, log10, lower, lpad, ltrim, mod, *nullif, *nvl, pi, rand, right, round, i64round, rpad, rtrim, sdow, sign, sin, sinh, sqrt, srand, sright, string2blob, strlen, substr, substrlen, tan, tanh, truncate, i64truncate.

138

3.9

Postavljanje upita nad više tabela

Veoma važna komponenta bilo koje relacione baze podataka je veza koja može postoji između dvije ili više tabela. Ovakve veze omogućavaju nam da povežemo podatke u jednoj tabeli sa podacima u drugoj tabeli. Ovakve veze postaju posebno važne kada nam je potrebno da postavljamo upite koji očekuju podatke iz dvije ili više tabela. Jedan takav tip upita je JOIN upit. JOIN je takva operacija koja uklapa rezultate pretrage jedne tabele sa rezultatima pretrage druge tabele tako da se čini da rezultat dolazi iz jedne tabele. SQL standard definiše nekoliko tipova JOIN operacija (ili upita) koji se razlikuju u načinu spajanja podataka. U nastavku ovog poglavlja, koristićemo nešto modifikovane tabele. Ovdje neće biti prikazan kod za formiranje ovakvih tabela, jer se može smatrati da su čitaoci do ovog momenta već dovoljno osposobljeni da samostalno kreiraju i popunjavaju tabele podacima. CDISK_ID NASLOV_CDISKA Integer, Char(60) Primary Key 1 Tina Turns the Country On 2 Acid Queen 3 Unchain My Heart 4 Tina Turns the Country On 5 Zdravko Colic: Najveci hitovi 6 Bijelo Dugme: Veliki hitovi 7 Toto: Africa Tabela 167: Tabela CDISKOVI

ID_IZDAVACA Integer

ZALIHA Integer

ID_Umjetnika Integer

1 2 2 2 5 4 3

5 6 8 2 1010 5 150

1001 1001 1006 1001 1005 1003 1004

ID_UMJETNIKA IME_UMJETNIKA Integer, Char(60) Primary Key 1001 Tina Turner 1002 Lou Reed 1003 Bijelo Dugme 1004 Toto 1005 Zdravko Colic 1006 Joe Cocker Tabela 168: Tabela CD_UMJETNICI ID_IZDAVACA NAZIV_KOMPANIJE Integer, Char(60) Primary Key 1 United Artists 2 EMI Records 3 MC Records 4 Star Records 5 City Records Tabela 169: Tabela IZDAVACI ID_ZAPOSLENOG Integer, Primary Key 1 2

PREZIME Char(60)

MENADZER Integer

Mikic Novakovic

NULL 1

139

3 Vasilic 4 Damjanovic Tabela 170: Tabela Zaposleni

3.9.1

1 2

Dekartov proizvod i Ekvi-spajanje

Jedan od najjednostavnijih upita spajanja je upit odvojen zarezima (comma-separated join). U ovakvom tipu operacije spajanja, potrebno je samo navesti listu tabela iz kojih preuzimamo podatke u okviru FROM klauzule SELECT iskaza. Naravno, ovakvi upiti se dalje mogu proširivati i dodatno filtrirati pomoću WHERE klauzule, ali nas u ovom uvodnom dijelu interesuje samo osnovna forma ovakvog upita nad više tabela. Da bi formirali najjednostavniji ovakav upit, dovoljno je u okviru FROM klauzule navesti imena tabela iz kojih preuzimamo podatke, kao u slijedećem primjeru: PRIMJER 74: Recimo da želimo da prikažemo sve podatke iz tabela CDISKOVI i CD_UMJETNICI. To bi mogli realizovati pomoću slijedećeg uipita: select * from CDISKOVI, CD_UMJETNICI Kod 147: Najjednostavniji upit spajanja Iako je sam upit veoma jednostavan, rezultat ovog upita je veoma dugačak i važan. CDISK_ ID 5 6 7 1 2 3 4 5 6 7 1 2 3 4 5 6 7 1 2 3 4 5 6 7 1 2 3 4 5 6 7 1 2 3 4 5

140

NASLOV_ CDISKA Zdravko Colic: Najveci hitovi Bijelo Dugme: Veliki hitovi Toto: Africa Tina Turns the Country On Acid Queen Unchain My Heart Tina Turns the Country On Zdravko Colic: Najveci hitovi Bijelo Dugme: Veliki hitovi Toto: Africa Tina Turns the Country On Acid Queen Unchain My Heart Tina Turns the Country On Zdravko Colic: Najveci hitovi Bijelo Dugme: Veliki hitovi Toto: Africa Tina Turns the Country On Acid Queen Unchain My Heart Tina Turns the Country On Zdravko Colic: Najveci hitovi Bijelo Dugme: Veliki hitovi Toto: Africa Tina Turns the Country On Acid Queen Unchain My Heart Tina Turns the Country On Zdravko Colic: Najveci hitovi Bijelo Dugme: Veliki hitovi Toto: Africa Tina Turns the Country On Acid Queen Unchain My Heart Tina Turns the Country On Zdravko Colic: Najveci hitovi

ID_ IZDAVACA 5 4 3 1 2 2 2 5 4 3 1 2 2 2 5 4 3 1 2 2 2 5 4 3 1 2 2 2 5 4 3 1 2 2 2 5

ZALIHA 1.010 5 150 5 6 8 2 1.010 5 150 5 6 8 2 1.010 5 150 5 6 8 2 1.010 5 150 5 6 8 2 1.010 5 150 5 6 8 2 1.010

ID_ UMJETNIKA 1.001 1.001 1.001 1.001 1.001 1.001 1.001 1.002 1.002 1.002 1.002 1.002 1.002 1.002 1.003 1.003 1.003 1.003 1.003 1.003 1.003 1.004 1.004 1.004 1.004 1.004 1.004 1.004 1.005 1.005 1.005 1.005 1.005 1.005 1.005 1.006

IME_ UMJETNIKA Tina Turner Tina Turner Tina Turner Tina Turner Tina Turner Tina Turner Tina Turner Lou Reed Lou Reed Lou Reed Lou Reed Lou Reed Lou Reed Lou Reed Bijelo Dugme Bijelo Dugme Bijelo Dugme Bijelo Dugme Bijelo Dugme Bijelo Dugme Bijelo Dugme Toto Toto Toto Toto Toto Toto Toto Zdravko Colic Zdravko Colic Zdravko Colic Zdravko Colic Zdravko Colic Zdravko Colic Zdravko Colic Joe Cocker

6 7 1 2 3 4 5 6

Bijelo Dugme: Veliki hitovi Toto: Africa Tina Turns the Country On Acid Queen Unchain My Heart Tina Turns the Country On Zdravko Colic: Najveci hitovi Bijelo Dugme: Veliki hitovi

4 3 1 2 2 2 5 4

5 150 5 6 8 2 1.010 5

1.006 1.006 1.006 1.006 1.006 1.006 1.001 1.001

Joe Cocker Joe Cocker Joe Cocker Joe Cocker Joe Cocker Joe Cocker Tina Turner Tina Turner

Tabela 171: Rezultat upita Iako ovako prikazani rezultati za prosječnog korisnika nemaju mnogo smisla, za programere ovakvi rezultati imaju veliko značenje sa aspekta performansi upita. Ako detaljnije pogledamo tabelu sa rezultatima, primjetićemo da je svaki red tabele CD_UMJETNICI povezan sa svakim redom tabele CDISKOVI. Npr, izvođač „Tina Turner“ je povezan najprije sa albumom „Zdravko Colic – Najveci hitovi“, pa sa albumom „Bijelo Dugme – Veliki hitovi“ – sve do albuma „Tina Turns the Country On“, ukupno 7 puta. Kako tabela CDISKOVI sadrži 7 redova, a tabela CD_UMJETNICI 6 redova, rezultat prethodnog upita sadrži ukupno 7x6 = 42 reda. Mogli bi reći i da se za svaki album u tabeli CDISKOVI ponove svi izvođači iz tabele CD_UMJETNICI. Rezultat prethodnog upita naziva se Dekartov ili Kartezijanski proizvod tabela (po francuskom matematičaru Rene Descartes-u). Dekartov proizvod tabela predstavlja polaznu osnovu od koje počinje optimizacija performanski većine upita. Sa aspekta korisnika, mnogo smislenije rezultate mogli bi dobiti ako bi prethodnom upitu dodali WHERE klauzulu. Primjetite da obje tabele (CD_UMJETNICI i CDISKOVI) imaju kolonu pod nazivom ID_UMJETNIKA. Ako bi u WHERE klauzuli odredili da se u rezultatu prikažu samo redovi za koje je polje ID_UMJETNIKA tabele CD_UMJETNICI jednako istoimenom polju tabele CDISKOVI, rezltirajuća tabela bi imala 7 redova a u njoj bi pored svakog naslova albuma stajao odgovarajući naziv izvođača. Ovakva vrsta upita naziva se ekvi-spajanje (ili equi-join). Ekvi-spajanje je takva vrsta spajanja koja izjednačava vrijednosti jedne ili više kolona prve tabele sa vrijednostima jedne ili više kolona druge tabele. Ekvi-spajanje se još naziva i prirodno spajanje. Operacija prirodnog (ekvi) spajanja je specijalni (i najčešći) slučaj operacije slobodnog (teta) 43 spajanja, a to je spajanje po jednakosti. PRIMJER 75: Recimo da želimo da prikažemo sve podatke iz tabela CDISKOVI i CD_UMJETNICI koji imaju istu vrijednost u kolonama ID_UMJETNIKA. To bi mogli realizovati pomoću slijedećeg uipita: select * from CDISKOVI, CD_UMJETNICI where CDISKOVI.id_umjetnika = CD_UMJETNICI.id_umjetnika

Kod 148: Ekvi-spajanje Rezultat prethodnog upita vidljiv je u slijedećoj tabeli: cdisk _id

5 6 7 1 2 3 4

naslov_cdiska

Zdravko Colic: Najveci hitovi Bijelo Dugme: Veliki hitovi Toto: Africa Tina Turns the Country On Acid Queen Unchain My Heart Tina Turns the Country On

id_ izdavaca

5 4 3 1 2 2 2

zaliha

1.010 5 150 5 6 8 2

CDISKOVI. id_ mjetnika

1005 1003 1004 1001 1001 1006 1001

CD_UMJETNICI. id_ umjetnika

1005 1003 1004 1001 1001 1006 1001

ime_umjetnika

Zdravko Colic Bijelo Dugme Toto Tina Turner Tina Turner Joe Cocker Tina Turner

Tabela 172: Rezultat upita

43

H.Borrie, The Firebird Book: A Reference for Database Developers, H.Borrie and IBPhoenix, 2004

141

U tabeli su podebljano (boldom) prikazane i dvije kolone koje najviše utiču na način izvršavanja ovog upita – CD_UMJETNICI.ID_UMJETNIKA i CDISKOVI.ID_UMJETNIKA, jer je spajanje obavljeno prema kriterijumu da se albumi, po koloni ID_UMJETNIKA spajaju sa odgovarajućim redovima tabele CD_UMJETNICI. Podaci u ovakvoj tabeli sa aspekta korisnika imaju mnogo veću vrijednost. Međutim, u rezultatu se, pored boldom označenih kolona, koje su ostavljene namjerno, vide i kolone ID_IZDAVACA i CDISK_ID koje prosječnom korisniku nisu potrebne. Zbog toga ćemo u slijedećem primjeru projektovati skup kolona koje treba da učestvuju u konačnom rezultatu upita. Takođe ćemo u primjeru proširiti i kriterijum selekcije samo na one albume kojih na zalihama imamo manje od 15. PRIMJER 76: Recimo da želimo da prikažemo sve podatke iz tabela CDISKOVI i CD_UMJETNICI koji imaju istu vrijednost u kolonama ID_UMJETNIKA, a da pri tome prikažemo samo kolone NASLOV_CDISKA, IME_UMJETNIKA i ZALIHA, gdje je zaliha manja od 15 albuma. To bi mogli realizovati pomoću slijedećeg uipita: select CDISKOVI.NASLOV_CDISKA, CD_UMJETNICI.IME_UMJETNIKA, CDISKOVI.ZALIHA from CDISKOVI, CD_UMJETNICI where CDISKOVI.id_umjetnika = CD_UMJETNICI.id_umjetnika

Kod 149: Ekvi-spajanje Rezultat prethodnog upita vidljiv je u slijedećoj tabeli: NASLOV_CDISKA IME_UMJETNIKA ZALIHA Zdravko Colic: Najveci hitovi Zdravko Colic 1.010 Bijelo Dugme: Veliki hitovi Bijelo Dugme 5 Toto: Africa Toto 150 Tina Turns the Country On Tina Turner 5 Acid Queen Tina Turner 6 Unchain My Heart Joe Cocker 8 Tina Turns the Country On Tina Turner 2 Tabela 173: Rezultat upita Da bi prikazali samo slogove kod kojih je zaliha manja od 15, dodaćemo još jedan predikat u where klauzulu: select CDISKOVI.NASLOV_CDISKA, CD_UMJETNICI.IME_UMJETNIKA, CDISKOVI.ZALIHA from CDISKOVI, CD_UMJETNICI where CDISKOVI.id_umjetnika = CD_UMJETNICI.id_umjetnika and CDISKOVI.zaliha < 15

Kod 150: Ekvi-spajanje Rezultat prethodnog upita vidljiv je u slijedećoj tabeli: NASLOV_CDISKA Bijelo Dugme: Veliki hitovi Tina Turns the Country On Acid Queen Unchain My Heart Tina Turns the Country On Tabela 174: Rezultat upita

142

IME_UMJETNIKA Bijelo Dugme Tina Turner Tina Turner Joe Cocker Tina Turner

ZALIHA 5 5 6 8 2

Generalno, osnovna pravila za pisanje upita tipa spajanje (JOIN), mogla bi se sažeti u slijedeće: •

U klauzuli FROM moramo navesti sve nazive tabela koje učestvuju u spajanju,



U klauzuli WHERE trebamo navesti uslov spajanja i opcione dodatne uslove,



Nazivi kolona koji su zajednički za više tabela moraju biti kvalifikovani nazivima njihovih tabela. Sintaksa za kvalifikaciju je: NAZIV_TABELE.NAZIV_KOLONE Sintaksa 31: Sintaksa kvalifikacije kolona Ako nazivi kolona nisu zajednički za više tabela, takve kolone mogu ali i ne moraju biti kvalifikovane imenima tabela.



I na kraju, najvažnije pravilo - podaci u tableama koje se spajaju moraju na neki način biti logički povezani. Ovakva logička veza se vrlo često izvodi ranije opisanim konceptom spoljnog (FOREIGN) ključa.

Iako je ekvi-join u kojem se koristi operator jednakosti vrlo česta vrsta spajanja, on nije jedini način spajanja tabela. Vrlo često ćemo biti u prilici da vidimo da i drugi operatori poređenja, npr. manje () itd. mogu biti veoma korisni. Ovakva vrsta spajanja u kojoj se koristi bilo koji drugi kriterijum (osim jednakosti) naziva se teta-join. Operacija slobodnog (teta) spajanja tabela R i S (R Θ S) kao rezultat proizvodi tabelu (relaciju) sa m+n kolona. Ta nova tabela sadrži redove tabele R na koje su dopisani redovi tabele S ali samo ako je zadovoljen uslov spajanja teta (Θ). Do sada prikazana varijanta ekvi-spajanja predstavlja njegovu originalnu formu. Uskoro ćemo vidjeti da se upiti ovog tipa mogu pisati i na drugačiji način, ali i da postoje i druge, nešto različite vrste spajanja. Kako smo u pravilima za pisanje upita tipa JOIN u tački 3. vidjeli, imena kolona se mogu ali i ne moraju kvalifikovati odgovarajućim imenima tabela. Međutim, imena tabela često mogu da budu veoma dugačka, što može dovesti do otežane čitljivosti napisanog upita. SQL standard zbog toga je uveo ranije pominjani koncept pseudonima ili aliasa, koji možemo iskoristiti da poboljšamo čitljivost nekog upita. Njegova sintaksa je: NAZIV_TABELE PSEUDONIM Sintaksa 32: Sintaksa aliasa – Oracle Express NAZIV_TABELE [as] PSEUDONIM Sintaksa 33: Sintaksa aliasa - Firebird Dakle, sintaksa je vrlo jednostavna – nakon naziva tabele navodimo PSEUDONIM. Primjetite i da Firebird dozvoljava da naglasimo postojanje pseudonima pomoću ključne riječi AS. PRIMJER 77: Prethodno opisani upit mogli bi pomoću aliasa napisati na slijedći način: select CD.NASLOV_CDISKA, UM.IME_UMJETNIKA, CD.ZALIHA from CDISKOVI CD, CD_UMJETNICI UM where CD.id_umjetnika = UM.id_umjetnika

Kod 151: Ekvi-spajanje uz upotrebu aliasa Rezultat ovakvog upita je identičan prethodno prikazanom:

143

NASLOV_CDISKA Bijelo Dugme: Veliki hitovi Tina Turns the Country On Acid Queen Unchain My Heart Tina Turns the Country On Tabela 175: Rezultat upita

IME_UMJETNIKA Bijelo Dugme Tina Turner Tina Turner Joe Cocker Tina Turner

ZALIHA 5 5 6 8 2

3.9.1.1 Ekvi-spajanje više od dvije tabele Svi do sada pokazani primjeri ekvi-spajanja prikazivali spajanje dvije tabele. Međutim, ne postoji prepreka da se spajanje obavi i nad više tabela. Jedini uslov da se ovakva vrsta spajanja obavi je da među svim navedenim tabelama postoji neka vrsta logičke veze. U prethodnim primjerima, kao logička veza služila nam je kolona ID_UMJETNIKA koja je zajednička za tabele CD_UMJETNICI i CDISKOVI. Međutim, ako pogledamo tabele date u uvodu ovog poglavlja, vidjećemo da postoji još jedna logička veza koja povezuje tabele CDISKOVI i IZDAVACI. Ta logička veza data je u sastavu kolone ID_IZDAVACA koja se nalazi u sastavu obje tabele. Ovakva veza mogla bi se iskoristiti i za pisanje upita koji bi izvršio ekvi-spajanje tabela CDISKOVI i IZDAVACI, ali i za spajanje sve tri tabele - CD_UMJETNICI, CDISKOVI i IZDAVACI. PRIMJER 78: Ekvi-spajanje tabela CDISKOVI i IZDAVACI po koloni ID_IZDAVACA mogli bi napisati na slijedeći način: select CD.NASLOV_CDISKA, UM.IME_UMJETNIKA, IZ.NAZIV_KOMPANIJE, CD.ZALIHA from CDISKOVI CD, CD_UMJETNICI UM, IZDAVACI IZ where CD.id_umjetnika = UM.id_umjetnika

and CD.ID_IZDAVACA = IZ.ID_IZDAVACA Kod 152: Ekvi-spajanje Rezultat ovakvog upita bio bi: NASLOV_CDISKA NAZIV_KOMPANIJE ZALIHA Toto: Africa MC Records 150 Bijelo Dugme: Veliki hitovi Star Records 5 Zdravko Colic: Najveci hitovi City Records 1010 Tina Turns the Country On United Artists 5 Acid Queen EMI Records 6 Unchain My Heart EMI Records 8 Tina Turns the Country On EMI Records 2 Tabela 176: Rezultat upita U prikazanim podacima postoje dvije logičke veze – prva između tabela CDISKOVI i CD_UMJETNICI po koloni ID_UMJETNIKA a druga između tabela CDISKOVI i IZDAVACI po koloni ID_IZDAVACA.

3.9.1.2 Ekvi-spajanje pomoću ključnih riječi CROSS JOIN Ekvi-spajanje (prirodno spajanje) je moguće izvesti i pomoću ključnih riječi CROSS JOIN. Rezultat ovakvog upita je identičan prethodno navedenom. Jedina razlika je u

144

sintaksi – umjesto liste tabela koje su odvojene zarezima, imena tabela se odvajaju pomoću ključne riječi CROSS JOIN. Sintaksa CROSS JOINA je: SELECT [LISTA_KOLONA] FROM NAZIV_TABELE cross join NAZIV_TABELE [cross join NAZIV_TABELE...] Sintaksa 34: Sintaksa za CROSS JOIN PRIMJER 79: Prethodno prikazani primjer spajanja može se izvasti i pomoću CROSS JOIN-a na slijedeći način: select CD.NASLOV_CDISKA, UM.IME_UMJETNIKA, IZ.NAZIV_KOMPANIJE, CD.ZALIHA from CDISKOVI CD cross join CD_UMJETNICI UM cross join IZDAVACI IZ /* pod komentarom su polja po kojima vršimo spajanje where CD.id_umjetnika = UM.id_umjetnika and CD.ID_IZDAVACA = IZ.ID_IZDAVACA */

Kod 153: Ekvi-spajanje Dobijeni rezultati su identični kao u prethodnom primjeru: NASLOV_CDISKA Toto: Africa Bijelo Dugme: Veliki hitovi Zdravko Colic: Najveci hitovi Tina Turns the Country On Acid Queen Unchain My Heart Tina Turns the Country On

IME_UMJETNIKA Toto Bijelo Dugme Zdravko Colic Tina Turner Tina Turner Joe Cocker Tina Turner

NAZIV_KOMPANIJE MC Records Star Records City Records United Artists EMI Records EMI Records EMI Records

ZALIHA 150 5 1010 5 6 8 2

Tabela 177: Rezultat upita nad tri tabele

3.9.1.3 Upit tipa SELF JOIN Još jedan tip spajanja koji se može kreirati je tzv. SELF-JOIN. Upiti ovog tipa predstavljaju ekvi-spajanja nad jednom tabelom (self – nad samom sobom). Oni se mogu izvoditi kao comma-separated ili kao cross join upiti. PRIMJER 80: Za ilustraciju upita tipa SELF JOIN, iskoristićemo tabelu ZAPOSLENI koju smo kreirali na početku poglavlja. Treba primjetiti da među poljima ID_ZAPOSLENOG i MENADZER ove tabele postoji logička veza. Ova veza ukazuje da je npr. zaposlenom „Vasilic“ nadređeni menadžer „Mikic“, kao i da je zaposlenom „Damjanovic“ nadređeni „Novakovic“. Tada će slijedeći SELF JOIN upit izlistati sve zaposlene i njima direktno nadređene: select a.ID_ZAPOSLENOG, a.PREZIME, b.PREZIME AS MGR from ZAPOSLENI a, ZAPOSLENI b where a.MENADZER = b.ID_ZAPOSLENOG order by a.ID_ZAPOSLENOG; Kod 154: SELF JOIN Dobijeni rezultati su pokazuju svakog od podređenih radnika i njima direktno nadređenog: ID_ZAPOSLENOG 2

PREZIME Novakovic

MGR Mikic

145

3 Vasilic 4 Damjanovic Tabela 178: Rezultat SELF JOIN-a

Mikic Novakovic

3.9.1.4 Ekvi-spajanje pomoću ključnih riječi NATURAL JOIN i USING Vidjeli smo da su u do sada iznesenim primjerima tabele bile logički povezane po kolonama koje su u obje tabele od interesa imale ista imena. Npr. tabele CDISKOVI i CD_UMJETNICI bile su vezane po koloni ID_UMJETNIKA koja ima isti naziv u obje tabele. Iako se tabele mogu spajati i po kolonama koje imaju različita imena, ipak je se u praksi pri samom projektovanju baze podataka pazi da nazivi ovakvih, logički povezanih kolona, imaju ista ili što sličnija imena, jer se na taj način poboljšava čitljivost i povećava jednostavnost rada sa takvom bazom podataka. Kako je ovakav način imenovanja je vrlo čest u praksi, SQL standard nam nudi još dva načina za izvođenje ekvi-spajanja ili prirodnog spajanja, pomoću ključnih riječi NATURAL JOIN i USING. Navođenjem ključnih riječi NATURAL JOIN, DBMS će automatski po jednakosti spojiti tabele po kolonama koje imaju ista imena, bez eksplicitnog navođenja njihovih imena. Ono što se mora upamtiti je da se ne radi o nekoj novoj vrsti prirodnog (ili ekvi) spajanja. Navedene ključne riječi samo nam omogućavaju jednostavniji način pisanja upita. PRIMJER 81: Ekvi-spajanje tabela CDISKOVI i IZDAVACI po koloni ID_IZDAVACA mogli bi napisati korištenjem ključnih riječi NATURAL JOIN na slijedeći način: select CD.NASLOV_CDISKA, UM.IME_UMJETNIKA, CD.ZALIHA from CDISKOVI CD natural join CD_UMJETNICI UM where CD.ZALIHA > 15 Kod 155: NATURAL JOIN Rezultat ovakvog upita bio bi: NASLOV_CDISKA IME_UMJETNIKA ZALIHA Zdravko Colic: Najveci hitovi Zdravko Colic 1010 Toto: Africa Toto 150 Tabela 179: Rezultat upita Da bi još jednom skrenuli pažnju na činjenicu da se radi o istom ekvi (prirodnom) spajanju, izvršićemo još jedan upit ekvivalentan prethodnom: select CD.NASLOV_CDISKA, UM.IME_UMJETNIKA, CD.ZALIHA from CDISKOVI CD, CD_UMJETNICI UM where CD.id_umjetnika = UM.id_umjetnika and CD.ZALIHA > 15 Kod 156: Ekvi spajanje Rezultat ovakvog upita bio bi identičan prethodno prikazanom. NASLOV_CDISKA

146

IME_UMJETNIKA

ZALIHA

Zdravko Colic: Najveci hitovi Zdravko Colic 1010 Toto: Africa Toto 150 Tabela 180: Rezultat upita Možemo reći da se prikazano ekvi-spajanje pomoću ključnih riječi NATURAL JOIN izvodi implicitno, jer nismo naveli kolone po kojima se spajanje vrši. SQL nam daje još jedan eksplicitan način za izvođenje operacije ekvi-spajanja pomoću spajanja po imenovanoj koloni upotrebom ključne riječi USING. Kod ove vrste upita, u okviru klauzule USING navodimo ime kolone po kojoj vršimo ekvispajanje. PRIMJER 82: Ekvi-spajanje tabela CDISKOVI i IZDAVACI po imenovanoj koloni ID_IZDAVACA mogli bi napisati korištenjem ključnih riječi JOIN i USING na slijedeći način: select CD.NASLOV_CDISKA, UM.IME_UMJETNIKA, CD.ZALIHA from CDISKOVI CD join CD_UMJETNICI UM using (ID_UMJETNIKA) where CD.ZALIHA > 15 Kod 157: Spajanje po imenovanoj koloni Rezultat ovakvog upita bio bi: NASLOV_CDISKA Zdravko Colic: Najveci hitovi Toto: Africa Tabela 181: Rezultat upita

3.9.2

IME_UMJETNIKA Zdravko Colic Toto

ZALIHA 1010 150

Unutrašnje i spoljno spajanje

Tokom ovog poglavlja, upoznali smo se sa različitim tipovima ekvi-spajanja. Tako se kod spajanja tipa comma-separated (zarezom razdvojeno) uslov spajanja se navodi u okviru WHERE klauzule. U slučaju ekvi-spajanja tipa NATURAL JOIN, uslov spajanja se određuje automatski na osnovu naziva kolona. U slučaju spajanja po imenovanoj koloni, uslov spajanja se navodi u okviru klauzule USING. SQL standard definiše još jednu vrstu spajanja koja se često naziva uslovno spajanje. Ako se koristi sintaksa uslovnog spajanja, ekvi-spajanje se izvodi navođenjem uslova spajanja u okviru ON klauzule, na način koji je vrlo sličan njegovom navođenju u okviru WHERE klauzule. Uslovno spajanje je vrlo popularno među SQL programerima zbog jasnoće, jednostavnosti i široke podrške u brojnim SQL platformama. Uslovno spajanje se dijeli na unutrašnja (INNER JOIN) i spoljna (OUTER JOIN) spajanja. INNER JOIN vraća samo one redove koji zadovoljavaju uslov ekvi-joina. S druge strane, OUTER JOIN može da vrati redove koji zadovoljavaju uslov ekvispajanja, ali i dio ili sve redove koji ne zadovoljavaju uslov ekvi-spajanja.

3.9.2.1 Upit tipa INNER JOIN INNER JOIN je najčešći tip uslovnog spajanja, koji se izvodi navođenjem ključnih riječi INNER JOIN ili samo ključne riječi JOIN. Sintaksa unutrašnjeg spajanja slijedi:

147

SELECT [LISTA_KOLONA] FROM [INNER] JOIN < NAZIV_TABELE > ON 100, ponovo se krećemo desno i pronalazimo traženi podatak. Međutim, podatak 100 iz prethodnog primjera vjerovatno se nalazi u nekom redu tabele. Pretpostavimo da se radi o tabeli IZDAVACI(ID_IZDAVACA, NAZIV_KOMPANIJE) i da smo DBMS-u postavili upit kojim pokušavamo da pronađemo naziv kompanije čiji ID je 100: select NAZIV_KOMPANIJE from IZDAVACI where ID_IZDAVACA = 100 Kod 173: Primjer upita Da bi navedeni primjer bio kompletan, treba reći i da indeksi u svojoj strukturi moraju sadržavati i pokazivače na mjesta (u datoteci ili na hard disku npr.) na kojima se nalaze redovi odgovarajuće tabele. Kada pomoću indeksa pronađemo čvor u kojem se nalazi traženi podatak (100), na osnovu sadržaja navedenog pokazivača (adrese u datoteci) mogli bi iz datoteke očitati traženi red tabele u kom se pored ID_IZDAVACA nalazi i traženi NAZIV_KOMPANIJE.

3.10.1 Automatski i korisnički definisani indeksi Firebird SUBP automatski kreira indekse pri kreiranju ograničenja čija je namjena očuvanje integriteta baze podataka. Međutim, uloga ovakvih automatskih indeksa nije ograničena samo na obezbjeđenje pravila integriteta. I ovakvi indeksi razmatraju od strane SUBP-a prilikom izvršenja upita i u mogu u velikoj mjeri ubrzati njihovo izvršenje. S druge strane, postoje i korisnički definisani indeksi koji se kreiraju pomoću ključnih riječi CREATE INDEX, pomoću kojih takođe možemo ubrzati izvršenje sporih upita. Slijedi sintaksa iskaza za kreiranje indeksa: create [UNIQUE] [ASC[ENDING] | DESC[ENDING]] index IME_INDEKSA ON IME_TABELE (KOLONA [,KOLONA...]); Sintaksa 37: CREATE INDEX sintaksa Obavezni dijelovi u sintaksi su, pored ključnih riječi CREATE INDEX .. ON i naziv indeksa, te naziv tabele i najmanje jedne kolone nad kojom kreiramo indeks. Naziv indeksa mora biti različit od naziva svih drugih objekata u bazi podataka. Opciona ključna riječ UNIQUE će ograničiti unos duplikata u navedenu kolonu ili kolone. Ključne riječi ASC i DESC određuju redoslijed sortiranja indeksa, pri čemu je podrazumjevana vrijednost ASC ako se ništa ne navede. PRIMJER 95: Nad kolonom NASLOV_CDISKA tabele CDISKOVI kreirati rastući indeks. create index CDISKOVI_NASLOV ON CDISKOVI(NASLOV_CDISKA) Kod 174:Kreiranje indeksa Kako nismo naveli niti ASC ni DESC ključne riječi, prethodni upit je kreirao rastući indeks nad kolonom NASLOV_CDISKA tabele CDISKOVI. Postojanje indeksa vidljivo je u uslužnim programima za administraciju baza podataka:

159

Slika 42: Stranica Object Browser - kartica INDEXES (Oracle Express)

Slika 43: Kartica INDICES programa FlameRobin (Firebird) Postojanje indeksa moguće je utvrditi i postavljanjem upita nad šemom baze podataka: /* Oracle Express */ /* Svi indeksi tabele 'CDISKOVI'*/ select index_name, index_type from user_indexes where TABLE_NAME = 'CDISKOVI'; /* Indeks pod imenom 'CDISKOVI_NASLOV' */ select index_name, index_type from user_indexes where INDEX_NAME = 'CDISKOVI_NASLOV'; Kod 175:Upit nad šemom baze podataka – Oracle /* Firebird 2.1 */ /* Svi indeksi tabele 'CDISKOVI'*/ select RDB$INDEX_NAME from RDB$INDICES where RDB$RELATION_NAME = 'CDISKOVI'; /* Indeks pod imenom 'CDISKOVI_NASLOV' */ select RDB$INDEX_NAME from RDB$INDICES where RDB$INDEX_NAME = 'CDISKOVI_NASLOV'; Kod 176:Upit nad šemom baze podataka – Firebird Kreiranje DESC indeksa prema sintaksi svodi se na jednostavno ubacivanje istoimene ključne riječi u iskaz za kreiranje indeksa.

160

PRIMJER 96: Nad kolonom NASLOV_CDISKA tabele CDISKOVI kreirati opadajući indeks. /* Oracle Express */ create index CDISKOVI_NASLOV_DESC ON CDISKOVI (NASLOV_CDISKA desc); /* Firebird 2.1 */ create desc index CDISKOVI_NASLOV_DESC ON CDISKOVI (NASLOV_CDISKA); Kod 177:Kreiranje indeksa Kako smo u upitu naveli ključnu riječ DESC, prethodni upit je kreirao opadajući indeks nad kolonom NASLOV_CDISKA tabele CDISKOVI. Nakon kreiranja DESC indeksa, kreiranje novog UNIQUE indeksa je još jednostavnije. PRIMJER 97: Nad kolonom IME_UMJETNIKA tabele CD_UMJETNICI kreirati UNIQUE indeks. create unique index CD_UMJETNICI_UN ON CD_UMJETNICI (IME_UMJETNIKA) Kod 178:Kreiranje indeksa Kako smo u upitu naveli ključnu riječ UNIQUE, prethodni upit je kreirao jedinstveni indeks nad kolonom IME_UMJETNIKA tabele CD_UMJETNICI. Kreiranjem UNIQUE indeksa obezbjeđujemo se da će sistem smjestiti samo po jednu (bez duplikata) vrijednost kolone IME_UMJETNIKA u svakom redu tabele CD_UMJETNICI. Treba primjetiti da će Firebird SUBP i prilikom kreiranja UNIQUE ograničenja automatski napraviti jedan UNIQUE indeks, koji će uzimati u obzir, između ostalog, i prilikom optimizacije upita. Postavlja se pitanje kakva je razlika između UNIQUE ograničenja i indeksa, ako i ograničenje i indeks sprječavaju pojavu duplikata i ako se oba uzimaju u obzir pri optimizaciji upita? Na prvi pogled vidljiva je samo formalna razlika jer SQL standard ne poznaje indekse. Međutim, ako radimo u nekom timu u kojem zajedno projektujemo neki sistem, korištenje UNIQUE indeksa da bi ograničili unos duplikata moglo bi zbuniti druge programere u timu i dovesti do nenamjernog uklanjanja ili mijenjanja ovakvog indeksa. S druge strane, UNIQUE ograničenje jasno govori svima da nam je namjera da spriječimo unos duplikata u kolonu/e koje su obuhvaćene ograničenjem. Automatski indeks kreiran u momentu kreiranja UNIQUE ograničenja ne može biti izmjenjen ni uklonjen slučajno – on se može uloniti samo uklanjanjem navedenog ograničenja. Većina SUBP omogućava i kreiranje kompozitnih (kompleksnih, ulančanih) indeksa, koji se definišu nad više kolona neke tabele. U skladu sa prikazanom sintaksom, takav indeks se definiše navođenjem više kolona neke tabele. PRIMJER 98: Nad kolonama IME_UMJETNIKA i NAZIV_CDA tabele UMJETNIK_ALBUM kreirati opadajući indeks. /* Oracle Express */ create index UM_ALB_I_N on UMJETNIK_ALBUM (IME_UMJETNIKA desc, NAZIV_CDA desc) /* Firebird 2.1 */ create desc index UM_ALB_I_N on UMJETNIK_ALBUM (IME_UMJETNIKA, NAZIV_CDA)

161

/* Firebird 2.1. ne dozvoljava sortiranje pojedinih kolona */ Kod 179:Kreiranje indeksa Ako razmišljamo o korištenju indeksa u svrhu optimizacije upita moramo voditi računa o odabranom pravcu sortiranja. Sa stanovišta optimizacije, nije svejedno da li je indeks opadajući ili rastući. Pretpostavka da indeks može pomoći pri sortiranju podataka u oba smjera je pogrešna. U prethodnom primjeru smo kreirali opadajući (DESC) indeks nad tabelom UMJETNIK_ALBUM iako je već postojao primarni ključ koji je sortiran u rastućem redoslijedu. Ono što je interesantno je da Firebird 2.1. ne dozvoljava sortiranje kompozitnog indeksa po svakoj koloni pojedinačno, već da je jedino moguće sortirati sve kolone koje pripadaju indeksu u opadajućem ili rastućem redoslijedu. Uklanjanje indeksa vrši se pomoću iskaza DROP INDEX ime_ind. Ovakav iskaz uklanja imenovani korisnički definisani indeks iz baze podataka. Sintaksa iskaza je: drop index IME_INDEKSA; Sintaksa 38: DROP INDEX sintaksa PRIMJER 99: Ukloniti ranije definisani indeks CD_UMJETNICI_UN nad kolonom IME_UMJETNIKA tabele CD_UMJETNICI. drop index CD_UMJETNICI_UN Kod 180:Uklanjanje indeksa PRIMJER 100: Ukloniti ranije kreirane indekse pod imenima CDISKOVI_NASLOV i CDISKOVI_NASLOV_DESC nad kolonom NASLOV_CDISKA tabele CDISKOVI: drop index CDISKOVI_NASLOV; drop index CDISKOVI_NASLOV_DESC; Kod 181:Uklanjanje indeksa Indeksi se na isti način uklanjaju i ako se radi o kompozitnim indeksima – indeksima koji su definisani nad više kolona neke tabele. Dovoljno je u iskazu DROP INDEX navesti ime indeksa. PRIMJER 101: Ukloniti ranije definisani indeks UM_ALB_I_N nad kolonama IME_UMJETNIKA i NAZIV_CDA tabele UMJETNIK_ALBUM. drop index UM_ALB_I_N Kod 182:Uklanjanje indeksa

3.10.2 Plan izvođenja upita Prije samog izvršenja upita, SUBP poziva odgovarajući skup rutina koje se zajedničkim imenom nazivaju optimizator. Optimizator uzima u obzir tabele, kolone i operacije koje treba obaviti da bi izračunao najefikasniji način za izvršenje nekog upita. Optimizator svoj posao počinje pretraživanjem indeksa koji su definisani nad tabelama i kolonama 48 koje se nalaze u upitu. Na osnovu izračunavanja „cijene“ pojedinih načina izvršenja, optimizator odabira najefikasniji plan. Svaki pojedini plan na neki način predstavlja mapu puta ili skup koraka koji se moraju izvršiti tokom izvršavanju upita. Finalni plan predstavlja „naj jeftinije“ rješenje koje u datom momentu SUBP može da ponudi. 48

Jedan od najtežih problema pri optimizaciji upita je izračunavanje „cijene“ različitih mogućih pristupa izvršenju. U teoriji baza podataka često se javljaju termini „skup“ i „košta“ koji se odnose na potrebno vrijeme i zauzetost resursa koji su potrebni za izvršenje nekog upita. Npr. kaže se da je neki upit „skup“ ako će njegovo izvršenje trajati mnogo vremena.

162

Da bi mogli da pregledamo plan izvršenja upita, Oracle Express nam nudi EXPLAIN PLAN iskaz, koji ima dva slijedeća oblika: explain plan for SQL_UPIT, koji će rezultate smjestiti u specijalnu tabelu (objekat) pod nazivom DBMS_XPLAN. Iz ove tabele, rezultate je moguće preuzeti pomoću upita SELECT * FROM TABLE(dbms_xplan.display); explain plan into NAZIV_TABELE for SQL_UPIT, koji će plan smjestiti u neku korisnički definisanu tabelu. Plan izvršenja nekog upita u Firebirdovom uslužnom programu isql može se dobiti upotrebom slijedeća dva iskaza: SET PLAN ON – će instruisati isql da pri svakom SELECT iskazu prikaže i plan njegovog izvršenja, SET PLANONLY – će instruisati isql da umjesto da izvrši upit prikaže samo plan njegovog izvršenja. Plan nekog upita može se vidjeti i u programima za administraciju baza podataka kao što su SQL Manager for Oracle, FlameRobin ili IBExpert. PRIMJER 102: Da bi mogli da analiziramo ponašanje i uticaj indeksa na optimizaciju upita u Oracle Expresu, pokrenućemo prozor SQL Commands u Internet Exploreru i unijeti slijedeći upit: select NASLOV_CDISKA from CDISKOVI where NASLOV_CDISKA > 'T' order by NASLOV_CDISKA Kod 183:Upit za analizu Nakon što upišemo upit u editor, nakon njegovog pokretanja kliknućemo na karticu „Explain“:

Slika 44: Plan izvršenja Sa slike je vidljivo da prilikom izvršenja ovog upita, Oracle Express neće moći da koristi indekse, jer je kreiran samo jedan indeks (primarni ključ) nad kolonom CDISK_ID.

163

Iako to u slučaju tabela sa ovako malim brojem podataka nije potrebno, radi eksperimenta ćemo kreirati indeks nad kolonom NASLOV_CDISKA tabele CDISKOVI, pa ćemo nakon toga ponovo pogledati plan izvršenja upita: create index NASLOVX on CDISKOVI(NASLOV_CDISKA) Kod 184:Kreiranje indeksa Nakon ponovnog izvršenja istog upita, kartica Explain sada nam daje nešto drugačije rezultate:

Slika 45: Plan izvršenja Sa slike je vidljivo da Oracle Express sada ima na raspolaganju indeks NASLOVX koji može da koristi da bi ubrzao izvršenje prethodnog upita.

PRIMJER 103: Da bi mogli da analiziramo ponašanje i uticaj indeksa na optimizaciju upita, pokrenućemo SQL Editor programa FlameRobin (meni „Run a Query“) i upisati slijedeći veoma jednostavan upit: select NASLOV_CDISKA from CDISKOVI where NASLOV_CDISKA > 'T' order by NASLOV_CDISKA Kod 185:Upit za analizu Nakon što upišemo upit u editor, umjesto njegovog pokretanja dugmetom „Execute statement“ kliknućemo na prvo dugme desno „Show query execution plan“:

164

Slika 46: SQL editor i dugme Show query execution plan“ programa FlameRobin U donjem oknu prozora, umjesto rezultata upita prikazan je plan njegovog izvršenja: Starting transaction... Preparing query: select NASLOV_CDISKA from CDISKOVI order by NASLOV_CDISKA Prepare time: 0.067s Field #01: CDISKOVI.NASLOV_CDISKA Alias:NASLOV_CDISKA Type:STRING(60) PLAN SORT ((CDISKOVI NATURAL)) Script execution finished. Kod 186:Plan izvršenja Prvih nekoliko linija prikazuju sam upit koji se obrađuje. Nakon njih slijedi „prepare time“ ili vrijeme koje je potrebno da se pronađe najbolji plan i da se upit pripremi za izvršenje. Nakon toga prikazana je kolona (NASLOV_CDISKA) koja će se pojaviti u rezultatu upita. Najzanimljivija linija označena je podebljano (boldom): PLAN SORT ((CDISKOVI NATURAL)) Iz navedene linije takođe je vidljivo i da će za pristup redovima tabele CDISKOVI korisititi NATURAL pristup. Riječ NATURAL znači da navedena kolona nije indeksirana – DBMS ovakvoj tabeli mora da pristupa sekvencijalno, onim redom kojim su podaci uneseni. Izvršenje ovakvog upita nad većim skupovima podataka moglo trajati prilično dugo, jer smo u upitu tražili da podaci budu sortirani po rastućem redoslijedu, a DBMS tražene podatke mora da sortira u toku izvršenja upita. Sada ćemo kreirati indeks nad kolonom NASLOV_CDISKA tabele CDISKOVI, pa ćemo nakon toga ponovo pogledati plan izvršenja upita: create index NASLOVX on CDISKOVI(NASLOV_CDISKA) Kod 187:Kreiranje indeksa

165

Ako bi sada ponovo zatražili plan izvršenja upita u FlameRobinu ( „Show query execution plan“) imali bi: Starting transaction... Preparing query: select NASLOV_CDISKA from CDISKOVI order by NASLOV_CDISKA Prepare time: 0.077s Field #01: CDISKOVI.NASLOV_CDISKA Alias:NASLOV_CDISKA Type:STRING(60) PLAN (CDISKOVI ORDER NASLOVX INDEX (NASLOVX)) Script execution finished. Kod 188:Plan izvršenja Nakon prvih nekoliko linija koje imaju isto značenje koje je ranije već objašnjeno, slijedi najzanimljivija linija koja je označena podebljano (boldom): PLAN (CDISKOVI ORDER NASLOVX INDEX (NASLOVX)) Optimizator je pronašao indeks koji smo kreirali nad kolonom NASLOV_CDISKA po kojoj vršimo sortiranje i njega će koristiti pri izvršenju navedenog upita. Kako su podaci koji se nalaze u tabeli već sortirani pomoću indeksa, SUBP neće gubiti vrijeme na njihovo sortiranje tokom izvršenja samog upita. Takođe, prilikom selekcije po uslovu where NASLOV_CDISKA > 'T', optimizator neće ni uzimati u obzir redove koji ne zadovoljavaju uslov. Zbog toga će se ovakav upit nad indeksiranom kolonom u slučaju kada se u tabeli nalazi velika količina podataka, izvršavati višestruko brže.

3.10.3 Kada indeksi mogu pomoći Kada optimizator odluči da koristi neki indeks pri realizaciji nekog upita, on preko pokazivača (pointera odnosno adresa) nalazi stvarne podatke. Očitavanje podataka je u ovom slučaju brzo jer su vrijednosti u indeksima sortirane. Ova činjenica omogućava sistemu da tražene podatke locira preko pokazivača (pointera). Na ovaj način sistem izbjegava očitavanje svih redova tabele koji prethode ovom redu, što bi morao da uradi u slučaju sekvencijalnog pristupa. Dakle, osnovna ideja pri korištenju indeksa je da se izbjegne prolaženje kroz sve redove neke tabele kada god se traži neki podatak iz nje. Kad se u upitima nalaze ORDER BY i GROUP BY klauzule, indeksi mogu u velikoj mjeri pomoći optimizatoru za ubrzanje izvršenja upita. Ako su u upitu nalazi funkcija Max(), postojanje opadajućeg (DESCENDING) indeksa će u najvećoj mjeri ubrzati pristup podacima. U slučaju JOIN-a, optimizator prolazi kroz proces spajanja odgovarajućih tokova podataka na osnovu implicitno ili eksplicitno zadanog „ON“ uslova. Ako na bilo kojoj strani JOIN-a postoji indeks, optimizator može da ga iskoristi za kreiranje inicijalnog toka podataka i da znatno ubrza izvršenje upita. Ako u se u upitu nalaze operacije poređenja, indeksi mogu biti upotrebljeni na takav način da se ni ne pristupa redovima koji ne zadovoljavaju uslov poređenja. Ako neka aplikacija mora često da pretražuje, sortira ili grupiše podatke po više od jedne kolone neke tabele, korisno je kreirati kompozitni (kompleksni) indeks nad tim kolonama. U slučaju korištenja kompozitnih ili kompleksnih indeksa, optimizator može 49 da iskoristi takve indekse prema pravilu koje se naziva „s-lijeva-u-desno“. 49

H.Borrie, The Firebird Book: A Reference for Database Developers, H.Borrie and IBPhoenix, 2004

166

Optimizator može da koristi kompozitni indeks samo ako se u ORDER BY klauzuli koriste sve ili prvih n kolona koje su navedene u definiciji indeksa. Dakle, pravilo „s-lijeva-u-desno“ će biti zadovoljeno ako su u ORDER BY klauzuli navedene: •

Sve kolone koje se nalaze u definiciji kompozitnog indeksa ili



Podskup kolona koje se nalaze u definiciji kompozitnog indeksa, s tim da u ORDER BY klauzuli prvo mora biti navedena prva kolona koja pripada indeksu, dok se ostale slažu s lijeva u desno.

Da bi objasnili ovo pravilo, ranije kreiranoj tabeli ODJELJENJE(ODJELJENJE_ID, NAZIV, GRAD) ćemo kreirati novi indeks: create index ODJELJENJE_IDX1 on ODJELJENJE(ODJELJENJE_ID,NAZIV,GRAD) Kod 189:Kreiranje indeksa U upitima u kojima se traži sortiranje po prvoj, prve dvije i sve tri kolone optimizator će biti u stanju da iskoristi postojanje indeksa. Npr. ako posmatramo upit: select * FROM odjeljenje order by ODJELJENJE_ID, NAZIV, GRAD Kod 190:Test upit 1 Njegov plan izvršenja pokazuje da je optimizator u stanju iskoristi postojanje kompozitnog indeksa, čiji je redoslijed sortiranja identičan onom koji je naveden u upitu. PLAN (ODJELJENJE ORDER ODJELJENJE_IDX1) Ako posmatramo slijedeći upit: select * FROM odjeljenje order by ODJELJENJE_ID, NAZIV Kod 191:Test upit 1 Iako se u upitu koriste samo dva od tri kolone navedena u indeksu, prema pravilu „slijeva-u-desno“ i ovdje optimizator uspijeva da iskoristi postojanje indeksa. PLAN (ODJELJENJE ORDER ODJELJENJE_IDX1) U slijedećem upitu tražimo sortiranje samo po jednoj koloni: select * FROM odjeljenje order by ODJELJENJE_ID Kod 192:Test upit 1 I kada se u upitu traži sortiranje samo po jednoj od od tri kolone navedena u indeksu, prema pravilu „s-lijeva-u-desno“ i ovdje optimizator uspijeva da iskoristi postojanje indeksa. PLAN (ODJELJENJE ORDER ODJELJENJE_IDX1) Međutim, optimizator ne uspijeva da iskoristi postojanje indeksa u slijedećim slučajevima: select * FROM ODJELJENJE order by NAZIV, GRAD; select * FROM ODJELJENJE

167

order by ODJELJENJE_ID, GRAD select * FROM ODJELJENJE order by NAZIV, ODJELJENJE_ID

Kod 193:Test upit 1 Pravilo „s-lijeva-u-desno“ u stvari služi samo kao podsjetnik koji nas tjera da razmišljamo o načinu na koji će vrijednosti biti indeksom sortirane – kada smo SQL iskazom kreirali indeks po poljima ODJELJENJE_ID, NAZIV, GRAD, u stvari smo podatke sortirali najprije po koloni ODJELJENJE_ID, pa zatim po koloni NAZIV i tek onda po koloni GRAD.

168

3.10.4 Pogledi (Views) U prethodnim poglavljima vidjeli smo da su perzistentne tabele predviđene da čuvaju podatke u bazi podataka. Međutim, ovakve tabele ne daju uvjek podatke u korsnicima upotrebljivoj formi. U ranijem izlaganju smo vidjeli i da je rezultat SQL upita nad nekom tabelom ili tabelama takođe tabela, koja ponovo može da bude operand nekog SQL upita. Ako takvoj tabeli koja je nastala kao rezultat nekog upita dodjelimo ime dobijamo 50 tabelu koja se naziva pogled ili view. Zbog toga, SQL standard definiše mogućnost da upite imenujemo i snimimo u šemi baze podataka pomoću CREATE VIEW iskaza. Pogled (View) je specifikacija tabele koja ne drži nikakve podatke. On se ponaša kao filter nad kolonama i redovima tabela koje su povezane sa njim. Osnovna sintaksa za kreiranje pogleda je: create view NAZIV_POGLEDA [(NAZIV_KOLONE_POGLEDA [,NAZIV_KOLONE_POGLEDA [,...]])] as [with check option]; Sintaksa 39: Osnovna sintaksa za kreiranje pogleda (View) Za sada ćemo se fokusirati samo na prva četiri reda sintakse, dok ćemo zadnji red (with check option) obraditi nešto kasnije. Pri kreiranju pogleda, nakon navođenja ključnih riječi CREATE VIEW i njegovog naziva, moramo navesti i nazive kolona koje će činiti rezultirajuću tabelu nastalu iz pogleda. Nakon ključne riječi AS slijedi i SELECT iskaz kojim određujemo koje će podatke pogled preuzeti iz tabele ili tabela. Broj kolona koje definišemo u sastavu pogleda mora se slagati sa brojem kolona koje će vratiti spomenuti SELECT iskaz. Da bi vidjeli rezultat kreiranja pogleda na djelu, pogledaćemo slijedeći primjer: PRIMJER 104: Korištenjem ključnih riječi CREATE VIEW kreirati pogled koji će iz tabele CD_INVENTAR preuzeti kolone NAZIV_CDA i NA_STANJU: create view VIEW_CD_INVENTAR (NAZIV_CDA, NA_STANJU) as select NAZIV_CDA, NA_STANJU from CD_INVENTAR; Kod 194:Kreiranje pogleda Iz sintakse slijedi da se pogledi mogu kreirati i bez liste kolona: create view VIEW_CD_INVENTAR2 as select NAZIV_CDA, NA_STANJU from CD_INVENTAR; Kod 195:Kreiranje pogleda bez liste kolona Kako je pogled u stvari virtuelna tabela, nad prethodno kreiranim pogledom možemo pokrenuti npr. slijedeći SELECT iskaz: select * from VIEW_CD_INVENTAR Kod 196:SELECT iskaz nad pogledom NAZIV_CDA Bijelo Dugme: Veliki hitovi Toto: Africa 50

NA_STANJU 5 150

B.Lazarević, Z.Marjanović, N.Aničić,S.Babarogić, Baze podataka, FON, Beograd 2008

169

Zdravko Colic: Najveci hitovi 1010 Tabela 199: Rezultat SELECT upita nad pogledom VIEW_CD_INVENTAR Da bi uklonili definiciju pogleda iz šeme baze podataka, koristimo DROP iskaz: drop view NAZIV_POGLEDA; Sintaksa 40: Osnovna sintaksa za uklanjanje pogleda (View) Firebird DBMS ne omogućava izmjenu pogleda pomoću iskaza ALTER. Zbog toga, da bi izvršili izmjenu pogleda, najprije da moramo ukloniti iz šeme baze podataka, pa ponovo definisati, kao u slijedećemo primjeru: PRIMJER 105: Izmjeniti ranije kreirani pogled (View) tako da iz tabele CD_INVENTAR u kolonama kolone NAZIV_CDA i NA_STANJU preuzima samo redove kod kojih je sadržaj kolone NA_STANJU veći od 100. Ranije kreirani pogled najprije moramo izbaciti iz šeme baze podataka: drop view VIEW_CD_INVENTAR; Kod 197:Brisanje pogleda Tek sada možemo napraviti novi pogled pod istim imenom: create view VIEW_CD_INVENTAR (NAZIV_CDA, NA_STANJU) as select NAZIV_CDA, NA_STANJU from CD_INVENTAR where NA_STANJU > 100; Kod 198:Kreiranje pogleda Nad prethodno kreiranim pogledom možemo pokrenuti npr. slijedeći SELECT iskaz: select * from VIEW_CD_INVENTAR Kod 199:SELECT iskaz nad pogledom NAZIV_CDA NA_STANJU Toto: Africa 150 Zdravko Colic: Najveci hitovi 1010 Tabela 200: Rezultat SELECT upita nad pogledom VIEW_CD_INVENTAR Kreirani pogled se, bar što se tiče SELECT iskaza, ponaša kao bazna tabela, koju možemo uključiti u bilo koji drugi SELECT iskaz: PRIMJER 106: Napisati SELECT upit koji će iz pogleda VIEW_CD_INVENTAR filtrirati samo redove čiji je sadržaj kolone NA_STANJU veći od 1000. select * from VIEW_CD_INVENTAR where NA_STANJU > 1000; Kod 200:SELECT iskaz nad pogledom NAZIV_CDA NA_STANJU Zdravko Colic: Najveci hitovi 1010 Tabela 201: Rezultat SELECT upita nad pogledom VIEW_CD_INVENTAR Treba primjetiti da ovakva upotreba pogleda nema previše smisla – što se performansi tiče, bolje bi bilo napisati pogled koji odmah vraća samo redove čiji sadržaj kolone NA_STANJU je veći od 1000, nego dva puta vršiti filtriranje. Međutim, ovaj primjer najbolje pokazuje da se pogled u SELECT iskazima ponaša kao obična tabela.

170

SQL standard dozvoljava i kreiranje pogleda čiji podaci nastaju primjernom SELECT iskaza nad više tabela. PRIMJER 107: Pretpostavimo da je potrebno da kreiramo pogled (View) kojim ćemo prikazati sve redove iz tabela CDISKOVI i CD_UMJETNICI koji imaju istu vrijednost u kolonama ID_UMJETNIKA. U rezultatu su nam potrebne samo kolone NASLOV_CDISKA, IME_UMJETNIKA i ZALIHA. create view V_NASLOV_CDISKA (NASLOV_CDISKA, IME_UMJETNIKA, ZALIHA) as select CDISKOVI.NASLOV_CDISKA, CD_UMJETNICI.IME_UMJETNIKA, CDISKOVI.ZALIHA from CDISKOVI, CD_UMJETNICI where CDISKOVI.id_umjetnika = CD_UMJETNICI.id_umjetnika Kod 201:Kriranje pogleda nad više tabela Rezultat SELECT * from V_NASLOV_CDISKA upita bio bi: NASLOV_CDISKA IME_UMJETNIKA ZALIHA Zdravko Colic: Najveci hitovi Zdravko Colic 1,010 Bijelo Dugme: Veliki hitovi Bijelo Dugme 5 Toto: Africa Toto 150 Tina Turns the Country On Tina Turner 5 Acid Queen Tina Turner 6 Unchain My Heart Joe Cocker 8 Tina Turns the Country On Tina Turner 2 Tabela 202: Rezultat SELECT upita nad pogledom V_NASLOV_CDISKA Firebirdovi pogledi ne mogu imati indekse niti ključeve. Bazne tabele od kojih se pogled sastoji koriste se kada optimizator treba da napravi plan upita. Osnovne prednosti korištenja pogleda su: •

Jednostavnost korištenja. Poglede mogu da definišu administratori baze i da takve jednostavne tabele stave na uvid korisnicima.



Sigurnost podataka. Pogled predstavlja moćan mehanizam kontrole pristupa podacima. Preko pogleda se korisnicima stavljaju na uvid samo neki podaci iz baze podataka.



Performanse. Pogled se u šemi baze podataka čuva u kompajliranom obliku.



Nezavisnost podataka. Ako korisnik razvija svoj program nad pogledom, promjena baze podataka neće zahtjevati promjenu njegovog programa, već samo promjenu definicije pogleda.

Osnovni problemi u korištenju pogleda su problemi ažuriranja baze podataka. Postoje mnogi pokušaji da se terijski definiše preko kojih pogleda je moguće ažurirati bazu podataka. Neke preporuke koje treba poštovati da bi preko pogleda mogla da se ažurira baza podataka su: •

U FROM klauzuli upita koji definiše pogled može da bude navedena samo jedna tabela,



U upitu ne treba koristiti GROUP BY i HAVING klauzule,



Ne treba koristiti ključnu riječ DISTINCT,

171



U WHERE klauzuli ne treba da se nalazi podupit koji se referencira na tabelu u FROM klauzuli upita direktno ili preko nekog pogleda,



Sve kolone u upitu koji formira pogled moraju biti imena kolona bazne tabele i ne mogu biti agregatne funkcije.

Dio sintakse WITH CHECK OPTION se koristi samo pri kreiranju pogleda. Ova klauzula se uključuje samo u poglede koje je moguće ažurirati. Njena uloga je da blokira bilo koju operaciju ažuriranja koja će narušiti uslov naveden u WHERE klauzuli pogleda. PRIMJER 108: Ako bi kreirali slijedeći pogled: create view VIEW_CD_INVENTAR3 as select NAZIV_CDA, NA_STANJU from CD_INVENTAR where NA_STANJU < 1500 with check option; Kod 202:Kreiranje pogleda sa CHECK opcijom Ako bi sada pokušali da u ažuriramo pogled pomoći upita: update VIEW_CD_INVENTAR3 set NA_STANJU = 5000 Kod 203:Ažuriranje pogleda Dobili bi poruku da je došlo do greške jer ažuriranje narušava CHECK ograničenje. /* Oracle Express */ ORA-01402: view WITH CHECK OPTION where-clause violation /* Firebird 2.1 */ Operation violates CHECK constraint Operation violates CHECK constraint VIEW_CD_INVENTAR3. Kod 204:Error poruka

172

on view or table. on view or table

3.10.5 Kreiranje SQL rutina – Stored procedure i Trigeri

3.10.5.1 Stored procedure Prije objavljivanja standarda SQL 1999 ANSI i ISO organizacije su 1996. godine objavile dopunu postojećeg standarda kojim su u SQL dodane procedure i funkcije. Ovaj dodatak standardu pod nazivom PSM-96 (PSM - Persistent Stored Module), predstavljao je prvi korak prema uključivanju SQL rutina u sam standard. Izmjenjena i dopunjena verzija ovog dodatka koja je uključena u standard SQL 1999 definisala je postojanje funkcija i procedura u SQL jeziku. SQL funkcije i procedure predstavljaju imenovane skupove predefinisanih iskaza koji izvode određene akcije nad podacima u bazi i koje su na neki način sačuvane u bazi podataka. Npr. mogli bi definisati proceduru koja izvršava određeni SELECT iskaz i snimiti je u bazu podataka. Takvu proceduru kasnije možemo pozivati preko njenog imena. Za razliku od pogleda (View) procedure i funkcije dozvoljavaju upotrebu parametara. Parmetri predstavljaju vrijednosti koje predajemo rutini i koje preuzimamo od rutine nakon njenog izvršenja. Osnovna razlika između funkcija i procedura je u tome što procedure mogu da uzimaju ulazne parametre i vraćaju izlazne, dok funkcije uzimaju ulazne, ali vraćaju samo jednu vrijednost. U različitim implementacijama SQL-a, procedure se najčešće nazivaju stored procedure, a funkcije korisnički definisane funkcije (User Defined Functions). Kažemo u najčešće jer npr. Firebird SUBP korisnički definisane funkcije tretitra nešto drugačije – za ovaj SUBP to su funkcije koje su definisane van šeme baze podataka, u nekom eksternom modulu (npr. DLL-u). Kako se radi o pravim malim programskim jezicima koji se nalaze u okviru SUBP, pojedinačno ćemo obraditi Oracle XE i Firebordov način kreiranja stored procedura.

3.10.5.2 Oracle stored procedure Oracle Express Edition ima mogućnost da kompajlira i snima procedure i funkcije u okviru šeme baze podataka. Jednom kada su kompajlirane, ovakve procedure i funkcije postaju dio šeme baze podataka, pa se mogu pozivati iz različitih aplikacija koje su povezane na Oracle XE. Stored procedure i funkcije mogu da preuzmu ulazne parametre u momentu njihovog pozivanja. Da bi izvršili neku proceduru ili funkciju, moramo je pozvati po njenom imenu. Jezik za kreiranje stored procedura i funkcija u Oracle XE se naziva PL/SQL (Procedural Language/SQL). Da bi kreirali stored proceduru, koristi se CREATE PROCEDURE iskaz. Prilikom kreiranja navodimo ime procedure, njene ulazne i izlazne parametre, lokalne varijable i BEGIN...END blok koji sadrži kod procedure. Osnovna sintaksa za kreiranje stored procedure je: create [or replace] procedure IME_PROCEDURE [(ARGUMENT tip_podatka [,ARGUMENT tip_podatka [...]])] is [[variabla] tip_podatka; [...]] begin ; end Sintaksa 41: Osnovna sintaksa ORACLE STORED PROCEDURE Za sam početak, u slijedećem primjeru, kreiraćemo jednu vrlo jednostavnu proceduru koristeći SQL Commands stranicu:

173

create or replace procedure ZDRAVO as begin dbms_output.put_line('Zdravo svima!'); end; Kod 205:Prva stored procedura U prvoj kreiranoj stored proceduri, koristili smo DBMS_OUTPUT paket (package) , koji služi za slanje poruka drugim stored procedurama, trigerima, ali i za slanje poruka u konzolu. Oracle paketi su grupe funkcija, procedura, varijabli i SQL iskaza koji su kreirani i objedinjeni u jednu cjelinu. Objektima koji su smješteni u paketu pristupamo preko njihovog imena. U okviru paketa dbms_output nalazi se i funkcija put_line koja služi da bi u konzolnom prozoru ispisala neku poruku. Da bi pokrenuli upravo napisanu proceduru, u SQL Commands prozoru moramo unijeti slijedeći kod begin zdravo; end; Kod 206:Poziv prve stored procedure Na izlazu, u dijelu Results prozora SQL Commands ćemo imati: Zdravo svima! Statement processed. 0,00 seconds Kod 207:Izlaz prve stored procedure Već smo spominjali da Oracle-ov PL/SQL dozvoljava da kreiramo module u kojima se mogu naći različiti objekti, kao što su stored procedure, funkcije, trigeri (koje ćemo upoznati u slijedećem poglavlju) i varijable. Paketi (packages) se kreiraju pomoću iskaza CREATE PACKAGE: create [or replace] package IME_PAKETA as procedure NAZIV_PROCEDURE; procedure NAZIV_PROCEDURE2; ... NAZIV_VARIJABLE tip_podatka := vrijednost; end Sintaksa 42: Osnovna sintaksa za kreiranje paketa U slijedećem primjeru kreiraćemo paket pod nazivom PRVI_PAKET i unutar njega proceduru ZDRAVO koju smo upravo napravili. create or replace package PRVI_PAKET as procedure ZDRAVO; end; Kod 208:Kreiranje paketa PRVI_PAKET U slijedećem primjeru ćemo kreirati proceduru pod imenom DANAS_JE koja treba da ispiše današnji datum u konzoli:

174

create or replace procedure DANAS_JE as begin dbms_output.put_line( 'Danas je ' || TO_CHAR(SYSDATE, ' DD-MM-YYYY HH24:MI:SS')); end; Kod 209:Druga stored procedura – DANAS_JE Prikazana procedura DANAS_JE takođe koristi usluge paketa dbms_output da bi ispisala rezultat. Zadatak funkcije TO_CHAR je da sistemski datum pretvori u tekstualni podatak i da fromatira ispis prema datoj maski „DD-MM-YYYY“. Već smo spominjali da unutar paketa možemo definisati i varijable. Da bi unutar paketa PRVI_PAKET definisali varijablu PDV_STOPA i dodali deklaraciju procedure DANAS_JE, izvršićemo slijedeći upit: create or replace package PRVI_PAKET as procedure ZDRAVO; procedure DANAS_JE; PDV_STOPA number(18,2) := 1.17; end; Kod 210:Izmjena paketa PRVI_PAKET Kreiranje varijable u okviru nekog paketa ne bi imalo mnogo smisla ako takvu varijablu ne bi mogli pozvati iz neke stored procedure. Međutim, u okviru stored procedura dozvoljeno je deklarisati i varijable različitog tipa i izvršavati različite SQL upite. U slijedećem primjeru ćemo se upoznati sa načinom kreiranja lokalnih varijabli, te vidjeti i kako se iz stored procedure mogu izvršavati SQL upiti. create or replace procedure PDV as IZNOS_SA_PDV number(18,2); begin IZNOS_SA_PDV := 0; select SUM(CIJENA * KOMADA) * PRVI_PAKET.PDV_STOPA into IZNOS_SA_PDV from ZALIHA_DISKOVA ; dbms_output.put_line( 'Sa PDV-om ' || TO_CHAR(IZNOS_SA_PDV, '99999.99' )); end; /*Maska moze biti '99999.99' ili '99999,99'*/ Kod 211:Stored procedura PDV Prethodni primjer predstavlja nam nekoliko novih koncepata. Lokalne varijable (local variables) se u stored procedurama deklarišu neposredno pred početak BEGIN...END bloka. Sama definicija je jednostavna – dovoljno je navesti naziv varijable i njen tip podataka: IZNOS_SA_PDV number; Pri tome se dodjela vrijednosti varijabli vrši pomoću simbola dvotačka-znak jednakosti: IZNOS_SA_PDV := 0; Pozivanje varijabli koje su definisane u okviru paketa vrši se navođenjem imena paketa nakon kojeg, odvojeno tačkom, slijedi ime same varijable:

175

PRVI_PAKET.PDV_STOPA U okviru BEGIN...END bloka u kojem se nalazi kod procedure, moguće je izvršavati različite SQL upite. Ključna riječ INTO pruža nam mehanizam pomoću kojeg se od SELECT upita (koji vraćaju rezultate) preuzimaju podaci: ... into IZNOS_SA_PDV... Zadnja linija procedure PDV služi za ispis rezultata, pri čemu se koristi funkcija TO_CHAR u kojoj je odabrana numerička maska ’99999.99’ ili ’99999,99’. Ova maska pruža nam način da formatiramo ispis broja i da ograničimo broj decimalnih mjesta koji će biti prikazani pri ispisu rezultata. Međutim, lokalne varijable nisu jedine varijable koje možemo definisati u okviru Oracleovih stored procedura. Postoje još tri tipa varijabli: •

Varijable tipa IN koje služe kao ulazni parametri kojim prebacujemo proceduri neku vrijednost,



Varijable tipa OUT koje služe da daju izlaz iz procedure i



Varijable tipa IN OUT je varijabla koja može biti proslijeđena kao ulazni argument i koja kasnije može biti izmjenjena u proceduri.

Pogledaćemo slijedeći primjer: create or replace procedure RAZLICITE_VARIJABLE (ID in number, IZLAZ out varchar2 ) as NASLOV CDISKOVI.NASLOV_CDISKA%type; begin select NASLOV_CDISKA into NASLOV from CDISKOVI where CDISK_ID = ID; IZLAZ := 'Naslov diska je pod brojem ' || ID || ' je ' || NASLOV ; end; Kod 212:Stored procedura RAZLICITE_VARIJABLE

U proceduri RAZLICITE_VARIJABLE koristićemo dva nova tipa varijabli – IN i OUT. Ulazni i izlazni argumenti (varijble) se navode neposredno nakon naziva stored procedure. Ulazni argumanti se navode imenom, nakon kojeg slijedi ključna riječ IN, a nakon nje se navodi tip podatka argumenta. Izlazni argumenti se takođe definišu navođenjem imena, nakon kojeg slijedi ključna riječ OUT a zatim i tip podatka argumenta. Ako procedura ima više bilo ulaznih, bilo izlaznih argumenata, oni moraju biti odvojeni zarezima: ...(ID in number, IZLAZ out varchar2)...

Još jedan način deklarisanja lokalnih varijabli je korištenjem ključne riječi %TYPE. Lokalne varijable koje će učestvovati u npr. SELECT iskazu možemo deklarisati na ovaj način bez navođenja tipa podatka, jer će ključna riječ %TYPE jednostavno preuzeti tip podređene kolone (u našem slučaju preuzeće tip podatka kolone CDISKOVI.NASLOV_CDISKA ): ...NASLOV

CDISKOVI.NASLOV_CDISKA%type;

... ...select NASLOV_CDISKA into NASLOV... Da bi pozvali ovakvu proceduru, moramo joj proslijediti ulazni parametar, i moramo imati mogućnost da prikažemo njen izlaz. U slijedećem primjeru, pozvaćemo proceduru iz SQL Commands prozora:

176

declare ID number := 1; NAZIV varchar2(100); begin RAZLICITE_VARIJABLE (ID, NAZIV ); DBMS_OUTPUT.PUT_LINE( NAZIV ); end; Kod 213:Poziv stored procedure RAZLICITE_VARIJABLE

Primjetite da smo i prilikom pozivanja ove funkcije definisali dvije varijable. Prva od njih, ID, služi da bi proceduri prenijeli ulazni argument. Druga varijabla, NAZIV, treba da preuzme vrijednost koju procedura vraća. Kada na ovaj način pozivamo proceduru, njeni argumenti se moraju slagati po redu, broju i tipu podatka. Slijedi prikaz izlaz iz procedure RAZLICITE_VARIJABLE: Naslov diska je pod brojem 1 je Tina Turns the Country On Statement processed. 0,05 seconds Kod 214:Izlaz stored procedure RAZLICITE_VARIJABLE Najteži dio pri kreiranju stored procedura je kreiranje kursora koji mogu da prolaze kroz skup redova neke tabele. Kursor varijable (REF CURSORs) se ponašaju kao pokazivači koji pokazuju odgovarajuće redove u nekoj tabeli. Kada definišemo kursor varijablu nad nekim upitom, on će sadržavati korektan skup kolona koje su definisane samim upitom. Tip podatka neke kursor varijable je REF CURSOR tip, a one se često neformalno 51 nazivaju REF KURSORI (REF CURSORS) . U slijedećem primjeru ćemo iskoristiti kursor i lokalno kreiranu stored proceduru. U SQL Commands prozor ćemo unijeti slijedeći kod: declare type CD_REFKURSOR_TIP is ref cursor return CDISKOVI%ROWTYPE; CD_KURSOR CD_REFKURSOR_TIP; procedure OBRADI_REDOVE (JEDAN_RED in CD_REFKURSOR_TIP) is CDISK_RED CDISKOVI%ROWTYPE; begin DBMS_OUTPUT.PUT_LINE('-- Rezultati --'); loop fetch JEDAN_RED into CDISK_RED; exit when JEDAN_RED%NOTFOUND; DBMS_OUTPUT.PUT_LINE(CDISK_RED.NASLOV_CDISKA); end loop; end; begin open CD_KURSOR for select * from CDISKOVI where CDISK_ID < 1000; OBRADI_REDOVE (CD_KURSOR); -- daje cd_cursor proceduri na obradu close CD_KURSOR; end;

Kod 215:Kursor i lokalna stored procedura

51

Oracle® Database Express Edition 2 Day Developer Guide, 10g Release 2 (10.2)

177

Prethodni primjer počeli smo deklaracijom novog tipa podatka pod nazivom CD_REFKURSOR_TIP. Ovaj tip podatka nastao je na osnovu čvrste veze tipa REF CURSOR i reda tabele CDISKOVI. Nakon toga, slijedi deklaracija varijable CD_KURSOR čiji je tip podatka upravo deklarisani CD_REFKURSOR_TIP. declare type CD_REFKURSOR_TIP is ref cursor return CDISKOVI%ROWTYPE; CD_KURSOR CD_REFKURSOR_TIP; ...

U Oracle-u, stored procedure možemo kreirati i kao lokalne procedure, bez njihovog snimanja u bazu podataka. Stored procedura OBRADI_REDOVE je kreirana na ovaj način. Ona će biti kompajlirana i postojaće samo u momentu izvršenja prethodno navedenog upita. Ova procedura uzima jedan ulazni (IN) parametar pod nazivom JEDAN_RED koji je tipa CD_REFKURSOR_TIP. Odabrani naziv ove varijable upućuje na suštinu upotrebe varijabli tipa kursor – njihova namjena je da drže jedan red neke tabele. ... procedure OBRADI_REDOVE (JEDAN_RED in CD_REFKURSOR_TIP) is ... U nastavku procedure, deklarisali smo i jednu (za proceduru) lokalnu varijablu tipa CDISKOVI%ROWTYPE pod nazivom CDISK_RED. Svrha ove variable je da iz kursora preuzme vrijednosti koje se nalaze u redu na koji on trenutno pokazuje. ... is CDISK_RED CDISKOVI%ROWTYPE; begin ...

U samom kodu procedure u BEGIN...END bloku, najprije dolazimo već mnogo puta opisanog ispisa u konzolu. Nakon toga slijedi još jedan programski blok – LOOP...END LOOP, koji čini programsku petlju. Programska petlja konstruisana na ovakav način će se izvršavati sve dok instrukcija EXIT koja se nalazi unutar ove petlje ne prekine njeno izvršavanje. ... loop ... Exit When JEDAN_RED%NOTFOUND; ... end loop; ...

Zadatak FETCH...INTO iskaza je da iz kursor varijable JEDAN_RED preuzme vrijednost reda podređene tabele i prebaci ga u varijablu CDISK_RED, jer kursori imaju ograničene mogućnosti prikazivanja rezultata. ... fetch JEDAN_RED into CDISK_RED;

... Linija EXIT WHEN zadužena je za prekidanje programske petlje kada kursor varijabla JEDAN_RED dobije vrijednost NOTFOUND (nije pronađeno), što indicira da je kursor završio sa obilaskom skupa rekorda. Ako se u kursoru nalazi validna vrijednost reda podređene tabele, izvršenje petlje se nastavlja. ... exit when JEDAN_RED%NOTFOUND; ...

U slučaju da programska petlja nije završena prethodnom komandom, koristimo poznatu funkciju PUT_LINE paketa DBMS_OUTPUT da bi ipisali sadržaj kursora u konzoli.

178

Kako smo varijablu CDISK_RED deklarisali kao tip ROWTYPE nad tabelom CDISKOVI, možemo pristupiti pojedinim kolonama svakog reda i ispisati ih na ekran. ... DBMS_OUTPUT.PUT_LINE(CDISK_RED.NASLOV_CDISKA); end loop; end; ...

Pravo izvršenje programa počinje sa lokalno definisanim blokom BEGIN...END koji je prikazan na dnu procedure. Prvi iskaz u ovom bloku otvara kursor CD_KURSOR kao SELECT upit nad tabelom CDISKOVI. begin open CD_KURSOR for select * from CDISKOVI where CDISK_ID < 1000; ... end; Tako otvoreni kursor se, kao ulazni parametar proslijeđuje proceduri OBRADI_REDOVE, a nakon izlaska iz procedure, kursor se zatvara komandom CLOSE. ... OBRADI_REDOVE (CD_KURSOR); -- daje cd_cursor proceduri na obradu close CD_KURSOR; ... Zadatak opisane stored procedure OBRADI_REDOVE je da prolazi kroz petlju sve dok u kursoru CD_KURSOR koji je nastao SELECT iskazom ima podataka. Tokom prolaska kroz petlju, u proceduri se red iz kursora prebacuje u varijablu CDISK_RED i zatim ispisuje na ekran. Interesantno je da se i REF CURSOR varijable mogu deklarisati u okviru paketa, ali i da se pojedinačni rekordi (redovi) mogu deklarisati unutar njih. U slijedećem primjeru ćemo u okviru paketa deklarisati po jednu ovakvu varijablu i ranije kreiranu proceduru RAZLICITE_VARIJABLE.

create or replace package PRVI_PAKET as procedure ZDRAVO; procedure DANAS_JE; procedure RAZLICITE_VARIJABLE; PDV_STOPA number := 1.17; type TIPKURSOR is ref cursor; type TIPREKORD is record (NASLOV varchar2(60), ZALIHA number); end; Kod 216:Izmjena paketa PRVI_PAKET Ako koristimo kursore, Oracle-ove stored procedure mogu da vraćaju i podatke u tabelarnom obliku (recordset). Iskoristićemo tip kursora koji smo pod nazivom TIPKURSOR kreirali u paketu PRVI_PAKET i prikazati jednu ovakvu proceduru: create or replace procedure TABELARNO ( SKUP_REZULTATA out PRVI_PAKET.TIPKURSOR ) as begin open SKUP_REZULTATA for select NASLOV_CDISKA, ZALIHA from CDISKOVI; end TABELARNO; Kod 217:Procedura TABELARNO

179

Prethodno kreiranu proceduru TABELARNO ćemo u SQL Commands prozoru pozvati pomoću: declare TEST_KURSOR PRVI_PAKET.TIPKURSOR; TEST_REKORD PRVI_PAKET.TIPREKORD; begin TABELARNO(TEST_KURSOR); loop fetch TEST_KURSOR into TEST_REKORD; exit when TEST_KURSOR%NOTFOUND; dbms_output.put_line (TEST_REKORD.NASLOV || ' ' || TEST_REKORD.ZALIHA); end loop; close TEST_KURSOR; end; Kod 218:Poziv procedure TABELARNO Poziv procedure tabelarno nećemo posebno komentarisati. U prethodnim primjerima treba primjetiti da je TIPREKORD koji je deklarisan u paketu PRVI_PAKET sastavljen od kolona koje treba da vrati upit u stored proceduri select NASLOV_CDISKA, ZALIHA from CDISKOVI; TIPREKORD je deklarisan kao record sa kolonama (NASLOV varchar2(60), ZALIHA number); koje se po redu, broju i tipu slažu sa kolonama spomenutog upita. Oracle PL/SQL jezik omogućava nam i kreiranje funkcija. Osnovna razlika izneđu procedure i funkcije je u tome što funkcija uvijek vraća neku vrijednost, a nosilac te vrijednosti je samo ime funkcije. Pogledaćemo slijedeći primjer: declare IME varchar2(20) := 'boris'; function VELIKA_SLOVA ( S1 in varchar2) return varchar2 as S2 varchar2(45); -- lokalna varijabla begin S2 := upper(S1); return S2; -- vracamo vrijednost stringa S2 end VELIKA_SLOVA ; -- pocetak izvrsnog bloka begin -- pozovi funkciju DBMS_OUTPUT.PUT_LINE( VELIKA_SLOVA (IME)); end; Kod 219:Lokalna funkcija VELIKA_SLOVA Za uklanjanje procedure, funkcije ili paketa iz šeme baze podataka, koristi se iskaz DROP, sa slijedećom sintaksom: drop NAZIV_PROCEDURE; drop NAZIV_FUNKCIJE; drop NAZIV_PAKETA; Sintaksa 43: Sintaksa DROP za procedure, funkcije i pakete

180

3.10.5.3 Firebird stored procedure Stored procedura u Firebird SUBP-u predstavlja program koji je napisan u Firebirdovom PSQL-u (Procedural SQL) i koji se kompajlira (prevodi) pomoću njegovog vlastitog interpretera i kao izvršni kod čuva u metapodacima same baze podataka. Jednom kompajlirana procedura može se kasnije pozivati direktno iz aplikacije ili iz nekog drugog PSQL modula, pomoću EXECUTE PROCEDURE ili SELECT iskaza. Firebirdov jezik za kreiranje procedura i trigera uključuje SQL iskaze za manipulaciju podacima i ekstenzije poput •

IF...THEN...ELSE blokova,



DO,



FOR...SELECT...DO,



izuzetaka (exceptins),



upravljanja greškama,



upravljanja događajima.

52

Zbog toga, sintaksa za kreiranje sintaksa za kreiranje Firebirdove stored procedure nije jednostavna. U prilogu slijedi tek osnovna sintaksa: create procedure IME_PROCEDURE [(ARGUMENT tip_podatka [,ARGUMENT tip_podatka [...]])] [returns (ARGUMENT tip_podatka [,ARGUMENT tip_podatka [...]]) as [declare [variable] var tip_podatka; [...]]] begin ; end Sintaksa 44: Osnovna sintaksa STORED PROCEDURE Čak i osnovna sintaksa, koja prikazuje samo mali dio PSQL jezika, na prvi pogled djeluje komplikovano. Zbog toga ćemo proces kreiranja procedura proći u koracima, tokom kojih ćemo se u svakom narednom koraku upoznavati sa sve kompleksnijim i kompleksnijim mogućnostima. Za kreiranje bilo koje stored procedure, dovoljne su nam samo slijedeće ključne riječi – CREATE PROCEDURE, AS, BEGIN i END, kao u slijedećem primjeru: create procedure TEST_PROC_1 as begin end; Kod 220:Prva stored procedura Ključne riječi CREATE PROCEDURE nakon kojih slijedi naziv procedure služe za kreiranje procedure pod navedenim imenom. Ključna riječ AS označava početak tijela procedure, dok BEGIN i END služe da označe početa i kraj bloka izvornog koda koji pripada proceduri. Da bi pokrenuli navedenu proceduru iz nekog SQL editora, dovoljno je upisati 52

H.Borrie, The Firebird Book: A Reference for Database Developers, H.Borrie and IBPhoenix, 2004

181

execute procedure TEST_PROC_1; Kod 221:Pokretanje stored procedure Stored procedure se mijenjaju pomoću iskaza ALTER. Iskazi CREATE i ALTER se mogu povezati pomoću ključne riječi OR. U tom slučaju, iskaz create or alter NAZIV_PROCEDURE... Sintaksa 45: Dopunjena sintaksa stored procedure će kreirati novu proceduru ako ona već ne postoji, ili će izmjeniti postojeću. Međutim, prethodno kreirana procedura ne bi radila nikakav posao – njenim izvršenjem ne bi dobili nikakav rezultat. Da bi stored procedura mogla da prikazuje rezultate, moraćemo se upoznati sa njenim ulaznim i izlaznim argumentima, kao u slijedećem primjeru: create or alter procedure TEST_PROC_1 ( ULAZNI_ARG1 integer, ULAZNI_ARG2 varchar(10) ) returns ( IZLAZNI_ARG1 integer, IZLAZNI_ARG2 varchar(10) ) as begin end; Kod 222:Izmjenjena stored procedura Prva razlika koju možemo primjetiti u odnosu na inicijalno kreiranje procedure je ključna riječ ALTER. Njeno dejstvo je saglasno njenom značenju u engleskom jeziku – alter = izmjeni. Druga novina slijedi odmah nakon naziva stored procedure – nakon njenog imena slijede zagrade između kojih smo naveli dva ulazna argumenta tipa integer i varchar(10). Preko ulaznih argumenata proceduri predajemo vrijednosti kojima želimo da utičemo na njeno ponašanje. U slijedećoj liniji, nakon ključne riječi RETURNS naveli smo i dva izlazna argumenta tipa integer i varchar(10). Ključna riječ returns označava da će argumenti koji slijede nakon nje biti vraćeni kao izlaz iz procedure. Prethodno napisana procedura izvršava se pomoću slijedećeg iskaza: execute procedure TEST_PROC_1(1, 'abcd'); Kod 223:Pokretanje stored procedure sa argumentima Međutim, izvršavanjem ovakve procedure još ne bi dobili nikakav značajan izlaz – obje izlazne varijable bi imale vrijednost NULL, kao na slici:

182

Slika 47: Izlaz procedure TEST_PROC_1 u FlameRobinu Da bi dobili neki izlaz, proširićemo navedenu proceduru kako slijedi: create or alter procedure TEST_PROC_1( ULAZNI_ARG1 integer, ULAZNI_ARG2 varchar(10) ) returns ( IZLAZNI_ARG1 integer, IZLAZNI_ARG2 varchar(10) ) as begin IZLAZNI_ARG1 = ULAZNI_ARG1; IZLAZNI_ARG2 = ULAZNI_ARG2; suspend; end; Kod 224:Izmjenjena stored procedura U prethodnom primjeru, u bloku izvornog koda procedure izvršili smo dodjelu vrijednosti izlaznim argumentima, nakon čega slijedi ključna riječ SUSPEND. Ključna riječ SUSPEND je neobično važna. Njenim navođenjem u bilo kom dijelu stored procedure navodimo da želimo da procedura na izlazu izbaci jedan red sa do tog momenta izračunatim vrijednostima. Važnost ove ključne riječi vidljiva je i pri upotrebi drugog načina za pozivanje stored procedura, koji je dat slijedećim fragmentom koda: select * from TEST_PROC_1(1, 'abcd'); Kod 225:Pokretanje stored procedure pomoću SELECT iskaza Iskaz SELECT možemo koristiti za izvršenje stored procedura koje su selektabilne 53 (selectable). To su procedure u koje smo uključili ključnu riječ SUSPEND. Za pozivanje stored procedura koje su konstruisane bez ove ključne riječi, moramo koristiti iskaz EXECUTE PROCEDURE. Ovakve procedure, napisane bez ključne riječi SUSPEND, nazivaju se izvršne (executable). PRIMJEDBA: Ako ne bi koristili ključnu riječ SUSPEND, poziv takve procedure pomoću SELECT iskaza bi u različitim programima za administraciju 53

H.Borrie, The Firebird Book: A Reference for Database Developers, H.Borrie and IBPhoenix, 2004

183

Firebirdovih baza podataka dao različite rezultate. Npr. IBExpert neće prikazati nikakav izlaz iz prethodne procedure ako iz nje izbacimo ključnu riječ SUSPEND, dok će nam FlameRobin dati poruku da je došlo do greške. Ako bi u programu FlameRobin pomoću SELECT iskaza pokrenuli navedenu stored proceduru, na izlazu bi dobili par vrijednosti (1, 'abcd'), kao na slici:

Slika 48: Izlaz procedure TEST_PROC_1 pozvane SELECT iskazom u FlameRobinu Treba napomenuti da se procedure mogu pokretati interaktivno iz naprednijih programa za administraciju Firebirdovih baza podataka, poput IBExpetra ili EMS SQL Management Studija. Interaktivno pokretanje podrazumjeva da smo pritiskom na neko dugme izvršili SELECT iskaz nad procedurom.

Slika 49: Prozor za editovanje stored procedura programa IBExpert Iz prikazane slike vidljivo je da su navedene dvije izlazne vrijednosti prikazane u vidu tabele koja ima samo jedan red. Mehanizam stored procedura SUBP-a Firebird je kreiran na takav način da podatke vraća u vidu pojedinačnih redova tabela – čak i kada procedura treba da vrati samo jedan izlazni argument, taj argument će biti prikazan u vidu jednog reda tabele koja ima samo jednu kolonu. Ovu osobinu Firebirdovih stored procedura ćemo ilustrovati slijedećim primjerom: create or alter procedure TEST_PROC_1( ULAZNI_ARG1 integer, ULAZNI_ARG2 varchar(10) ) returns ( IZLAZNI_ARG1 integer,

184

IZLAZNI_ARG2 varchar(10) ) as begin IZLAZNI_ARG1 = ULAZNI_ARG1; IZLAZNI_ARG2 = ULAZNI_ARG2; suspend; IZLAZNI_ARG1 = ULAZNI_ARG1+100; IZLAZNI_ARG2 = ULAZNI_ARG2 || 'def'; suspend; end; Kod 226:Izmjenjena stored procedura Drugi, izmjenjeni dio koda uvećava vrijednost argumenta ULAZNI_ARG1 za 100 i dodjeljuje izračunatu vrijednost argumentu IZLAZNI_ARG1. Zatim slijedi linija: IZLAZNI_ARG2 = ULAZNI_ARG2 || 'def'; koja će, pomoću operatiora konkatencije (||) spojiti string koji se nalazi u argumentu ULAZNI_ARG2 i string 'def'. Pretpostavimo da ovakvu proceduru pokrenemo pomoću slijedećeg SELECT iskaza: select * from TEST_PROC_1(1, 'abcd'); Kod 227:Pokretanje stored procedure pomoću SELECT iskaza Izlaz ovakve procedure vidljiv je u programu FlameRobin:

Slika 50: Izlaz procedure TEST_PROC_1 pozvane SELECT iskazom u FlameRobinu Na izlazu iz procedure dobili smo skup redova, odnosno tabelu kod koje je vrijednost svakog reda određena položajem ključne riječi SUSPEND u izvornom kodu. Na ovaj način, stored procedura je vratila rowset - skup redova odnosno virtualnu tabelu, koju najprodnije preuzimamo pomoću SELECT iskaza. Činjenica da su Firebirdove stored procedure konstruisane na takav način da podatke vraćaju u tabelarnom obliku prirodno nas vodi ka PSQL iskazima za manipulaciju podacima. Zbog toga ćemo napisati novu stored proceduru pod nazivom TEST_PROC_2: create or alter procedure TEST_PROC_2 returns ( NAZIV char(60) )

185

as begin for select NAZIV_KOMPANIJE from IZDAVACI into :NAZIV do suspend; end; Kod 228:Stored procedura TEST_PROC_2 Prvih nekoliko linija u prikazanom primjeru su nam od ranije poznate. Pomoću ključnih riječi CREATE OR ALTER PROCEDURE kreirali smo stored proceduru pod nazivom TEST_PROC_2, koja treba da vrati argument NAZIV tipa char(60). U samom tijelu procedure nalazi se jedan SELECT iskaz koji je okružen ključnim riječima FOR i INTO ... DO. Kombinacija ključnih riječi for select...into...do kreira programsku petlju za obradu implicitnog kursora. Implicitni kursor u ovom slučaju prolazi kroz sve redove tabele IZDAVACI, uzima vrijednost kolone NAZIV_KOMPANIJE i izvršava iskaz koji se nalazi nakon ključne riječi do, koji u našem slučaju vraća jedan red virtualne tabele. Pokrenućemo navedenu proceduru pomoću slijedećeg select iskaza: select * from TEST_PROC_2; Kod 229:Pokretanje stored procedure pomoću SELECT iskaza U programu FlameRobin, rezultati bi bili prikazani na slijedeći način:

Slika 51: Izlaz procedure TEST_PROC_2 pozvane SELECT iskazom u FlameRobinu Izlazni argument procedure TEST_PROC_2 deklarisali smo kao char(60) jer je kolona NAZIV_KOMPANIJE u tabeli IZDAVACI definisana na isti način. Argumenti u koje se preuzimaju odgovarajuće kolone neke tabele moraju se slagati po redu, broju i tipu podataka sa navedenim kolonama tabele. Da bi ilustrovali ovo pravilo, namjerno ćemo proceduru napisati pogrešno: create or alter procedure TEST_PROC_2 returns ( NAZIV char(10) ) as

186

begin for select NAZIV_KOMPANIJE from IZDAVACI into :NAZIV do suspend; end; Kod 230:Izmjenjena stored procedura koja će proizvesti grešku Ako bi, kao u primjeru, pokušali da skratimo dužinu navedenog argumenta npr. na char(10), pri izvršenju ove procedure dobili bi slijedeću poruku o grešci: SQL Message: Arithmetic overflow or division by zero has ocurred. Engine Message: Arithmetic exception, numeric overflow or string truncation At procedure TEST_PROC_2, line: 9, col: 3 Kod 231:Prepoznatljiva poruka o grešci Navedena greška je rezultat činjenice da u varijablu NAZIV tipa char(10) nije moguće smjestiti npr. podatak 'United Artists' dužine 14 karaktera. U okviru izvornog koda stored procedure, dozvoljeno je koristiti ključne riječi BEGIN i END za odvajanje pojedinih blokova koda, na sličan način kao u programskim jezicima pascal ili basic. PSQL takođe posjeduje i iskaze za kontrolu roka programa IF...THEN...ELSE čija je sintraksa veoma slična njihovoj sintaksi u programskom jeziku pascal. Pogledaćemo primjer jedne stored procedure koji ilustruje navedene koncepte. create or alter procedure TEST_PROC_3 returns ( IME_UMJETNIKA varchar(60), MJESTO_RODJENJA varchar(60) ) as begin for select IME_UMJETNIKA, MJESTO_RODJENJA from CD_UMJETNICI into :IME_UMJETNIKA, :MJESTO_RODJENJA do begin If (MJESTO_RODJENJA is null) then MJESTO_RODJENJA = '-- Nepoznato/nije uneseno --'; suspend; end end; Kod 232:Stored procedura TEST_PROC_3 Procedura TEST_PROC_3 prikazana u prethodnom primjeru ima dva izlazna argumenta IME_UMJETNIKA, MJESTO_RODJENJA tipa char(60). Nakon što for...select iskazom iz tabele očita odgovarajuće vrijednosti i dodjeli ih u navedene argumente, slijedi blok koda begin...end koji je uokvirio if...then konstrukciju i ključnu riječ suspend. U okviru if...then konstrukcije testiramo da li je uneseno mjesto rođenja umjetnika, pa ako nije, postavljamo njegovu vrijednost na '-- Nepoznato/nije uneseno -', nakon čega ključna riječ suspend vraća rezultat u vidu jednog reda virtualne tabele. Dobijeni rezultati mogu se prikazati slijedećom tabelom: IME_UMJETNIKA

MJESTO_RODJENJA

187

Tina Turner -- Nepoznato/nije uneseno -Lou Reed New York Bijelo Dugme -- Nepoznato/nije uneseno -Toto -- Nepoznato/nije uneseno -Zdravko Colic -- Nepoznato/nije uneseno -Joe Cocker -- Nepoznato/nije uneseno -Tabela 203: Rezultat izvršenja stored procedure U prethodnom primjeru, unutrašnji begin...end blok u velikoj mjeri utiče na način izvršavanja for...do petlje. Ako bi izbacili ključne riječi begin i end, kao u slijedećemo primjeru, stored procedura bi vratila samo jedan red podataka virtualne tabele: create or alter procedure TEST_PROC_4 returns ( IME_UMJETNIKA varchar(60), MJESTO_RODJENJA varchar(60) ) as begin for select IME_UMJETNIKA, MJESTO_RODJENJA from CD_UMJETNICI into :IME_UMJETNIKA, :MJESTO_RODJENJA do If (MJESTO_RODJENJA is null) then MJESTO_RODJENJA = '-- Nepoznato/nije uneseno --'; suspend; end; Kod 233:Stored procedura TEST_PROC_3 IME_UMJETNIKA MJESTO_RODJENJA Joe Cocker -- Nepoznato/nije uneseno -Tabela 204: Rezultat izvršenja stored procedure Kako smo izbacili ključne riječi begin i end, u okviru for..do petlje će uvijek biti izvršeno testiranje i eventualna dodjela vrijednosti za svaki red tabele CD_UMJETNICI. Međutim, kako se ključna riječ suspend više ne nalazi u petlji, ona će biti izvršena samo jednom, kada tok izvršenja programa napusti petlju i tada će biti prikazan samo zadnji rezultat. U prethodnim primjerima upoznali smo se sa stored procedurama koje su koristile ulazne i izlazne argumente. Gotovo svi programski jezici danas imaju potprograme koje pozivamo po imenu i kojima možemo proslijediti odgovarajuće ulazne argumente (varijable) i koji izračunate vrijednosti vraćaju preko izlaznih argumenata (varijabli). Današnji programski jezici takođe poznaju i koncept lokalne varijable – varijable koja se deklariše i definiše u okviru samog potprograma i koja služi za privremeno držanje rezultata i međurezultata. Firebirdov PSQL takođe poznaje koncept lokalnih varijabli. Varijable se deklarišu i definišu korištenjem ključnih riječi DECLARE VARIJABLE koje se zadaju neposredno prije prvog pojavljivanja ključne riječi begin, navođenjem jedne varijable u jednom redu.

188

as declare varijable NAZIV char(10); /* deklaracija */ declare varijable BROJAC integer = 0; /* deklaracija i definicija*/ declare varijable COUNTER integer DEFAULT 1; begin ... Sintaksa 46: Primjer sintakse deklaracije i definicije lokalnih varijabli Prvu varijablu NAZIV smo deklarisali kao char(10). Ovakvu varijablu ćemo kasnije moći da koristimo u proceduri za dodjelu različitih privremenih tekstualnih podataka. Druge dvije varijable, BROJAC i COUNTER deklarišemo kao cjelobrojne podatke, ali ih istovremeno inicijalizujemo (definišemo njihovu vrijednost) na 0 i 1, respektivno. Dakle, deklaracijom neke varijable za nju obezbjeđujemo potreban memorijski prostor, ali joj još ne dodjeljujemo vrijednost. S druge strane, deklaracijom i definicijom neke varijable istovremeno joj obezbjeđujemo potreban memorijski prostor i dodjeljujemo joj neku vrijednost. Firebirdov PSQL poznaje i programske petlje tipa WHILE...DO, koje imaju sličnu ulogu kao istoimene konstrukcije u programskom jeziku Pascal (ili while u programskom jeziku C, ili while...end while u visual basicu). Sintaksa WHILE ... DO petlje je: while [(uslov)] do ... Sintaksa 47: Sintaksa WHILE ... DO petlje Slijedi primjer koji ilustruje dva navedena koncepta> PRIMJER 109: Korištenjem prikazanih koncepata (lokalne varijable i WHILE...DO petlja) napraviti stored proceduru koja izračunava faktorijel nekog broja: create procedure FAKTORIJEL ( I integer) returns ( REZ integer) as declare variable MEDJUREZ integer = 1; begin while (i > 0) do begin medjurez = medjurez * i; i = i - 1; end rez = medjurez; suspend; end Kod 234:Stored procedura FAKTORIJEL Pokretanjem navedene procedure sa argumentom 4 select * from FAKTORIJEL(4) Kod 235:Stored procedura FAKTORIJEL

189

Dobićemo rezultat 24, jer je faktorijel od broja 4 jednak 1*2*3*4 = 24. Za uklanjanje stored procedure iz šeme baze podataka koristi se iskaz DROP čija je sintaksa vrlo jednostavna: drop procedure NAZIV_PROCEDURE Sintaksa 48: Sintaksa DROP PROCEDURE iskaza

3.10.6 Trigeri (triggers) Većina relacionih DBMS je implementirala koncept trigera (eng trigger - okidač) mnogo prije nego što se ovaj koncept pojavio u SQL:1999 standardu. Trigeri su objekti koji pripadaju šemi baze podataka, na isti način na koji šemi pripadaju i stored procedure, pogledi ili tabele. Trigeri su specifična vrsta ECA (Event-Condition-Action) pravila. Događaj (Event) je operacija ažuriranja baze podataka, uslov (Condition) je proizvoljni SQL predikat a 54 akcija (Action) je sekvenca SQL naredbi. SQL:1999 standard definiše trigere koji su vezani za tačno jednu tabelu i koji se pozivaju svaki put: •

Kada se ubaci jedan ili više redova u tabelu za koju je defnisan triger (INSERT naredba),



Kada se promjeni jedan ili više redova u tabeli za koju je defnisan triger (UPDATE naredba),



Kada se obriše jedan ili više redova u tabeli za koju je defnisan triger (DELETE naredba).

3.10.6.1 Oracle trigeri Triger se može posmatrati i kao posebna vrsta stored procedure koja je, u Oracle Expressu, vezana za tabelu, pogled ili događaj. Triger može biti pozvan jednom, kada se desi neki specifičan događaj ili mnogo puta – po jednom za svaki red zahvaćen nekim INSERT, UPDATE ili DELETE iskazom. Jedan triger mogže biti izvršen prije nekog od navedenih događaja, npr. da spriječi neželjene izmjene u bazi podataka ili nakon nekog događaja, da bi eventualno izvršio neke dodatne akcije. Izvršni dio trigera može sadržavati proceduralne iskaze ili iskaze jezika za manipulaciju podacima. Trigeri se kreiraju korištenjem CREATE TRIGGER iskaza. Trigeri mogu biti u vidu PL/SQL procedure ili C procedure. Ovakve procedure se mogu pridružiti tabeli, pogledu, šemi ili samoj bazi podataka. Trigeri se izvršavaju automatski kada se desi neki događaj. Tipovi trigera su •

DML trigeri definisani nad tabelama,



INSTEAD OF trigeri nad pogledima,



Sistemski trigeri nad objektima DATABASE ili SCHEMA.

Trigeri mogu biti kreirani tako da okidaju ako se desi neki od slijedećih događaja: • 54

DML

55

iskaz tipa INSERT, UPDATE ili DELETE,

B.Lazarević, Z.Marjanović, N.Aničić,S.Babarogić, Baze podataka, FON, Beograd 2008 DML – Data Manipulatin Language, Jezik za manipulaciju podacime, obično iskazi INSERT, UPDATE ili DELETE

55

190

56



DDL



Operacije baze podataka (LOGON, LOGOFF).

iskaz tipa CREATE, ALTER ili DROP,

Trigeri uvijek okidaju na osnovu nekog od navedenih događaja. Npr. ako je triger definisan kao: delete or insert or update on CDISKOVI... tada će bilo koji od slijedećih iskaza pokrenuti triger: delete from CDISKOVI... insert into CDISKOVI... update CDISKOVI... Trigeri mogu okidati u različitim momentima i na različite načine, što se u trigerima definiše slijedećim opcijama: •

Opcije BEFORE i AFTER okidaju triger prije ili poslije nekog događaja,



Opcija FOR EACH ROW okida triger za svaki red (a ne za cijelu tabelu),



Opcija WHEN okida triger na osnovu nekog uslova,



Opcija INSTEAD OF okida triger umjesto izvršenja nekog događaja.

Osnovna sintaksa za kreiranje trigera u Oracle-u je: create [or replace] trigger {before|after {of }} {insert|delete|update} on [referencing [new as ] [old as ]] [for each row [when ()]] Sintaksa 49: Pojednostavljena sintaksa CREATE TRIGGER iskaza - Oracle Da bi mogli da posmatramo ponašanje trigera, definisaćemo i jednu novu tabelu pod imenom ZALIHA_OBRISANA, koju ćemo koristiti da u nju upisujemo različite podatke: PRIMJER 110: Prije početka rada sa primjerima koji opisuju ponašanje trigera, najprije kreirati novu tabelu pod nazivom ZALIHA_OBRISANA: create table ZALIHA_OBRISANA ( KOMPAKT_DISK varchar(70), KATEGORIJA varchar(20), CIJENA number(5,2), KOMADA integer ); Kod 236:Kreiranje tabele ZALIHA_OBRISANA Pretpostavimo da je tabela ZALIHA_DISKOVA veoma bitna za funkcionisanje naše aplikacije i da zbog toga želimo da pratimo i evidentiramo izmjene koje korisnici naprave nad njom. Zbog toga ćemo kreirati niz trigera koji će u tabelu pod nazivom ZALIHA_OBRISANA upisivati promjene koje budemo smatrali da treba da evidentiramo. Prvi triger kojeg ćemo kreirati imaće zadatak da nakon izmjene podatka u koloni KATEGORIJA tabele ZALIHA_DISKOVA pokrene zapisivanje podataka. 56

DDL – Data Definition Language – Jezik za definisanje podataka, obično iskazi CREATE, ALTER I DROP

191

PRIMJER 111: Kreiraćemo triger koji će nakon ažuriranja (UPDATE) kolone KATEGORIJA u novu tabelu pod nazivom ZALIHA_OBRISANA upisati stare vrijednosti (vrijednosti prije izmjene) svih redova tabele ZALIHA_DISKOVA koji će biti zahvaćeni izmjenom: create or replace trigger PRATI_ZALIHA_DISKOVA after update of KATEGORIJA on ZALIHA_DISKOVA for each row begin insert into ZALIHA_OBRISANA values (:old.KOMPAKT_DISK, :old.KATEGORIJA, :old.CIJENA, :old.KOMADA); end; Kod 237:Kreiranje trigera PRATI_ZALIHA_DISKOVA Ključna riječ :OLD daje nam pristup starim vrijednostima u kolonama tabele ZALIHA_DISKOVA prije njihove izmjene. S druge strane, ključna riječ :NEW nam pruža uvid u nove vrijednosti koje se nalaze u kolonama tabele navedene u trigeru. Ključne riječi :OLD i :NEW se moraju pisati sa dvotačkom na početku. Pretpostavimo da se u tabeli ZALIHA_DISKOVA nalaze slijedeći podaci: KOMPAKT_DISK KATEGORIJA CIJENA KOMADA Negativ Vokal 16.99 13 Jednoj zeni Instrumental 20.00 42 The Slim Shady Vokal 14.99 22 Sheryl Crow Vokal 15.99 17 Ja ti priznajem Vokal 16.99 6 Ljubav nije za nas Vokal 14.99 8 Peter Gunn Instrumental 14.99 32 Tabela 205: Tabela ZALIHA_DISKOVA Recimo se pojavila potreba da izmjenimo sadržaj kolone kategorija – naziv kategorije „Instrumental“ je predugačak pa želimo da ga skratimo na „Instr.“. Recimo i da ćemo ažuriranje provesti jednim SQL iskazom, kako slijedi: update ZALIHA_DISKOVA set KATEGORIJA = 'Instr.' where KATEGORIJA = 'Instrumental' Kod 238:Upit za izmjenu kolone KATEGORIJA Nakon izmjene, u tabelama ZALIHA_DISKOVA i ZALIHA_OBRISANA će se pojaviti novi podaci: KOMPAKT_DISK KATEGORIJA CIJENA KOMADA Negativ Vokal 16.99 13 Jednoj zeni Instr. 20.00 42 The Slim Shady Vokal 14.99 22 Sheryl Crow Vokal 15.99 17 Ja ti priznajem Vokal 16.99 6 Ljubav nije za nas Vokal 14.99 8 Peter Gunn Instr. 14.99 32 Tabela 206: Izmjenjena tabela ZALIHA_DISKOVA KOMPAKT_DISK Jednoj zeni Peter Gunn

192

KATEGORIJA Instrumental Instrumental

CIJENA 20.00 14.99

KOMADA 42 32

Tabela 207: Tabela ZALIHA_OBRISANA Dakle, iako smo jednim iskazom izmjenili sadržaj svih kolona kod kojih je KATEGORIJA = 'Instrumental', triger je evidentirao sve redove koji su mijenjani, zahvaljujući ključnim riječima FOR EACH ROW. Prethodni triger je nakon ažuriranja tabele (after update of), odnosno njene kolone KOMPAKT_DISK (of KOMPAKT_DISK) i svakog reda u tabeli (for each row) u tabelu ZALIHA_OBRISANA upisao cijeli red koji je zahvaćen navedenim izmjenama. Prethodno opisani triger prati ažuriranje jedne kolone tabele ZALIHA_DISKOVA i pri tome evidentira sve redove koji su zahvaćeni promjenom. Međutim, u Oracle-u je moguće konstruisati i triger koji posmatra dešavanja na nivou tabele. Ako bi iz prethodnog trigera izbacili ključne riječi FOR EACH ROW, morali bi još malo izmjeniti definiciju trigera kao u slijedećem primjeru: PRIMJER 112: Kreiraćemo triger koji će nakon ažuriranja (UPDATE) kolone KATEGORIJA u novu tabelu pod nazivom ZALIHA_OBRISANA upisati da je došlo do izmjene navedene kolone: create or replace trigger PRATI_ZALIHA_DISKOVA_TABELA after update of KATEGORIJA on ZALIHA_DISKOVA begin insert into ZALIHA_OBRISANA values ('Izmjena na nivou tabele', NULL, NULL, NULL); end; Kod 239:Kreiranje trigera PRATI_ZALIHA_DISKOVA_TABELA Kod ovakvih trigera nije dozvoljeno koristiti ključne riječi:OLD i :NEW. Pretpostavimo da se u tabeli ZALIHA_DISKOVA nalaze slijedeći podaci: KOMPAKT_DISK KATEGORIJA CIJENA KOMADA Negativ Vokal 16.99 13 Jednoj zeni Instr. 20.00 42 The Slim Shady Vokal 14.99 22 Sheryl Crow Vokal 15.99 17 Ja ti priznajem Vokal 16.99 6 Ljubav nije za nas Vokal 14.99 8 Peter Gunn Instr. 14.99 32 Tabela 208: Tabela ZALIHA_DISKOVA Recimo se pojavila potreba da izmjenimo sadržaj kolone kategorija – naziv kategorije „Instr.“ je prekratak pa želimo da ga produžimo na „Instrum.“. Recimo i da ćemo ažuriranje ponovo provesti jednim SQL iskazom, kako slijedi: update ZALIHA_DISKOVA set KATEGORIJA = 'Instr.' where KATEGORIJA = 'Instrum.' Kod 240:Upit za izmjenu kolone KATEGORIJA Nakon izmjene, u tabelama ZALIHA_DISKOVA i ZALIHA_OBRISANA će se pojaviti novi podaci: KOMPAKT_DISK Negativ Jednoj zeni

KATEGORIJA Vokal Instrum.

CIJENA 16.99 20.00

KOMADA 13 42

193

The Slim Shady Vokal 14.99 Sheryl Crow Vokal 15.99 Ja ti priznajem Vokal 16.99 Ljubav nije za nas Vokal 14.99 Peter Gunn Instrum. 14.99 Tabela 209: Izmjenjena tabela ZALIHA_DISKOVA

22 17 6 8 32

KOMPAKT_DISK KATEGORIJA CIJENA KOMADA Jednoj zeni Instrumental 20.00 42 Peter Gunn Instrumental 14.99 32 Izmjena na nivou tabele NULL NULL NULL Jednoj zeni Instrumental 20.00 42 Peter Gunn Instrumental 14.99 32 Tabela 210: Tabela ZALIHA_OBRISANA Iz sadržaja tabele ZALIHA_OBRISANA, vidljivo je da su sada okinula oba trigera. Triger PRATI_ZALIHA_DISKOVA_TABELA koji je definisan na nivou tabele ili triger na nivou iskaza (bez ključnih riječi FOR EACH ROEW) je okinuo samo jednom, dok je triger PRATI_ZALIHA_DISKOVA koji je definisan na nivou reda okinuo dva puta – po jednom pri izmjeni svakog reda. Iako dozvoljava definisanje više trigera istog tipa nad jednom tabelom, Oracle XE 10g ne garantuje nikakav redoslijed njihovog izvršenja. U slučaju da nad istom tabelom kreiramo dva trigera tipa before upadate, ne postoji način na koji možemo da odredimo kojim redoslijedm će oni biti izvršeni. Da bi što jednostavnije pratili diskusiju koja slijedi, izbacićemo prethodno kreirane trigere iz šeme baze podataka. Izbacivanje trigera vrši se pomoći iskaza DROP koji ma vrlo jednostavnu sintaksu: drop trigger ; Sintaksa 50: Sintaksa DROP TRIGGER iskaza - Oracle PRIMJER 113: Slijedeća dva iskaza izbacuju ranije kreirane trigere iz baze podataka i brišu sve ranije zapisane podatke u tabeli ZALIHA_OBRISANA: drop trigger PRATI_ZALIHA_DISKOVA; drop trigger PRATI_ZALIHA_DISKOVA_TABELA; delete from ZALIHA_OBRISANA; Kod 241:Primje DROP TRIGER iskaza U prethodnoj diskusiji, spominjali smo da Oracle-ovi trigeri mogu da okidaju i ako se ostvari određeni uslov, kada se u trigeru navodi ključna riječ WHEN. Ponašanje trigera koji su definisani pomoću ključne riječi WHEN posmatraćemo na slijedećem primjeru. PRIMJER 114: Kreiraćemo triger koji će nakon ažuriranja (UPDATE) kolone KOMADA u novu tabelu pod nazivom ZALIHA_OBRISANA upisati da je došlo do ubacivanja novog podatka, ali samo ako je količina veoma velika – npr. veća od 10000. create or replace trigger PRATI_ZALIHA_DISKOVA_VECE_OD after update of KOMADA on ZALIHA_DISKOVA referencing new as NOVI for each row when (NOVI.KOMADA > 10000) begin insert into ZALIHA_OBRISANA values

194

('Neobicno: ' || :NOVI.KOMPAKT_DISK, :NOVI.KATEGORIJA, :NOVI.CIJENA, :NOVI.KOMADA); end; Kod 242:Kreiranje trigera PRATI_ZALIHA_DISKOVA_VECE_OD U prethodnom trigeru smo koristili ključne riječi referencing new as NOVI, koje navode da ćemo novoj vrijednosti reda u trigeru pristupati preko reference, odnosno preudonima NOVI. Navedeni triger treba da okine u slučaju ažuriranja kolone KOMADA, ali samo ako je nova vrijednost koju upisujemo u kolonu neobično velika, npr. veća od 10000, što upućuje na moguću grešku pri unosu podataka od strane korisnika. Pretpostavimo da se u tabeli ZALIHA_DISKOVA nalaze slijedeći podaci: KOMPAKT_DISK KATEGORIJA CIJENA KOMADA Negativ Vokal 16.99 13 Jednoj zeni Instrum. 20.00 42 The Slim Shady Vokal 14.99 22 Sheryl Crow Vokal 15.99 17 Ja ti priznajem Vokal 16.99 6 Ljubav nije za nas Vokal 14.99 8 Peter Gunn Instrum. 14.99 32 Tabela 211: Izmjenjena tabela ZALIHA_DISKOVA Ako npr. redu (Peter Gun, Instrum., 14.99, 32) izmjenimo kolonu KOMADA sa 32 na 100000 pomoću slijedećeg upita: update ZALIHA_DISKOVA set KOMADA = 100000 where KOMPAKT_DISK = 'Peter Gun' Kod 243:Izmjena podataka u tabeli ZALIHA_DISKOVA Nakon izmjene, u tabelama ZALIHA_DISKOVA i ZALIHA_OBRISANA će se pojaviti novi podaci: KOMPAKT_DISK KATEGORIJA CIJENA KOMADA Negativ Vokal 16.99 13 Jednoj zeni Instrum. 20.00 42 The Slim Shady Vokal 14.99 22 Sheryl Crow Vokal 15.99 17 Ja ti priznajem Vokal 16.99 6 Ljubav nije za nas Vokal 14.99 8 Peter Gunn Instrum. 14.99 100000 Tabela 212: Izmjenjena tabela ZALIHA_DISKOVA KOMPAKT_DISK KATEGORIJA CIJENA KOMADA Neobicno: Peter Gunn Instr. 14.99 100000 Tabela 213: Tabela ZALIHA_OBRISANA U slijedećem primjeru ćemo kreirati još dva trigera koji okidaju na DELETE i INSERT događaje. PRIMJER 115: Najprije ćemo kreirati triger koji će prije brisanja (DELETE) nekog reda tabele ZALIHA_DISKOVA u novu tabelu pod nazivom ZALIHA_OBRISANA upisati da je došlo do brisanja:

195

create or replace trigger PRATI_ZALIHA_DISKOVA_BRISANJE before delete on ZALIHA_DISKOVA referencing old as STARI for each row begin insert into ZALIHA_OBRISANA values ('Brisao: ' || :STARI.KOMPAKT_DISK, :STARI.KATEGORIJA, :STARI.CIJENA, :STARI.KOMADA); end; Kod 244:Kreiranje trigera PRATI_ZALIHA_DISKOVA_BRISANJE Primjetite da u prethodnom trigeru više ne navodimo naslov kolone , jer se operacija brisanja uvijek odnosi na cijeli red. Zatim ćemo kreirati triger koji će prije umetanja (INSERT) nekog reda tabele ZALIHA_DISKOVA u novu tabelu pod nazivom ZALIHA_OBRISANA upisati da je došlo do umetanja, ali ponovo samo ako se radi o neobično velikoj vrijednosti: create or replace trigger PRATI_ZALIHA_DISKOVA_UMETANJE before insert on ZALIHA_DISKOVA referencing new as NOVI for each row when (NOVI.KOMADA > 10000) begin insert into ZALIHA_OBRISANA values ('Neobican INS: ' || :NOVI.KOMPAKT_DISK, :NOVI.KATEGORIJA, :NOVI.CIJENA, :NOVI.KOMADA); end; Kod 245:Kreiranje trigera PRATI_ZALIHA_DISKOVA_UMETANJE Nakon brisanja reda (Peter Gun, Instrum., 14.99, 100000) i umetanja reda (TEST, Instrum., 14.99, 222333), u tabelama će se pojaviti slijedeći podaci: KOMPAKT_DISK KATEGORIJA CIJENA KOMADA Negativ Vokal 16.99 13 Jednoj zeni Instrum. 20.00 42 The Slim Shady Vokal 14.99 22 Sheryl Crow Vokal 15.99 17 Ja ti priznajem Vokal 16.99 6 Ljubav nije za nas Vokal 14.99 8 TEST Instrum. 14.99 222333 Tabela 214: Izmjenjena tabela ZALIHA_DISKOVA KOMPAKT_DISK KATEGORIJA CIJENA KOMADA Brisao: Peter Gunn Instr. 14.99 100000 Neobican INS: TEST Instr. 14.99 222333 Neobicno: Peter Gunn Instr. 14.99 100000 Tabela 215: Tabela ZALIHA_OBRISANA Zadnja opcija koju možemo koristiti kada kreiramo trigere je INSTEAD OF opcija, koja pokreće triger umjesto događaja koji je trebao biti izvršen. Ova opcija koristi se samo za izvršavanje DML iskaza koji ne bi mogli biti izvršeni na neki drugi način. Primjer za ovakvu operaciju je ažuriranje pogled (View). Kompleksnij pogledi se najčešće ne mogu

196

ažurirati, ali postavljanjem trigera nad nekim pogledom moguće je ažurirati neku od podređenih tabela, pomoću ključnih riječi INSTEAD OF.

3.10.6.2 Firebird trigeri Trigeri se koriste za provođenje pravila poslovnog integriteta. I u SUBP Firebird, oni u stvari predstavljaju stored procedure tako da se PSQL tehnika i sintaksa njihovog pisanja ne razlikuje mnogo od sintakse pisanja stored procedura. Međutim, trigeri ne mogu biti pozvani od strane aplikacije ili neke druge stored procedure. Oni ne mogu uzimati ulazne i vraćati izlazne argumente na način na koji to stored procedure mogu. Što se trigera tiče, Firebirdov PSQL posjeduje određena proširenja koja su primjenjiva samo na trigere. Svi trigeri u SUBP Firebird se izvršavaju na nivou redova tabele, svaki 57 put kada se slika reda izmjeni. SQL:1999 standard ne dozvoljava da trigeri budu povezani sa pogledima, ipak mnogi SUBP nude i ovu mogućnost. Svaki Firebirdov triger, zavisno od momenta izmjene podataka u redu, može da se izvršava u jednoj od dvije FAZE: before (prije izmjene) i after (nakon izmjene podataka). Slijedeća karakteristika svakog Firebirdovog trigera je EVENT – neki DML događaj (Data Manipulation Language) poput INSERT, UPDATE ili DELETE događaja. U firebirdu je moguće kombinovati navedene događaje prema slijedećoj tabeli: Vrsta trigera BEFORE INSERT AFTER INSERT BEFORE UPDATE AFTER UPDATE BEFORE DELETE AFTER DELETE BEFORE OR [OR ] AFTER OR [OR ]

Opis Okida prije ubacivanja novog reda. Dozvoljava da sve vrijednosti budu izmjenjene prije upisivanja u red. Okida nakon ubacivanja novog reda. Obično se koristi da na osnovu datih podataka u izmjenimo neku drugu tabelu. Okida prije izmjene reda. Dozvoljava da sve vrijednosti budu izmjenjene prije upisivanja u red. Okida nakon izmjene reda. Obično se koristi da na osnovu datih podataka u izmjenimo neku drugu tabelu. Okida prije brisanja reda. Ne prihvata izmjene bilo koje kolone u redu. Okida nakon brisanja reda. Ne prihvata izmjene bilo koje kolone u redu. Okida prije nego što se desi bilo koji od navedenih DML događaja (INSERT, UPDATE ili DELETE) Okida nakon nego što se desi bilo koji od navedenih DML događaja (INSERT, UPDATE ili DELETE)

Tabela 216: Moguće kombinacije Faza i događaja Trigeri se kreiraju pomoću CREATE TRIGGER iskaza, čija je pojednostavljenja sintaksa:

57

H.Borrie, The Firebird Book: A Reference for Database Developers, H.Borrie and IBPhoenix, 2004

197

create trigger NAZIV_TRIGERA for {tabela | view} {BEFORE | AFTER} {DELETE | INSERT | UPDATE} AS Sintaksa 51: Sintaksa CREATE TRIGGER iskaza Tijelo trigera mogli bi predstaviti slijedećom pojednostavljenom sintaksom: = declare variable NAZIV_VARIJABLE tip_podatka; [declare variable NAZIV_VARIJABLE tip_podatka;...] BEGIN [< SEKVENCA_SQL_NAREDBI >...] END Sintaksa 52: Sintaksa DROP PROCEDURE iskaza Istovremeno sa kreiranjem bilo kog trigera, automatski se kreiraju i INSERTING, UPDATING, DELETING, NEW i OLD kontekst varijable. INSERTING, UPDATING i DELETING kontekst varijable su tipa boolean i mogu se upotrebiti za iskaze uslovnog grananja kod trigera koji se sastoje od više događaja. Npr: if INSERTING then else if UPDATING then else if DELETING then Kod 246:Upotreba INSERTING, UPDATING i DELETING kontekst varijabli. Kontekst varijable OLD i NEW služe nam za pristup staroj i novoj vrijednosti neke kolona prije i njene izmjene i nakon njene izmjene. Npr. ako bi definisali BEFORE UPDATE triger koji bi okidao u slučaju nekog UPDATE iskaza koji mijenja kolonu KOMADA tabele ZALIHA_DISKOVA, tada bi kontekst varijabla old.NA_STANJU držala vrijednost kolone prije izmjene, dok bi kontekst varijabla new.NA_STANJU držala vrijednost kolone nakon izmjene njene vrijednosti. PRIMJEDBA: Svaki blok komandi u nekom Firebirdovom SQL skriptu mora da završi simbolom tačka-i-zarez (;). Međutim, i FB stored procedure i trigeri koriste isti simbol za završetak svake instrukcije. Međutim, moderni alati sakrivaju postojanje ovog dualizma od korisnika i na taj način omogućavaju ugodniji rad. Međutim, FlameRobin u verziji 0.9.2.1851 ima mali nedostatak, jer pri pisanju trigera zahtjeva korištenje ključnih riječi SET TERM kojima odvajamo način na koji Firebird završava neki blok u skriptu od načina na koji se završavaju instrukcije unutar trigera. Najčešće se problem dualizma rješava na slijedeći način: SET TERM ^ ; CREATE TRIGGER... BEGIN ... END ^ SET TERM ; ^ Navedeni fragment koda najprije daje Firebirdovoj mašineriji instrukciju da kao terminator skripta koristi simbol (^). Tokom trigera se sada normalno može kotistiti tačka-i-zarez (;). Zadnja linija ponovo daje Firebirdovoj mašineriji instrukciju da kao terminator skripta ponovo može da koristi simbol (;). Ovakav način pisanja trigera karakterističan je samo za open-source program FlameRobin ili neke starije programe za administraciju baza podataka. Svi koji

198

koriste neki od komercijalnih proizvoda ili njihove probne (trial) verzije vjerovatno nikada neće morati da pišu SET TERM iskaze. Ponašanje trigera ilustrovaćemo kroz nekoliko primjera. PRIMJER 116: Pretpostavimo da želimo da obezbjedimo mehanizam kojim ćemo moći da vratimo podatke koje korisnici naše aplikacije slučajno obrišu iz tabele ZALIHA_DISKOVA. Zbog toga ćemo najprije kreirati novu tabelu pod nazivom ZALIHA_OBRISANA u koju ćemo upisati svaki red koji korisnici obrišu iz tabele ZALIHA_DISKOVA. create table ZALIHA_OBRISANA ( KOMPAKT_DISK varchar(70), KATEGORIJA varchar(20), CIJENA numeric(5,2), KOMADA integer ); Kod 247:Kreiranje tabele ZALIHA_OBRISANA Nakon toga ćemo nad tabelom ZALIHA_DISKOVA definisati triger koji će prije stvarnog brisanja podataka iz tabele, navedene podatke upisati u novu tabelu ZALIHA_OBRISANA. create trigger ZALIHA_DISKOVA_BD0 for ZALIHA_DISKOVA before delete as begin insert into ZALIHA_OBRISANA (KOMPAKT_DISK, KATEGORIJA, CIJENA, KOMADA) values (old.KOMPAKT_DISK, old.KATEGORIJA, old.CIJENA, old.KOMADA); end Kod 248:Triger ZALIHA_DISKOVA_BD0 U navedenom primjeru kreirali smo triger pod nazivom ZALIHA_DISKOVA_BD0. Nakon ključne riječi FOR naveli smo da se triger odnosi na tabelu pod nazivom ZALIHA_DISKOVA i da se radi o trigeru tipa BEFORE DELETE (triger okida prije brisanja). U ostatku koda koristimo INSERT iskaz kojim u tabelu ZALIHA_OBRISANA pomoću kontekst varijable OLD ubacujemo vrijednosti obrisanog reda. Pretpostavimo da je tabela ZALIHA_OBRISANA prazna, dok sadržaj tabele ZALIHA_DISKOVA: KOMPAKT_DISK KATEGORIJA CIJENA KOMADA Negativ Vokal 16.99 13 Jednoj zeni Instrumental 20.00 42 The Slim Shady Vokal 14.99 22 Sheryl Crow Vokal 15.99 17 Ja ti priznajem Vokal 16.99 6 Ljubav nije za nas Vokal 14.99 8 Peter Gunn Instrumental 14.99 32 Tabela 217: Tabela ZALIHA_DISKOVA Nakon brisanja reda (Peter Gunn, Instrumental, 14.99, 32), pod dejstvom trigera ZALIHA_DISKOVA_BD0 u tabeli ZALIHA_OBRISANA će se pojaviti obrisani podaci:

199

KOMPAKT_DISK KATEGORIJA CIJENA KOMADA Peter Gunn Instrumental 14.99 32 Tabela 218: Tabela ZALIHA_OBRISANA U prethodnom primjeru, koristili smo kontekst varijablu OLD za pristup podacima prije njihovog brisanja. Treba napomenuti da u slučaje DELETE trigera, Firebird 2.1. ne dozvoljava korištenje kontekst varijable NEW. Ako se prisjetimo definicija ovih kontekstnih varijabli, to je sasvim logično – prije izmjene podataka, red još uvijek postoji i iz njega možemo uzeti vrijednosti kolona pomoću ključne riječi OLD. Međutim nakon izmjene (čita: brisanja) red više ne postoji, tako da korištenje ključne riječi NEW nema smisla. Kao i procedure, trigeri se mijenjaju pomoću iskaza ALTER. Iskazi CREATE i ALTER se mogu povezati pomoću ključne riječi OR. U tom slučaju, iskaz create or alter NAZIV_TRIGERA... Sintaksa 53: Dopunjena sintaksa trigera će kreirati novi triger ako on već ne postoji, ili će izmjeniti postojeći triger. Nad jednom tabelom moguće je definisati više trigera istog tipa (ista faza i događaj). Npr. nad tabelom CD_INVENTAR mogli bi definisati dva trigera tipa BEFORE UPDATE ili dva trigera tipa BEFORE DELETE. Da bi DBMS znao kojim redoslijedom da izvršava trigere istog tipa (ista faza i događaj) koji su definisani nad istom tabelom, možemo mu to naznačiti pomoću ključne riječi POSITION. Ključna riječ POSITION navodi kojim redoslijedom će se izvršavati trigeri istog tipa (ista faza i događaj) definisani nad istom tabelom. Nakon ključne riječi POSITION navodimo cijeli broj između 0 i 32767 kojim utvrđujemo sekvencu kojom će se trigeri izvršavati. Npr, ako u trigeru ZALIHA_DISKOVA_BD0 navedemo ključnu riječ POSITION 0, a u trigeru ZALIHA_DISKOVA_BD1 ključnu riječ POSITION 1, najprije će biti izvršen triger u kojem je navedena pozicija 0 pa tek onda triger u kom je navedena pozicija 1. Treba reći da cijeli brojevi koji se navode nakon ključne riječi POSITION ne moraju biti navedeni u sekvenci jedan iza drugog – dozvoljeno je npr. u prvom trigeru upotrebiti POSITION 3, a u drugom POSITION 5. U tom slučaju, najprije će biti izvršen triger numerisan manjim brojem (3) pa onda većim brojem (5). Ovakvo numerisanje trigera nije obavezno. SUBP Firebird će se snaći i ako sve trigere numerišemo pozicijom nula (0). U ovom slučaju, trigeri će biti izvršeni abecednim redoslijedom njihovih imena. Ključnu riječ POSITION ne moramo ni navoditi prilikom kreiranja trigera – tada će svim trigerima biti dodjeljena podrazumjevana (default) pozicija 0. Da bi ilustrovali redoslije izvršavanja trigera istog tipa (ista faza i događaj) nad istom tabelom obradićemo još jedan primjer: PRIMJER 117: Nad tabelom ZALIHA_DISKOVA ćemo definisati još jedan triger koji će prije stvarnog brisanja podataka iz tabele, navedene podatke upisati u novu tabelu ZALIHA_OBRISANA, pri čemu će biti izmjeniti podaci u koloni KOMADA. Ovaj triger ćemo numerisati pomoću ključne riječi POSITION 1. create trigger ZALIHA_DISKOVA_BD1 for ZALIHA_DISKOVA before delete position 1 as begin insert into ZALIHA_OBRISANA (KOMPAKT_DISK, KATEGORIJA, CIJENA, KOMADA) values

200

(old.KOMPAKT_DISK, old.KATEGORIJA, old.CIJENA, old.KOMADA+1000); end Kod 249:Triger ZALIHA_DISKOVA_BD1 U prethodnom primjeru kreirali smo triger pod nazivom ZALIHA_DISKOVA_BD1. Izvorni kod trigera je gotovo identičan prethodno kreiranom trigeru ZALIHA_DISKOVA_BD0. Osnovna razlika je u njegovom numerisanju – uvaj triger smo numerisali brojem 1 pomoću ključne riječi POSITION. Da bi na neki način mogli da razlikujemo dobijene rezultate, u ovom trigeru smo kolonu KOMADA tabele ZALIHA_OBRISANA uvećali za 1000. Ako bi sada obrisali jedan red tabele ZALIHA_DISKOVA, npr. (Ljubav nije za nas, Vokal, 14.99, 8) u tabeli ZALIHA_OBRISANA bi imali slijedeće podatke (novi podaci su označeni boldom): KOMPAKT_DISK KATEGORIJA CIJENA KOMADA Peter Gunn Instrumental 14.99 32 Ljubav nije za nas Vokal 14.99 8 Ljubav nije za nas Vokal 14.99 1008 Tabela 219: Tabela ZALIHA_OBRISANA Prvu liniju označenu boldom ubacio je prethodno definisani triger pod nazivom ZALIHA_DISKOVA_BD0, jer je on podrazumjevano dobio poziciju 0. Nakon toga, izvršen je triger pod imenom ZALIHA_DISKOVA_BD1 koji smo numerisali pozicijom 1 i u kom smo kolonu KOMADA uvećali za 1000. Navedeno numerisanje trigera određuje njihov redoslijed samo ako su istog tipa. Međutim, ako se radi o trigerima različitog tipa, redoslijed njihovog okidanja određuje faza izvršenja trigera, odnosno ključne riječi BEFORE i AFTER. Da bi ilustrovali različite faze okidanja trigera i upotrebu INSERTING, UPDATING i DELETING kontekst varijabli, pogledaćemo slijedeći primjer: PRIMJER 118: Nad tabelom ZALIHA_DISKOVA ćemo definisati još jedan triger. Ovaj triger ćemo definisati kao AFTER INSERT OR UPDATE OR DELETE. Triger će dakle okidati nakon ubacivanja, mijenjanja podataka ili brisanja podataka u tabeli ZALIHA_DISKOVA. create or alter trigger ZALIHA_DISKOVA_AA0 for ZALIHA_DISKOVA after insert or update or delete position 0 as begin if (INSERTING) then begin insert into ZALIHA_OBRISANA (KOMPAKT_DISK) values ('Ubacen: ' || new.KOMPAKT_DISK); end else if (UPDATING) then begin insert into ZALIHA_OBRISANA (KOMPAKT_DISK) values ('Mijenjan: ' || old.KOMPAKT_DISK); end

201

else if (UPDATING) then begin insert into ZALIHA_OBRISANA (KOMPAKT_DISK) values ('Brisan: ' || old.KOMPAKT_DISK); end end Kod 250:Triger ZALIHA_DISKOVA_AA0 U trigeru pod nazivom ZALIHA_DISKOVA_AA0 vidljiva su tri bloka uslovnog grananja toka programa. Kako je ovo nešto složeniji primjer, prokomentarisaćemo događaje koji aktiviraju dejstvo svakog od ovih blokova. U slučaju da u tabelu ubacujemo novi red npr. (EKV 86 Live, Vokal, 20.00, 100) u tabelu ZALIHA_DISKOVA, došlo bi do okidanja ovog trigera jer je definisan kao AFTER INSERT triger (after insert or...). Kako se radi o događaju tipa INSERT, kontekst varijabla INSERTING bi bila od strane DBMS-a postavljena na TRUE, i izvršio bi se prvi IF...THEN blok. U okviru prvog bloka, triger vrši sastavljanje stringova 'Ubacen: ' i new.KOMPAKT_DISK i upisuje navedeni sadržaj u tabelu ZALIHA_OBRISANA. Novi sadržaj tabele je: KOMPAKT_DISK KATEGORIJA CIJENA KOMADA Ljubav nije za nas Vokal 14.99 8 Ljubav nije za nas Vokal 14.99 1008 Peter Gunn Instrumental 14.99 32 Ubacen: EKV 86 Live NULL NULL NULL Tabela 220: Tabela ZALIHA_OBRISANA Ako bi sada izmjenili sadržaj prethodno ubačenog reda u tabeli ZALIHA_DISKOVA u npr. (Paket aranzman, Vokal, 20.00, 100) ponovo bi došlo do okidanja istog trigera jer je on definisan i kao AFTER UPDATE triger (after insert or update or...). U ovom slučaju, kontekst varijable INSERTING i DELETING su postavljene na FALSE od strane DBMS-a, dok je varijabla UPDATING postavljena na TRUE, zbog čega će se izvršiti drugi IF...THEN blok. U okviru drugog bloka, spaja se string 'Mijenjan: ' i stara vrijednost kolone KOMPAKT_DISK i upisuje u tabelu ZALIHA_OBRISANA: KOMPAKT_DISK KATEGORIJA CIJENA KOMADA Ljubav nije za nas Vokal 14.99 8 Ljubav nije za nas Vokal 14.99 1008 Peter Gunn Instrumental 14.99 32 Ubacen: EKV 86 Live NULL NULL NULL Mijenjan: EKV 86 Live NULL NULL NULL Tabela 221: Tabela ZALIHA_OBRISANA Slučaj brisanja nekog reda iz tabele ZALIHA_DISKOVA je najinteresantniji i najsloženiji. Nad ovom tabelom ranije smo već definisali dva trigera istog tipa čiji smo redoslijed izvršenja odredili ključnim riječima POSITION. Ova dva trigera su definisana ključnim riječima BEFORE DELETE, i izvršiće se prije brisanja reda iz tabele. Nakon brisanja reda iz tabele, okinuće i triger ZALIHA_DISKOVA_AA0, jer je on definisan kao AFTER DELETE (after insert or update or delete...). Kako ga je pokrenuo događaj brisanja reda, kontekst varijable INSERTING i UPDATING će od strane DBMS-a biti postavljene na FALSE, a varijabla DELETING će biti postavljena na TRUE, zbog čega će biti izvršen treći IF...THEN blok. U tabeli obrisana će se naći slijedeći podaci:

202

Prvo se izvršava

KOMPAKT_DISK KATEGORIJA Ljubav nije za nas Vokal Ljubav nije za nas Vokal Peter Gunn Instrumental Ubacen: EKV 86 Live NULL Mijenjan: EKV 86 Live NULL Paket aranzman Vokal Paket aranzman Vokal Brisan: Paket aranzman NULL Tabela 222: Tabela ZALIHA_OBRISANA

CIJENA 14.99 14.99 14.99 NULL NULL 20.00 20.00 NULL

ZALIHA_DISKOVA_BD0

KOMADA (BEFORE DELETE, POSITION80) 1008 Drugi se izvršava 32 ZALIHA_DISKOVA_BD1 (BEFORE NULL DELETE, POSITION NULL 1) 100 1100 Na kraju se izvršava NULL ZALIHA_DISKOVA_AA0 (AFTER DELETE)

U prethodnim primjerima napravili smo trigere tipa BEFORE DELETE i imenovali smo ih kao ZALIHA_DISKOVA_BD0 i ZALIHA_DISKOVA_BD1. Dobra praksa kodiranja navodi da bi pri davanju imena trigerima trebalo poštovati konvenciju prema kojoj se ime trigera formira od imena tabele nad kojom se definiše i po jednog slova koje označava fazu i događaj na koje se triger odnosi (BD = Before Delete). Predloženi sufiksi su BI, AI, BU, AU, BD, AD, BIU, AIU, BA, AA itd. Značenje prvih nekoliko dvoslovnih sufiksa je jednostavno: BI = Before Insert, AI = After Insert itd. Troslovni sufiksi odnose se na trigere koji okidaju na dva događaja, npr: BIU = Before Insert Or Update, AI = After Insert or Update itd. Trigeri koji obuhvataju sve događaje označeni su slovom A (od all - svi): BA = Before All (Insert Or Update Or Delete), AI = After All

203

3.10.7 Upravljanje greškama Izuzeci (exception) su specijalne konstrukcije koje postoje u brojnim programskom jezicima i koje mijenjaju tok izvršenja programa kada dođe do neke greške u njegovom izvršenju. Standardno ponašanje PSQL modula kada dođe do nekog izuzetka (exception) je da prekinu izvršenje, ponište sav prethodni rad do inicijalnog BEGIN iskaza, prenesu izvršenje programa na finalni END iskaz i vrate kontrolu klijentu, pri čemu će mu prikazati jednu ili više poruka da je došlo do greške. Ako je navedeni modul neki triger, tada će pojava izuzetka poništiti i sve prethodno izvršene trigere.

3.10.7.1 Firebird Exceptions Iskaz kojim se kreira izuzetak (exception) je veoma jednostavan: create exception NAZIV_IZUZETKA ; Sintaksa 54: Sintaksa iskaza za kreiranje izuzetka Naziv izuzetka može da bude standardan Firebirdov naziv dužine do 31 karaktera i mora da bude jedinstven naziv u odnosu na druge identifikatore u šemi baze podataka. Sintaksa za uklanjanje izuzetka iz baze podataka je: drop exception NAZIV_IZUZETKA; Sintaksa 55: Sintaksa iskaza za uklanjanje izuzetka Iskaz za izmjenu definicije izuzetka je takođe vrlo jednostavan: alter exception NAZIV_IZUZETKA ; Sintaksa 56: Sintaksa iskaza za izmjenu izuzetka PRIMJER 119: Da bi vidjeli ponašanje izuzetaka u praksi, kreiraćemo jednu novu stored proceduru. create procedure SREDNJA_VRIJEDNOST_ZALIHA ( ID_UM integer) returns ( SUMA double precision) as declare variable ZALIHA double precision; declare variable BROJAC integer = 0; begin SUMA = 0; for select ZALIHA from CDISKOVI where ID_UMJETNIKA > :ID_UM into :ZALIHA do begin if (ZALIHA is not NULL) then begin SUMA = SUMA + ZALIHA; BROJAC = BROJAC + 1; end end SUMA = SUMA / BROJAC; suspend; end

204

Kod 251:Procedura SREDNJA_VRIJEDNOST_ZALIHA Zadatak ove procedure je da selektuje one redove tabele CDISKOVI kod kojih je ID_UMJETNIKA veće od vrijednosti ulaznog argumenta. Pretp je sadržaj tabele CDISKOVI npr. CDISK_ID 1 2 3 4 5 6 7 8

NASLOV_CDISKA Tina Turns the Country On Acid Queen Unchain My Heart Tina Turns the Country On Zdravko Colic: Najveci hitovi Bijelo Dugme: Veliki hitovi Toto: Africa The Wall

ID_IZDAVACA 1 2 2 2

ZALIHA 5 6 8 2

ID_UMJETNIKA 1001 1001 1006 1001

5 4 3 3

1010 5 150 11

1005 1003 1004 NULL

Tabela 223: Tabela CDISKOVI Ako bi proceduru pozvali sa ulaznim argumentom npr. ID_UL = 1, procedura bi se ispravno izvršavala. Međutim, ako bi proceduru pozvali sa ulaznim argumentom ID_UL = 2000, došlo bi do greške pri izvršavanju. Arithmetic overflow or division by zero has ocurred. Engine Message: Arithmetic exception, numeric overflow or string truncation At procedure SREDNJA_VRIJEDNOST_ZALIHA, line: 22, col: 3 Kod 252:Error poruka Ako pogledamo navedenu poruku, vidimo da je uzrok greške lociran u liniji broj 22 stored procedure. ... suma = suma / brojac; ...

Kod 253:Izvor greške Greška u navedenom slučaju nastaje zbog dijeljenja sa nulom. Ako pogledamo kolonu ID_UMJETNIKA tabele CDISKOVI, primjetićemo da su sve vrijednosti u koloni manje od 1007, a u uslovu SELECT iskaza smo naveli da se u rezultatima upita moraju naći samo oni koji su veći od 2000. Kako ni jedan red tabele ne zadovoljava traženi uslov, varijabla BROJAC se neće uvećavati – njena vrijednost će ostati nula. Prethodno prikazana poruka je više programerski orjentisana – da bi korisnicima prikazali jasniju poruku, kreiraćemo izuzetak pod nazivom DIJELJENJE_S_NULOM: create exception DIJELJENJE_S_NULOM 'Doslo je do greske uslijed dijeljenja sa nulom!'; Kod 254:Izuzetak DIJELJENJE_S_NULOM Sada ćemo kod stored procedure izmjeniti na takav način da umjesto korisnicima nerazumljive poruke prikaže jasniju poruku o grešci: create procedure SREDNJA_VRIJEDNOST_ZALIHA ( ID_UM integer) returns ( SUMA double precision) as

205

declare variable ZALIHA double precision; declare variable BROJAC integer = 0; begin SUMA = 0; for select ZALIHA from CDISKOVI where ID_UMJETNIKA > :ID_UM into :ZALIHA do begin if (ZALIHA is not NULL) then begin SUMA = SUMA + ZALIHA; BROJAC = BROJAC + 1; end end if (BROJAC = 0) then exception DIJELJENJE_S_NULOM ; suma = suma / brojac; suspend; end Kod 255: Procedura SREDNJA_VRIJEDNOST_ZALIHA sa izuzetkom Nakon poziva ove procedure sa argumentom 2000, biće pokrenut naš izuzetak DIJELJENJE_S_NULOM koji korisnicima daje mnogo jasniju poruku. Izuzetak (exception) se u proceduri poziva pomoću ključne riječi EXCEPTION nakon koje slijedi naziv izuzetka i opcioni tekst. exception NAZIV_IZUZETKA ; Sintaksa 57: Sintaksa iskaza za poziv izuzetka Ako navedemo opcioni dio DRUGA_PORUKA, takva nova poruka će biti ispisana umjesto poruke koja je definisana pri kreiranju izuzetka. PSQL kod može da „uhvati“ greške koje se događaju u procedurama i trigerima i da ih proslijedi do rutina koje su zadužene za njihovu obradu. Ako se neki izuzetak obrađuje u našem kodu, naša je dužnost da zaobiđemo problem koji se pojavio – u tom slučaju nikakva poruka ne mora biti vraćena klijentu. U Firebird SUBP-u postoji veliki broj interno definisanih izuzetaka koji će biti izbačeni ako dođe do odgovarajuće greške. Svaka od ovih grešaka je označena pomoću dva koda – SQLCODE i GDSCODE. Slijedi isječak iz (mnogo duže) tabele sa kodovima grešaka: SQLCODE 101 100 ... S

GDSCODE 335544366 335544338 S S

SYMBOL segment from_no_match S

Tekst poruke Segment buffer length shorter than expected No match for first value expression S

Tabela 224: Tabela Firebird Error kodovi Ova dva koda su u proceduralnom SQL jeziku predstavljena pomoću dvije kontekstne varijable SQLCODE i GDSCODE

206

Međutim, standardni izuzeci koji su ugrađeni u SUBP ne moraju uvijek zadovoljiti sve naše potrebe. Ako želimo da definišemo vlastita pravila, možemo kreirati vlastite izuzertke i obrađivati ih okviru neke rutine za obradu. Zbog toga je za upravljanje greškama neobično važan i WHEN iskaz, koji ima formu: when do ; Sintaksa 58: Sintaksa iskaza za poziv izuzetka pomoću ključne riječi WHEN U prethodnoj sintaksi, može biti: NAZIV_IZUZETKA | GDS_KOD |SQL_KOD | ANY Sintaksa 59: Sintaksa iskaza za poziv izuzetka pomoću ključne riječi WHEN Dio sintakse koji je predstavljen pomoću može biti bilo koji pojedinačni SQL iskaz ili niz iskaza između ključnih riječi BEGIN i END. Upotrebu ključne riječi WHEN mogli bi slikovito prikazati na slijedeći način:

Slika 52: Obrada greške Na prethodnoj slici prikazana su dva primjera obrade greške. U prvom primjeru (slika lijevo) definisali smo vlastiti izuzetak koji generišemo ako npr. neka poslovna pravila nisu zadovoljena. Nakon generisanja izuzetka, kontrola toka programa se prenosi na liniju sa iskazom WHEN...DO gdje se testira da li smo naveli da ćemo obraditi izuzetak datog imena. Ako je naveden taj izuzetak (ili ključna riječ ANY) izvršava se rutina za obradu greške koja je omeđena BEGIN...END blokom. Druga slika (desno) prikazuje slučaj kada je došlo do bilo koje druge greške tokom izvršenja procedure ili trigera. Kontrola toka programa se ponovo prenosi na WHEN iskaz gdje se provjerava da li je navedeno da će baš ta greška koja ima odgovarajući error kod biti obrađena u rutini za obradu u okviru BEGIN...END bloka. Ako se u okviru WHEN iskaza navede ključna riječ ANY, tada će rutina za obradu grešaka obrađivati bilo koju grešku koja se potencijalno javi. PRIMJER 120: Da bi vidjeli ponašanje obrade izuzetaka u praksi, kreiraćemo još jedan izuzetak i jednu novu stored proceduru. create exception NEGATIVAN 'Negativan broj!'; /* kreirali smo novi izuzetak pod nazivom NEGATIVAN*/ create procedure TEST_IZUZETAKA ( ULAZ integer) returns ( IZLAZ double precision) as

207

begin if (ULAZ < 0) then exception NEGATIVAN; IZLAZ = 10 / ULAZ; /* -802 – aritmeticka greska, pokrece se i pri dijeljenju sa nulom*/ when sqlcode -802 do begin ULAZ = 0; IZLAZ = 0; suspend; exit; end when exception NEGATIVAN do begin IZLAZ = 10 / (-ULAZ); suspend; exit; end end Kod 256:Procedura TEST_IZUZETAKA Ako bi ovakvu proceduru pomoću SELECT iskaza pozvali sa negativnim ulaznim argumentom, npr. -1, prvi test u liniji if (ULAZ < 0) then... bi izbacio naš izuzetak NEGATIVAN. Za „hvatanje“ ovog izuzetka zadužena je linija when exception NEGATIVAN do koja bi tada ulaznu vrijednost pretvorila u pozitivan broj. Treba reći da ovo nije prava greška koja bi se javila u progtramu, već da se radi o vrijednosti koja nam iz bilo kojeg razloga ne odgovara kao rezultat izračunavanja. Ako bi proceduru pozvali sa nulom kao ulaznim argumentom, prilkom dijeljenja u liniji IZLAZ = 10 / ULAZ; bi došlo do aritmetičke greške zbog dijeljenja sa nulom i kontekst varijabla SQLCODE bi tada imala vrijednost -802. Za „hvatanje“ ove greške zadužena je linija when sqlcode -802 do i pripadajući BEGIN...END blok koda.

208

4

Upravljanje izvršenjem transakcija

Baza podataka je zajednički resurs koji istovremeno (konkurentno) koristi veći broj programa. Pri ovakvom korišćenju baze podataka može doći do mnogih neželjenih efekata kao što su, na primjer: •

otkaz sistema u toku izvršenja nekog programa koji može da ostavi bazu podataka u nekonzistentnom stanju,



neželjena interferencija dva ili više programa nad podacima za koje istovremeno konkurišu, može, takođe, da dovede bazu podataka u nekonzistentno stanje.

Osnovni cilj sistema za upravljanje bazama podataka je da omoguće efikasnu obradu transakcija. Transakcija je jedno izvršenje neke "logičke jedinice posla", jedno izvršenje neke logičke cjeline jednog programa ili jedno izvršenje cijelog programa. U jednom trenutku vremena nad bazom podataka se izvršava više transakcija. Često se i više izvršenja jednog istog programa (svako od njih predstavlja transakciju) obavlja konkurentno. Na primjer, izvršenje programa za podizanje i ulaganje novca na račun u nekoj banci, može se pokrenuti gotovo istovremeno sa više različitih šaltera. Probleme do kojih može da dovede otkaz sistema i nekontrolisano konkurentno izvršenje transakcija ilustrovaćemo sa nekoliko primjera. Otkaz sistema u toku obrade transakcije. Na slijedećoj slici prikazano je odvijanje transakcije za prenos novca (N KM) komitenta banke sa računa X na račun Y. Ako u trenutku t5 dođe do otkaza sistema transakcija se neće u potpunosti obaviti i doći će do narušavanja integriteta baze podataka - novac će se skinuti sa računa X, ali se neće prenijeti na račun Y.

Slika 53: Narušavanje integriteta baze zbog otkaza sistema Gubljenje rezultata ažuriranja. Na slijedećoj slici prikazano je izvršenje dvije transakcije u vremenu. Transakcija A podiže, a transakcija B ulaže novac na isti račun. Očigledno je da je ažuriranje koje Transakcija A obavlja u trenutku t5 izgubljeno, odnosno "prebrisano" ažuriranjem koje je izvršila transakcija B u trenutku t6.

209

Slika 54: Gubljenje rezultata ažuriranja Neko izvršenje skupa transakcija ćemo predstavljati samo preko sekvenci naredbi za čitanje i upisivanje elementa baze podataka. Na primjer izvršenje transakcija A i B sa 54. (gubljenje rezultata ažuriranja) se predstavlja na slijedeći način:

rA(X),rB(X),wA(X),wB(X) Vidljivo je da se transakcije u prikazanom slučaju identifikuju slovima – TA, TB,... Ako bi ih identifikovali rednim brojevima (odnosno nazivali T1, T2,...Ti, ...), u tom slučaju ri(X), i wi(X) znači čitanje ili upisivanje elementa X baze podataka koje vrši transakcija identifikovana sa i. Postoje i drugi problemi do kojih dolazi pri otkazu sistema i konkuretnoj obradi transakcija. Neki od njih će biti prikazani kasnije.

4.1

Osobine transakcija

Kao što je već rečeno, transakcija je jedno izvršenje neke "logičke jedinice posla" (Logical Unit of Work - LUW) korisnika baze podataka. Ta "logička jedinica posla" može da predstavlja neku logičku cjelinu jednog programa ili cjelokupan program. Transakcija mora da posjeduje slijedeći (ACID) skup osobina: Atomnost (Atomicity). Skup aktivnosti nad bazom podataka koje se izvršavaju po principu "sve ili ništa“ (ili su sve aktivnosti uspješno obavljene ili je baza podataka ostala nepromjenjena) je atomski skup aktivnosti. Očigledno je da transakcija, "logička jedinica posla", mora predstavljati atomski skup aktivnosti. Da bi atomnost transakcije imala smisla, SUBP mora da garantuje i atomnost svake aktivnosti (pojedinačne operacije) nad bazom podataka. To je posebno bitno za relacione SUBP gde su operandi u operacijama skupovi. Kada se vrši ažuriranje skupa i kada se ta atomska operacija prekine, neophodno je da budu poništene sve promjene koje je ona do tada izazvala. Konzistentnost (Consistency). Izvršenje transakcije treba da prevede bazu podataka iz jednog u drugo konzistentno stanje. Bez obzira na koji način neka transakcija završi – da li potvrdom (COMMIT) ili poništenjem (ROLL BACK), podaci u bazi podataka ne smiju ostati kontradiktorni. Izolacija (Isolation). Po pravilu, transakcija ne treba svoje promjene baze podataka da učini vidljivim drugim transakcijama prije nego što se ona okonča, odnosno promjene potvrde u bazi podataka. Međutim, da bi se povećao paralelizam obrade transakcija, u jednom SUBP dozvoljavaju se različiti nivoi izolovanosti transakcije, o čemu će se kasnije detaljnije govoriti.

210

Trajnost (Durability). Kada su u bazi podataka potvrđene promjene koje je izvršila neka transakcija, ove promjene se više ne mogu izgubiti. Navedene osobine se obično nazivaju "ACID osobine transakcije“, po prvim slovima njihovih engleskih naziva. Da bi se one obezbjedile, skup instrukcija koje predstavlja transakciju počinje, po pravilu, sa specijalnom instrukcijom BEGIN TRANSACTION, a završava se bilo sa instrukcijom COMMIT (potvrđuju se promjene u bazi podataka, ako su sve instrukcije transakcije uspješno izvršene) ili instrukcijom ROLLBACK (poništavaju se promjene u bazi, ako sve instrukcije nisu uspješno završene). Instrukcija ROLLBACK može da bude i implicitna, a inicira je SUBP kada, iz bilo kog razloga, dođe do nekog neplaniranog završetka transakcije. Jedan program može predstavljati kolekciju transakcija, mada u praksi, često, jedan program predstavlja jednu transakciju. U savremenim SUBP transakcije mogu biti "ugnježdene", odnosno dozvoljeno je da se jedna transakcija smjesti u drugu. U tom slučaju, naredba COMMIT ugnježdene transakcije stvarno ne potvrđuje promjene u bazi podataka dok se uspješno ne okonča i transakcija na "najvišem nivou ugnježdenja (spoljna transakcija). Ako se u bilo kojoj transakciji ugnježdene strukture pokrene instrukcija ROLLBACK, poništavaju se promjene koje su proizvele sve ostale transakcije strukture.

4.1.1

Potreba za izolacijom transakcija

U jednom SUBP, mnogo transakcija može da se izvršava istovremeno nad istim podacima. Ove transakcije moraju biti izolovane jedna od druge. Ako transakcije ne bi bile izolovane, javio bi se niz problema u radu sa bazom podataka. Jedan od problema bio bi i problem čitanja nepotvrđenih promjena. Ovaj problem se javlja kada se jednoj transakciji dozvoli da čita ili, još gore, da mijenja slog koji druga transakcija ažurira, a promjene koje je ona učinila još nisu potvrđene (naredbom COMMIT). Primjer ovog problema prikazan je na slijedećoj slici. Transakcija B je pročitala u trenutku t4 vrijednost X koju je u trenutku t3 transakcija A ažurirala, ali to ažuriranje još nije potvrđeno. Pošto je u trenutku t7 transakcija A poništila svoju promjenu podatka X, transakcija B je pročitala nekorektnu (nepostojeću) vrijednost (nepotvrđeno ili "prljavo" čitanje), a zatim i izvršila nekorektno ažuriranje.

Slika 55: Problem nepotvrđenih promjena

4.1.2

Implementacija COMMIT i ROLLBACK naredbi

Na kraju ovog dijela neophodno je objasniti i način na koji se implementiraju COMMIT i ROLLBACK, posebno. Da bi se mogle poništiti promjene koje je transakcija izvršila nad bazom podataka SUBP posjeduje i održava specijalnu memorijsku jedinicu (na nekoj

211

spoljnoj memoriji) koja se naziva log ili žurnal. Na ovoj memorijskoj jedinici, za svaku transakciju i svaki objekat baze koji je ona ažurirala čuvaju se vrijednosti prije (beforeimage) i vrijednosti poslije ažuriranja (after- image). Kada se izda instrukcija ROLLBACK sistem, koristeći vrijednosti prije za datu transakciju, ažurira odgovarajuće objekte baze podataka. Moguće je, takođe, da poslije izdavanja naredbe COMMIT, odnosno za vrijeme njenog izvršavanja, dođe do otkaza sistema. Tzv. write-ahead log protokol rješava ovaj problem. Naime, pri svakom ažuriranju baze podataka prvo se upiše zapis na log, sa vrijednostima prije i poslije za odgovarajući objekat i transakciju, a tek potom se ažurira sama baza. Ako u izvršenju naredbe COMMIT dođe do otkaza, sistem koristi vrijednosti poslije sa loga da bi doveo bazu u konzistentno stanje.

4.1.3

Konkurentna i serijska obrada transakcija

Kao što je rečeno, transakcija se u sistemima zasnovanim na bazi podataka ne obavlja samostalno, već konkurentno (uporedno sa drugim transakcijama u sistemu). Više transakcija mogu istovremeno zahtjevati iste resurse, isti rekord baze podataka. Nekontrolisana međusobna interferencija transakcija može da dovede bazu u nekonzistentno stanje. Konkurentno izvršavanje transakcija može dovesti do konflikta u slučajevima kada se transakcije prepliću, tj. pristupaju istom objektu, pri čemu bar jedna od njih vrši operaciju upisivanja podataka.

4.1.3.1 Problemi i anomalije pri konkurentnoj obradi transakcija Problemi i anomalije koji nastaju kada više korisnika istovremeno pristupa nekoj bazi podataka se nazivaju problemi konkurentne obrade transakcija. Oni uključuju: 1. Gubitak rezultata ažuriranja (Lost Updates), 2. prljavo čitanje (Dirty Read), 3. nekonzistentno čitanje (Nonrepeatable Read), 58

4. Fantomsko čitanje (Phantom Reads).

Očigledno je da primjer izvršenja skupa transakcija S1 (gubitak rezultata ažuriranja – Lost Updates) dovodi do konflikta. Gubitak rezultata ažuriranja nastaje kada dvije ili više transakcija selektuju isti red nesvjesne postojanja drugih. Nakon toga, transakcije vrše izmjene vrijednosti u istom redu iste tabele. U tom slučaju, zadnja izmjena reda poništava izmjene koje su napravile sve ranije transakcije i dolazi do gubitka rezultata ažuriranja. S1: r1(X) r2(X) w1(X) w2(X) T1 SELECT * FROM tabela WHERE id = 1;

T2 SELECT * FROM tabela WHERE id = 1;

UPDATE tabela SET polje = 21 WHERE id = 1; COMMIT; UPDATE tabela SET polje = 25 WHERE id = 1; COMMIT;

Tabela 225: Gubitak rezultata ažuriranja – Lost Updates

58

Concurrency Problems, MSDN online, dostupno na http://msdn.microsoft.com/

212

Isto važi i za izvršenje S2 (nekonzistentno čitanje ili Nonrepeatable Read). Prva transakcija može nekoliko puta selektovati isti red neke tabele. Ako istom redu tabele pristupa i transakcija T2 koja ga izmjeni i potvrdi svoje izmjene (COMMIT), transakcija T1 će pri svakom očitavanju dobiti različite rezultate. S2: r1(X) r2(X) w2(X) r1(X) T1 SELECT * FROM tabela WHERE id = 1;

T2 SELECT * FROM tabela WHERE id = 1; UPDATE tabela SET polje = 25 WHERE id = 1; COMMIT;

SELECT * FROM tabela WHERE id = 1; COMMIT;

Tabela 226: Nekonzistentno čitanje ili Nonrepeatable Read Prljavo čitanje (Dirty Read) je vrlo slično nekonzistentnom čitanju. Razlika je u tome što transakcija T2 nakon izmjene podataka (w2) može poništiti izmjene (ROLLBACK). S3: r1(X) r2(X) w2(X) r1(X) T1 SELECT * FROM tabela WHERE id = 1;

T2 UPDATE tabela SET polje = 25 WHERE id = 1;

SELECT * FROM tabela WHERE id = 1; ROLLBACK;

Tabela 227: Prljavo čitanje ili Dirty Read Fantomsko čitanje (Phantom Reads) nastaje kada transakcija T2 obriše ili umetne novi red koji pripdada rangu redova koje je transakcija T1 već očitala. Tada će T1 pri svakom očitavanju dobiti drugi skup vrijednosti: S4 : r1(X) d2(X) r1(X) S’4: r1(X) i2(X) r1(X) T1 SELECT * FROM tabela WHERE polje BETWEEN 10 AND 30;

T2

INSERT INTO tabela (polje) VALUES (25); COMMIT SELECT * FROM tabela WHERE polje BETWEEN 10 AND 30;

Tabela 228: Fantomsko čitanje ili Phantom Read

4.1.3.2 Konkurentna (uporedna) obrada transakcija Međusobno djelovanje transakcija može dovesti bazu podataka u nekonzistentno stanje, čak i kada svaka pojedina transakcija održi ispravnost stanja i kda pri tome nema otkaza sistema. Zbog toga, redoslijed kojim različite transakcije (T1, T2,...) izvršavaju akcije (r, w,..) mora na neki način biti regulisan u SUBP. Komponenta koja nadzire izvršenje navedenih akcija u SUBP-u naziva se Planer (Scheduler), a proces kojim se obezbjeđuje da transakcije koje se simultano izvršavaju očuvaju konzistentnost podataka se naziva kontrola konkurentnosti (Concurency Control). Komponenta koja upravlja cjelokupnim izvršenjem transakcija naziva se Menadžer transakcija (Transaction manager). Uloga Planera i menadžera transakcija vidljiva je sa slijedeće slike:

213

Slika 56: Planer Kada transakcije zahtjevaju zapisivanja ili očitavanja pojedinih elemenata baze podataka, ovi zahtjevi se proslijeđuju Planeru. U većini situacija, Planer izvršava čitanja i pisanja direktno, pri čemu najprije provjerava da li se navedeni element već nalazi u nekom baferu (kešu) baze podataka. Međutim, u pojedinim situacijama, nije sigurno izvršiti neki zahtjev odmah. Zbog toga, planer ponekad mora odložiti neki zahtjev na određeno vrijeme (npr. određeni broj milisekundi). U nekim rješenjima, Planer može potpuno otkazati izvršenje transakcije koja je postavila zahtjev. U nastavku ovoga poglavlja, biće prikazani neki načini koje Planer može da koristi da bi obezbjedio da se pri konkurentnom izvršavanju transakcija očuva konzistentnost stanja baze podataka. Apstraktan zahtjev kojim se ovo postiže naziva se serijabilnost

4.1.3.3 Serijska obrada transakcija Da bi počeli istraživanje kontrole konkurentnog izvršavanja transakcija, moramo istražiti uslove pod kojima će transakcije koje se izvršavaju istovremeno (konkurentno) očuvati bazu podataka u konzistentnom stanju. Osnovna pretpostavka ili princip korektnosti izvršavanja transakcija glasi: Svaka transakcija, ako se izvršava u izolaciji (bez drugih transakcija koje se izvršavaju istovremeno), će transformisati bazu podataka iz jednog 59 konzistentnog stanja u drugo. Međutim, u praksi se neka transakcija vrlo često izvršava uporedo sa drugim transakcijama, tako da se ovaj princip ne može direktno primjenjivati. Zbog toga je veoma važno pronaći plan koji garantovano proizvodi isti rezultat kao kada se transakcije izvršavaju jedna po jedna. Jedno izvršenje skupa transakcija predstavlja vremenski orjentisanu sekvencu (redoslijed) akcija koju poduzima jedna ili više transakcija. Serijsko izvršenje dvije transakcija je izvršenje u kome se transakcije ne prepliću, već se prvo potpuno izvrše sve akcije jedne, pa onda druge transakcije (A pa B, ili B pa A).

T1 R(A) A=A+100 W(A) R(B) B=B+100 59

T2

A 25

B 25

125

H.G.Molina, J.D.Ullman, J.Widom, Database Systems: The Complete Book, Prentice Hall

214

W(B)

125 R(A) A=A*2 W(A) R(B) B=B*2 W(B)

250

250

Tabela 229: Primjer serijskog izvršenja60 Rezultat serijskog izvršenja skupa transakcija u bilo kom redoslijedu ćemo smatrati korektnim. Koristeći ovaj stav, možemo da uvedemo koncept serijabilnosti ili linearnosti izvršenja skupa transakcija. Uporedno (konkurentno) izvršavanje skupa transakcija je serijabilno (linearno) 61 ako proizvodi isti rezultat kao i neko serijsko izvršenje istog skupa transakcija. T1

T2

R(A) A=A+100 W(A)

A 25

B 25

125 R(A) A=A*2 W(A)

R(B) B=B+100 W(B)

250

125 R(B) B=B*2 W(B)

250

Tabela 230: Primjer serijabilnog izvršenja62 Prethodna slika prikazuje plan izvršenja transakcija koji je serijabilan ali nije serijski. U ovom izvršenju, T2 djeluje na A nakon T1, ali prije nego što T1 izmjeni B. Međutim, efekat akcija koje su izvršile transakcije T1 i T2 prema ovom planu je isti kao i efekat akcija prema planu prikazanom za serijsko izvršenje. Zbog toga se usvaja da je skup uporednih transakcija izvršen korektno (bez konflikta), ako i samo ako je taj skup serijabilan. Ovakva definicija serijabilnosti uzima u obzir i detalje (semantiku) transakcija. Na primjer, ako bi u primjerima prikazanim na slikama 54. (gubljenje rezultata ažuriranja) i 55. (problem nepotvrđenih promjena) bilo N = 0, izvršenje transakcija A i B bi bilo serijabilno.

4.1.3.4 Protokoli za ostvarivanje serijabilnosti izvršenja skupa transakcija Različiti protokoli serijabilnosti izvršenja skupa transakcija zasnivaju, se na različitim načinima utvrđivanja serijabilnosti i različitim postupcima ostvarivanja serijabilnosti.

60

H.G.Molina, J.D.Ullman, J.Widom, Database Systems: The Complete Book, Prentice Hall B.Lazarević, Z.Marjanović, N.Aničić,S.Babarogić, Baze podataka, FON, Beograd 2008. 62 H.G.Molina, J.D.Ullman, J.Widom, Database Systems: The Complete Book, Prentice Hall 61

215

View - serijabilnost Za definisanje tzv. view-ekvivalnencije dva izvršenja skupa transakcija i viewserijabilnosti datog izvršenja skupa transakcija koriste se slijedeći pojmovi: •

Ako u nekom izvršenju skupa transakcija neko upisivanje wJ(X) prethodi nekom čitanju istog elementa (reda) baze rI(X) i nema nijedne druge operacije upisivanja wk(X) između njih, kaže se da "rI(X) čita iz wJ(X)", odnosno da između rI(X) i wJ(X) postoji "čita iz" odnos.



Operacija wJ(X) se zove "krajnje upisivanje", ako je to posljednje upisivanje elementa X u bazu.

"View" ekivivalnecija i "view" serijabilnost se definišu na slijedeći način: •

Dva izvršenja skupa transakcija su view-ekvivalentna (SI≈vSJ) ako posjeduju iste "čita iz" odnose i ista "krajnja upisivanja".



Izvršenje skupa transakcija je view-serijabilno ako je view-ekvivalentno sa 63 nekim serijskim izvršenjem.

Izvršenje S5 je view-serijabilno zato što je view-ekvivalentno serijskom izvršenju S6. S5: ... w0(X) r2(X) r1(X) w2(X) S6: ... w0(X) r1(X) r2(X) w2(X)

Analiza: S5 T0 W0: UPDATE tabela SET polje = 21 WHERE id = 1; COMMIT;

T1

S6 T2

R2: SELECT * FROM tabela WHERE polje = 1; R1: SELECT * FROM tabela WHERE polje = 1; COMMIT;

T0 W0: UPDATE tabela SET polje = 21 WHERE id = 1; COMMIT;

T1

T2

R1: SELECT * FROM tabela WHERE polje = 1; COMMIT; R2: SELECT * FROM tabela WHERE polje = 1;

W2: UPDATE tabela SET polje = 21 WHERE id = 1; COMMIT;

W2: UPDATE tabela SET polje = 21 WHERE id = 1; COMMIT;

Tabela 231: Analiza serijabilnosti a) Izvršenje S6 je očigledno serijabilno, jer se najprije izvršava T0 pa T1 pa onda T2.

63

B.Lazarević, Z.Marjanović, N.Aničić,S.Babarogić, Baze podataka, FON, Beograd 2008.

216

b) U transakciji S5 postoje slijedeći čita iz odnosi i krajnja upisivanja: •

postoji „čita iz“ odnos R2(X) čita iz W0(X),



postoji „čita iz“ odnos R1(X) čita iz W0(X),



a W2(X) je krajnje upisivanje;

c) U transakciji S6 postoje slijedeći čita iz odnosi i krajnja upisivanja: •

postoji „čita iz“ odnos R1(X) čita iz W0(X),



postoji „čita iz“ odnos R2(X) čita iz W0(X),



a W2(X) je krajnje upisivanje;

Kako pokazuju tačke b) i c) u navedenim izvršenjima S5 i S6 postoje isti "čita iz" odnosi i ista "krajnja upisivanja", tako da su ova dva izvršenja su View-Ekvivalena. Kako smo u tački a) utvrdili da je izvršenje S6 serijabilno, slijedi da je izvršenje S5 View-Serijabilno. Algoritam utvrđivanja view-ekvivalentnosti dva izvršenja skupa transakcija, koji treba da čita dva niza operacija čitanja i upisivanja i da utvrđuje da li je zadovoljen uslov, ima polinomijalnu složenost. Međutim, algoritam za utvrđivanje view-serijabilnosti zahtjeva nalaženje svih mogućih serijskih izvršenja skupa transakcija i zbog toga je neefikasan. Zbog toga se, mada najopštije definisana serijabilnost, view-serijabilnost praktično ne koristi.

4.1.3.5 Konflikt-serijabilnost Jedan od praktičnijih pristupa utvrđivanju serijabilnosti izvršenja skupa transakcija se ostvaruje preko definisanja koncepta konflikt-serijabilnosti. Pod konfliktom se ovdje podrazumjeva situacija u kojoj izmjena redoslijeda dvije operacije u izvršenjiu dovodi do izmjene efekata na bazu barem jedne od transakcija iz posmatranog izvršenja. Ako pretpostavimo da transakcije TI i TJ, pripadaju nekom izvršenju, pri čemu se radi o različitim transakcijama (ij), tada slijedeći parovi operacija neće biti u konfliktu ako im izmjenimo redoslijed izvršavanja: 1. rI(X), rJ(Y) nije konflikt čak i kada je X = Y, jer ni jedna ni druga operacija ne mijenjaju vrijednost bilo kog elementa baze podatka. 2. rI(X), wJ(Y) očigledno nije konflikt, pod pretpostavkom da je X ≠ Y. Pošto transakcije operišu nad različitim elementima baze podataka, ako Tj upiše Y prije nego što Ti očita X, X će ostati neizmjenjen. 3. wI(X), rJ(Y) nije konflikt, pod pretpostavkom da je X ≠ Y. Kao i pod 2, transakcije operišu nad različitim elementima baze podataka, pa izmjena njihovog redoslijeda u izvršenju nije konflikt. 4. wI(X),wJ(Y) nije konflikt, pod pretpostavkom da je X ≠ Y, jer transakcije ponovo 64 operišu nad različitim elementima. S druge strane, postoje tri situacije u kojima ne smijemo mijenjati redoslijed izvršavanja transakcija: a) Ako dvije akcije iste transakcije, ri(X) i wi(Y), izmjene mjesta doći će do konflikta. Redoslijed akcija pod jednom transakcijom je fiksan i SUBP ga ne smije mijenjati. 64

H.G.Molina, J.D.Ullman, J.Widom, Database Systems: The Complete Book, Prentice Hall

217

b) Izmjena redoslijeda dva zapisivanja istog elementa od strane različitih transakcija je takođe konflikt – wi(X) i wj(X) ne mogu mijenjati mjesta. Ako SUBP zamjeni mjesta, npr. wj(X) pa wi(X), kako god transakcija Tj izračunala X, u bazi će ostati zapisan rezultat koji upiše Ti. c) Očitavanje i upisivanje istog elementa baze podataka od strane različitih transakcija postaje konflikt, ako izmjenimo redoslijed akcija. To znači, ako imamo: a.

ri(X) i wj(X) logično ne smiju mijenjati mjesta. Zamjena mjesta ri(X) i wj(X) utiče na vrijednost X koju bi očitala transakcija Ti.

b. wi(X) i ri(X) takođe ne smiju mijenjati mjesta. Ako bi im zamjenili 65 mjesta, Ti bi potencijalno očitala staru (pogrešnu) vrijednost. Najopštije, dvije susjedne operacije različitih transakcija ne smiju mijenjati mjesta: 1. Ako se operacije obavljaju nad istim elementom baze podataka, 2. Ako je bar jedna od njih upisivanje. Postojanje ovog pravila omogućava Planeru da pokuša da nekonfliktnim izmjenama mjesta akcija (r, w) pokuša da pretvori trenutni redoslijed izvršenja u serijski redoslijed. Pri pravljenju redoslijeda akcija (r, w), Planer proizvoljan broj puta mijenja mjesta akcijama, sve dok se radi o nekonfliktnim izmjenama mjesta. Zbog toga kažemo da su dva izvršenja konflikt-ekvivalentna, ako se jedno u drugo mogu pretvoriti nekonfliktnim izmjenama susjednih akcija. Neki raspored ćemo nazvati 66 konflikt-serijabilnim ako je on konflikt-ekvivalentan nekom serijskom izvršenju. Dva izvršenja skupa transakcija su konflikt-ekvivalentna ako se jedan u drugi mogu transformisati nekonfliktinim izmjenama susednih operacija. Izvršenje skupa transakclja je konflikt-serijabilno ako je konflikt-ekvivalentno sa nekim 67 serijskim izvršenjem. Posmatrajmo redoslijed izvršenja iz prethodnog primjera serijabilnog izvršenja: r1(A), w1(A), r2(A), w2(A), r1(B), w1(B), r2(B), w2(B) U poglavlju „Serijska obrada transakcija”, iznijeli smo tvrdnju da je ovaj plan serijabilan. U nastavku slijedi niz nekonfliktnih zamjena mjesta kojima je prikazani redoslijed moguće pretvoriti u serijski (T1, T2) redoslijed: r1(A), w1(A), r2(A), w2(A), r1(B), w1(B), r2(B), w2(B) r1(A), w1(A), r2(A), r1(B), w2(A) , w1(B), r2(B), w2(B) r1(A), w1(A), r1(B), r2(A), w2(A) , w1(B), r2(B), w2(B) r1(A), w1(A), r1(B), r2(A), w1(B), w2(A) , r2(B), w2(B) r1(A), w1(A), r1(B), w1(B), r2(A), w2(A) , r2(B), w2(B) T1

65

T2

H.G.Molina, J.D.Ullman, J.Widom, Database Systems: The Complete Book, Prentice Hall H.G.Molina, J.D.Ullman, J.Widom, Database Systems: The Complete Book, Prentice Hall 67 B.Lazarević, Z.Marjanović, N.Aničić,S.Babarogić, Baze podataka, FON, Beograd 2008. 66

218

4.1.3.6 Graf prethođenja i konflikt serijabilnost Postoji relativno jednostavan postupak za utvrđivanje konflikt-serijabilnosti izvršenja skupa transakcija. Ako u nekoj transakciji postoji par operacija koji proizvodi konflikt, njihov redoslijed u svakom konflikt-ekvivalentnom serijskom izvršenju mora da ostane isti. Ako ovaj zahtjev ne dovodi do kontradikcije, moguće je naći konflikt-ekvivalentno serijsko izvršenje. U protivnom je to nemoguće. Za utvrđivanje da li dolazi do kontradikcije koristi se graf prethođenja transakcija. U ovom grafu transakcije jednog izvršenja su čvorovi, a usmjerene grane pokazuju prethođenje transakcija. Kaže se da transakcija TI prethodi transakciji TJ (piše se kao TI
View more...

Comments

Copyright ©2017 KUPDF Inc.
SUPPORT KUPDF