You are on page 1of 40

1 SQL Upitni jezik

1.1 Uvod

SQL jezik inovirala je tvrtka IBM, polazeći od osnovnih operacija relacijskih baza podataka,
kako ih je definirao Codd . SQL je neproceduralni jezik IV generacije. Pod time se
podrazumijeva, da nije potrebno definirati korake ( proceduru) izvođenja, nego se definira
«što želimo kao rezultat i način kako će rezulatat biti prikazan». Naredbe jezika dijele se u
dvije skupine:

DML Data Komande za traženje, umetanje, izmjene i brisanje


Manipulation podataka.
Language
DDL Data Komande za definiciju objekata ( tablica, indeksa, pgleda )
Definition relacijske baze podataka.
Language

1.2 Upiti u relacijskoj bazi podataka

1.2.1 Projekcija i restrikcija

Definirana je relacija ( tablica ) u relacijskoj bazi Studenti, s atributima ( kolonama ):

Ime

Prezime

DatumRodjenja

StudijID

PostaID

Izlistajmo sadržaj tablice i prikažimo ga na konzoli komandom:

SELECT * FROM Studenti;

Rezulta ovog upita je:

Ime Prezime DatumRodjenja StudijID PostaID


Ivo Ivic 22.06.1981 1 21000
Ana Matic 01.01.1980 1 22000
Tomislav Butorovic 21.01.1982 1 21000
Ana Marija Tomic 21.12.1981 1 20000
Marko Markovic 24.07.1981 2
Helena Topic 05.08.1979 20000
Hrvoje Antic 21.03.1981 1 23000
Ante Zelic 08.09.1981 1 53000

Dakle, prikazane su sve kolone i svi retci tablice, pri čemu je poredak redaka slučajan,
najčešće onim redom kako su retci upisivani u tablicu.

Često nam nisu potrebne sve kolone, pogotovu kod tablica s većim brojem kolona. Kolone
koje želimo prikazati pobrojimo poslije ključne riječi SELECT, pa komanda kojom ćemo
prikazati samo Ime i Prezime studenta izgleda:

SELECT Ime, Prezime FROM Studenti;

Rezultat izvođenja komande je:

Ime Prezime
Ivo Ivic
Ana Matic
Tomislav Butorovic
Ana Marija Tomic
Marko Markovic
Helena Topic
Hrvoje Antic
Ante Zelic

Često želimo prikaz samo nekih redaka tablice i to onih koji zadovoljavaju određeni uvjet.
Prikažimo Ime i Prezime studenata koji su upisani na studij «Matematike – Informatike».
Pregledom tablice Studiji:

SELECT * FROM Studiji;

StudijID Studij
1 Matematika - Informatika
2 Tehnicka kultura - Informatika
3 Matematika
4 Matematika - Fizika
5 Biologija - Kemija

nalazimo, da studij Matematike – Informatike ima oznaku StudijID=1. Tako će upit za prikaz
imena i prezimena studenata Matematieke – Informatike biti:

SELECT Ime, Prezime

FROM Studenti

WHERE StudijID=1

Ime Prezime
Ivo Ivic
Ana Matic
Tomislav Butorovic

Konačno, želimo studente Matematike – Informatike ali po abecednom redu prezimena:

SELECT Ime, Prezime

FROM Studenti

WHERE StudijID=1

ORDER BY Prezime

Ime Prezime
Tomislav Butorovic
Ivo Ivic
Ana Matic

Dakle, SQL – upitna komanda nad jednom tablicom ima opći oblik:

SELECT Kolona1, Kolona2, Kolona... | *

FROM Tablica

[ WHERE uvjet ]

[ ORDER BY Kolona2 [DESC], Kolona [DESC]... ]


pri čemu je redoslijed kolona proizvoljan i u SELECT klauzuli i u ORDER BY klauzuli.
Želimo li prikazati sve kolone tablice u poretku kako je tablica definirana, možemo
upotrijebiti simbol zvjezdice ( * ) koji uključuje sve kolone. Uvjet u WHERE klauzuli mora
za svaki redak rezultirati s jednom od dvije moguće vrijednosti: ISTINA ili LAŽ. Prikazani će
biti oni retci čija je vrijednost ISTINA. SELECT klauzula provodi relacijsku operaciju
projekcije, a WHERE provodi operaciju restrikcije. Kada restrikcija nije potrebna, tj. žele li se
prikazati svi reci, onda se WHERE klauzula ispušta ( uglate zagrade u gornjoj definiciji),
jednako kao i ORDER BY klauzula, kada poredak nije eksplicitno definiran.

Kako Sustav za upravljanje relacijskom bazom podataka ( RDBMS ) izvodi ovaj upit (tablica
nema definiranih indeksa ):

 Prevede upit u niz poziva primitivnih procedura

 Utvrdi optimalan slijed izvođenja

 Kako nema definiranih indeksa ( ili kada je tablica s malim brojem redaka) izvodi
potpuno skeniranje tablice, dakle kreće od prvog do posljednjeg retka

 Stvori privremenu radnu tablicu, s kolonama

- Ime varchar(50)
- Prezime varchar(50)

uzimajući definiciju kolona iz temeljne tablice Studenti

 Pročita prvi redak tablice Studenti i ako je vrijednost kolone StudijID=1, upiše vrijednosti
Ime i Prezime u radnu tablicu. U slučaju da StudijID nije 1, ide na slijedeći redak.

 Poreda retke u radnoj tablici po abecednom redu prezimena

 Ispiše rezultat u prozoru konzole

1.2.2 Prirodno spajanje

Nedostatak gornjih upita je taj, što brojčane oznake StudijID nisu dovoljno opisne, tj. iako
vidimo oznaku studija, ne znamo o kojem se studiju radi, naravno, ne želimo li stalno tražiti
naziv studija u tablici Studiji. Na sreću, SQL upitni jezik provodi i operaciju prirodnog
spajanja dviju ili više tablica:

SELECT Ime, Prezime, Studenti.StudijID, Studiji.*


FROM Studenti, Studiji

ORDER BY Prezime

Ime Prezime StudijID StudijID Studij


1 Hrvoje Antic 2 1 Matematika - Informatika
2 Hrvoje Antic 2 2 Tehnicka kultura - Informatika
3 Hrvoje Antic 2 3 Matematika
4 Hrvoje Antic 2 4 Matematika - Fizika
5 Hrvoje Antic 2 5 Biologija - Kemija
6 Tomislav Butorovic 1 1 Matematika - Informatika
7 Tomislav Butorovic 1 2 Tehnicka kultura - Informatika
8 Tomislav Butorovic 1 3 Matematika
---

38 Ante Zelic 3 3 Matematika


39 Ante Zelic 3 4 Matematika - Fizika
40 Ante Zelic 3 5 Biologija - Kemija

Rezultat ovog upita je relacija, prikazana kao Kartezijev produkt tablica Studenti i Studiji.
Dakle, svaki redak tablice Studenti je udružen sa svakim retkom tablice Studiji. Kako Studenti
sadrži 8 redaka, a Studiji 5, to rezultantana tablica sadrži 40 redaka. Uočavamo da neki retci
ne sadrže istinite podatke: student Hrvoje Antić je upisan na studij 2 – Tehnicka kultura –
Informatika ( lijeva kolona StudijID u tablici ), pa povezivanje sa studijima 1, 3, 4 i 5 ne odgovara
istini. Zato u pravilu, operaciju prirodnog spajanja ograničavamo na retke koji sadrže istinite podatke,
dakle:

SELECT Ime, Prezime, Studenti.StudijID, Studiji.*

FROM Studenti, Studiji

WHERE Studenti.StudijID=Studiji.StudijID

ORDER BY Prezime

Ime Prezime StudijID StudijID Studij


Hrvoje Antic 2 2 Tehnicka kultura - Informatika
Tomislav Butorovic 1 1 Matematika - Informatika
Ivo Ivic 1 1 Matematika - Informatika
Marko Markovic 2 2 Tehnicka kultura - Informatika
Ana Matic 1 1 Matematika - Informatika
Ana Marija Tomic 3 3 Matematika
Helena Topic 2 2 Tehnicka kultura - Informatika
Ante Zelic 3 3 Matematika

Rezultat upita je virtualna tablica, pod čime se misli da ne postoji njen fizički zapis na
mediju, npr. disku, nego se dinamički izgrađuje pri izvođenju upita.

Uobičajeni naziv za ovakav oblik spajanja tablica je «spajanje jednakosti» ( eng. «equi –
join»).

1.2.3 Vanjsko ( Outer Join ) spajanje

Izvedimo sličan upit, kojim ćemo prikazati ime, prezime, poštanski broj i naziv pošte
studenta:

Ime Prezime PostaID PostaID Posta


Hrvoje Antic 23000 23000 Zadar
Tomislav Butorovic 21000 21000 Split
Ivo Ivic 21000 21000 Split
Ana Matic 22000 22000 Sibenik
Helena Topic 20000 20000 Dubrovnik
Ante Zelic 53000 53000 Gospic

Nažalost, umjesto očekivanih 8 redaka, tablica ne sadrži retke:

Ana Marija Tomic

Marko Markovic

Razlog leži u nedefiniranim poštanskim brojevima ( prigodom prijave, studenti nisu prijavili
adresu, jer su bili u fazi preseljenja ). No, mi želimo prikazati sve studente, čak i ako nije
definiran poštanski broj. Naravno, ako pošta nije poznata, neće biti ispisana.

SELECT Ime, Prezime, Studenti.PostaID, Poste.*

FROM Studenti

LEFT OUTER JOIN Poste ON Studenti.PostaID=Poste.PostaID

ORDER BY Prezime
Ime Prezime PostaID PostaID Posta
Hrvoje Antic 23000 23000 Zadar
Tomislav Butorovic 21000 21000 Split
Ivo Ivic 21000 21000 Split
Marko Markovic NULL NULL NULL
Ana Matic 22000 22000 Sibenik
Ana Marija Tomic NULL NULL NULL
Helena Topic 20000 20000 Dubrovnik
Ante Zelic 53000 53000 Gospic
Engleski termin ovog oblik spajanja je LEFT OUTER JOIN, što možemo prevesti kao
«spajanje slijeva», a prikazuje sve retke u tablici s lijeve strane ključne riječi (Studenti). Svaki
redak tablice Studenti će pokušati spojiti s tablicom Poste preko identičnih vrijednosti kolona
PostaID i prikazati naziv pošte, kad god je spajanje uspješno, odnosno NULL vrijednost kad
spajanje nije moguće.

Vrijednost NULL tumačimo kao nedefinirana ili nepoznata vrijednost.

Kako Sustav za upravljanje relacijskom bazom podataka ( RDBMS ) izvodi ovaj upit (tablice
nemaju definirane indekse ):

 Prevede upit u niz poziva primitivnih procedura

 Utvrdi optimalan slijed izvođenja

 Kako nema definiranih indeksa ( ili kada je tablica s malim brojem redaka) izvodi
potpuno skeniranje tablice, dakle kreće od prvog do posljednjeg retka tablice Studenti

 Stvori privremenu radnu tablicu, s kolonama

- Ime varchar(50)
- Prezime varchar(50)
- PostaID int ( iz tablice Studenti)
- PostaID int ( iz tablice Poste)
- Posta varchar(50)

uzimajući definiciju kolona iz temeljnih tablica Studenti i Poste

 Pročita prvi redak tablice Studenti i upiše vrijednosti u radnu tablicu:

Ivo Ivic 21000


 Pretraži tablicu Poste, počev od prvog retka za vrijednost
Poste.PostaID=Studenti.PostaID, odnosno dok ne pronađe PostaID=21000

 Upiše u redak radne tablice PostaID ( 21000 ) i Posta ( Split )

 Ponovlja postupak čitanja svih redaka

 Poreda retke u radnoj tablici po abecednom redu prezimena

 Ispiše rezultat u prozoru konzole

Isto tako, moguće je spojiti tablicu s desna:

SELECT Studiji.*, Ime, Prezime

FROM Studenti

RIGHT OUTER JOIN Studiji ON Studenti.StudijID=Studiji.StudijID

ORDER BY Studiji.StudijID

StudijID Studij Ime Prezime


1 Matematika - Informatika Ivo Ivic
1 Matematika - Informatika Ana Matic
1 Matematika - Informatika Tomislav Butorovic
2 Tehnicka kultura - Informatika Marko Markovic
2 Tehnicka kultura - Informatika Helena Topic
2 Tehnicka kultura - Informatika Hrvoje Antic
3 Matematika Ana Marija Tomic
3 Matematika Ante Zelic
4 Matematika - Fizika NULL NULL
5 Biologija - Kemija NULL NULL

Ovim upitom prikazuju se sve moguće studijske grupe, te studenti onih studijskih grupa koje
imaju upisane studente. Studiske grupe bez studenata, isto tako su navedene, ali naravno bez
pridruženih studenata.
1.2.4 Unutrašnje ( Inner Join ) spajanje

U nekim prilikama, ipak želimo prikaz samo onih redaka koji se mogu spojiti s
odgovarajućim recima druge tablice. Recimo, kada trebamo uputiti pisma na adrese studenata,
studenti bez adrese trebaju biti ispušteni iz prikaza:

SELECT Ime, Prezime, Studenti.PostaID, Posta

FROM Studenti

INNER JOIN Poste ON Studenti.PostaID=Poste.PostaID

ORDER BY Prezime

Ime Prezime PostaID Posta


Hrvoje Antic 23000 Zadar
Tomislav Butorovic 21000 Split
Ivo Ivic 21000 Split
Ana Matic 22000 Sibenik
Helena Topic 20000 Dubrovnik
Ante Zelic 53000 Gospic

Isti rezulata se dobije i primjenom «Equi-join» spajanjem, no ipak «INNER JOIN» zapis
potpunog spajanja ima prednost, jer u komandi jasno razlikuje klauzulu restrikcije WHERE
od spajanja INNER JOIN.

Dakle, sintaksa potpune upitne komande koja izvršava projekciju, potpuno i nepotpuno
spajanje, restrikciju i određivanje poretka je:

SELECT Kolona1, Kolona2, ...

FROM Tablica1

[ INNER JOIN Tablica2 ON Kolona3=Kolona4 AND Kolona5=Kolona6 ]

[ LEFT OUTER JOIN Tablica3 ON Kolona7=Kolona8 AND ... ]

[ WHERE uvjet ]

[ ORDER BY Kolona1 [ ASC | DESC ], Kolona2 [ ASC | DESC ], ... ]


1.2.5 Funkcije u SQL Upitu

Često trebamo neke izračunate podatke, čija se vrijednost temelji na baznim podacima,
upisanim u tablici. Prikažimo ime i prezime studenata u jednoj koloni, spajanjem kolona ime i
prezime, te ukupni broj slova imena i prezimena ( razmak nije uključen). Retke je potrebno
poredati po dužini teksta, tako da student s najdužim imenom i prezimenom bude na vrhu
poretka:

SELECT Prezime + ' ' + Ime, LEN(Prezime + Ime)

FROM Studenti

ORDER BY LEN(Prezime + Ime) DESC

Ime Prezime Dužina Ime i Prezime


Butorovic Tomislav 17
Tomic Ana Marija 15
Markovic Marko 13
Topic Helena 11
Antic Hrvoje 11
Zelic Ante 9
Matic Ana 8
Ivic Ivo 7

Ključna riječ DESC ( DESCEDING ) označava inverzni poredak prikazane tablice.


Predefiniran je poredak od manje vrijednosti prema većoj ASC ( ASCEDING ) i nije ga
potrebno navoditi.

Neke često korištene funkcije su:

Sintaksa Opis
LEFT( Tekstualni izraz, n ) Izdvaja n pozicija s lijeva iz tekstualnog izraza
( obično tekstualna kolona tablice)
RIGHT( Tekstualni izraz, Izdvaja n pozicija s desna iz tekstualnog izraza
n) ( obično tekstualna kolona tablice)
SUBSTRING( Tekstualni Izdvaja D znakova iz tekstualnog izraza, počev od
izraz, S, D) pozicije S izraza
LEN( Tekstualni izraz ) Daje dužinu ( broj slova ) tekstualnog izraza

Primjeri:

a) Prikazati početno slovo imena ( inicijal ) i prezime u jednoj koloni.

SELECT LEFT(Ime, 1) + '. ' + Prezime

FROM Studenti

Inicijal Prezime
I. Ivic
A. Matic
T. Butorovic
A. Tomic
M. Markovic
H. Topic
H. Antic
A. Zelic

b) Prikazati dva posljednja slova prezimena studenta

SELECT RIGHT(Prezime, 2), Prezime

FROM Studenti

2 zadnja slova
prezimena Prezime
ic Ivic
ic Matic
ic Butorovic
ic Tomic
ic Markovic
ic Topic
ic Antic
ic Zelic
c) Prikazati 3 slova imena studenta, počev od 3. slova

SELECT SUBSTRING(Ime, 3, 3 ), Ime

FROM Studenti

3 slova počev od
3. Pozicije Ime
o Ivo
a Ana
mis Tomislav
aM Ana Marija
rko Marko
len Helena
voj Hrvoje
te Ante

d) Prikazati sve studente čije je ime=Ivo'

SELECT *

FROM Studenti

WHERE Ime='Ivo'

Ime Prezime DatumRodjenja StudijID PostaID


Ivo Ivic 22.06.1981 1 21000

e) Prikazati sve studente čije ime sadrži slovo i na bilo kojoj poziciji.

SELECT *

FROM Studenti

WHERE Ime LIKE '%i%'


Ime Prezime DatumRodjenja StudijID PostaID
Ivo Ivic 22.06.1981 1 21000
Tomislav Butorovic 21.01.1982 1 21000
Ana Marija Tomic 21.12.1981 3 NULL

f) Prikazati sve studente kojima naziv pošte sadrži slovi i na bilo kojoj poziciji.

SELECT Ime, Prezime, Studenti.PostaID, Posta

FROM Studenti

LEFT OUTER JOIN Poste ON Studenti.PostaID=Poste.PostaID

WHERE Posta LIKE '%i%'

Ime Prezime PostaID Posta


Ivo Ivic 21000 Split
Ana Matic 22000 Sibenik
Tomislav Butorovic 21000 Split
Helena Topic 20000 Dubrovnik
Ante Zelic 53000 Gospic

g) Prikazati sve studente kojima naziv pošte sadrži slovi i na bilo kojoj poziciji.

SELECT Ime, Prezime, Studenti.PostaID, Posta

FROM Studenti

LEFT OUTER JOIN Poste ON Studenti.PostaID=Poste.PostaID

WHERE Posta NOT LIKE '%i%'

Ime Prezime PostaID Posta


Hrvoje Antic 23000 Zadar

h) Prikazati ime, prezime i dužinu imena svim studentima, čije je ime duže od 5 slova.
Poredati po dužini imena.
SELECT Ime, Prezime, LEN(Ime)

FROM Studenti

WHERE LEN(Ime) > 5

ORDER BY LEN(Ime)

Duzina
Ime Prezime Imena
Helena Topic 6
Hrvoje Antic 6
Tomislav Butorovic 8
Ana Marija Tomic 10

g) Prikazati ime i prezime studenta u jednoj koloni, te svaku pojavu malog slova a, zamijeniti
velikim slovom A.

SELECT REPLACE(Ime + ' ' + Prezime, 'a', 'A')

FROM Studenti

Ime Prezime
Ivo Ivic
AnA MAtic
TomislAv Butorovic
AnA MArijA Tomic
MArko MArkovic
HelenA Topic
Hrvoje Antic
Ante Zelic

1.2.6 Grupiranje podataka i sumarna izračunavanja

a) Zanima li nas koliko imamo ukupno studenata u tablici Studenti, izvest ćemo upit:

SELECT count(*)

FROM Studenti
(No column name)
8

Dakle, count(*), pri čemu * da nas zanima broj redaka, bez obzira na definiranu vrijednost
kolona, će izbrojati ukupni broj redaka tablice.

Umetnemo li redak koji sadrži isključivo nedefinirane vrijednosti ( što je u suprotnosti s


pravilima relacijskih baza ), broj redaka bit će 9.

b) Ispišimo sada ukupni broj studenta, te broj studenata koji imaju definiranu adresu
(PostaID):

SELECT count(*) As BrojStudenata, count(PostaID) As ImaDefiniranuAdresu

FROM Studenti

BrojStudenata ImaDefiniranuPostu
8 6

c) Ispišimo broj studenata na svakoj studijskoj grupi. Grupe na kojima nema upisanih
studenata nije potrebno prikazati, te poredati prema broju studenata na grupi, počev od
najbrojnije grupe:

SELECT StudijID, count(*)

FROM Studenti

GROUP BY StudijID

ORDER BY count(*) DESC

StudijID count(*)
1 3
2 3
3 2
Kako programski sustav za upravljanje relacijskom bazom podataka( RDBMS) izvodi ovaj
upit ( Pretpostavka je da tablica nije indeksirana):

 RDBMS prevede definiranu komandu SQL upita u niz poziva primitivnih procedure

 Izračuna optimalan redoslijed izvođenja primitiva

 U bazi za privremene – radne tablice stvori tablicu čije su kolone:

StudijID smallint ( Uzima definiciju kolone iz polazne tablice )

Count1 int

 Krene od prvog retka tablice Studenti i upiše vrijednost StudijID ( 1 ) u radnu tablicu, te
brojačkoj koloni Count dodijeli vrijednost 1.

 Prelazi na slijedeći redak i ponovno pronalazi StudijID=1. Kako oznaka studija postoji u
radnoj tablici, uveča brojač pojava Count za 1, te on sada iznosi 2.

 Prelazi na slijedeći redak i pronalazi StudijID=2, te stvori novi redak s brojačem na


inicijalnoj vrijednosti 1.

 Ove korake ponavlja sve do posljednjeg redka tablice, te svaki put kada naiđe na
veijednost StudijID, koja ne postoji u tablici, stvori redak. Ako oznaka studija postoji u
radnoj tablici, uvečava joj brojač za 1.

 Sortira retke radne tablice od najveće do najmanje vrijednosti brojačke kolone.

d) Gore dobiveni rezultat je ispravan, ali nije razumljiv, jer oznake studija nisu deskriptivne.
Zato bismo radije čitali rezultat uz puni naziv studijske grupe, pa zato moramo spojiti tablicu
Studiji, gdje se opisi nalaze:

SELECT Studij, count(*) As BrojStudenata

FROM Studenti S

INNER JOIN Studiji ST ON S.StudijID=ST.StudijID

GROUP BY Studij

ORDER BY count(*) DESC

Studij BrojStudenata
Matematika - Informatika 3
Tehnicka kultura - Informatika 3
Matematika 2

e) Zahtijeva li se prikaz samo onih studijskih grupa, na kojima je opisano više od 2 studenta,
upit će biti:

SELECT Studij, count(*) As BrojStudenata

FROM Studenti S

INNER JOIN Studiji ST ON S.StudijID=ST.StudijID

GROUP BY Studij

HAVING count(*) > 2

ORDER BY count(*) DESC

Studij BrojStudenata
Matematika - Informatika 3
Tehnicka kultura - Informatika 3

Dakle, uvjet koji se odnosi na sumarne podatke definira se u klauzuli HAVING.

f) Želimo li pak, ispisati sve studijske grupe, te ukupan broj studenata upisan na svaku
studijsku grupu, uključujući i grupe na kojima nema upisanih studenata, upit će biti:

SELECT Studij, count(Ime)

FROM Studiji ST

LEFT OUTER JOIN Studenti S ON S.StudijID=ST.StudijID

GROUP BY Studij

ORDER BY Studij DESC

Studij BrojStudenata

Biologija - Kemija 0
Matematika 2
Matematika - Fizika 0
Matematika - Informatika 3
Tehnicka kultura - Informatika 3

Uočimo, da count(Ime) osigurava da BrojStudenata bude 0, kada na Studiju nema upisanih


studenata, dok bi count(*) dao ispravan broj u slučaju da je barem jedan student upisan na
Studijsku grupu, ali bi isto tako dao vrijednost jedan i kad na grupu nije upisan niti jedan
student. U pravilu ćemo uvijek kada se tablice spajaju s OUTER JOIN, upotrijebiti
count( Kolona ).

g) Ispis studenata i njihovih prosječnih ocjena, dobit ćemo upitom:

SELECT Ime, Prezime, AVG(Ocjena*1.0)

FROM Studenti S

LEFT OUTER JOIN StudentiOcjene SO ON S.StudentID=SO.StudentID

GROUP BY Ime, Prezime

ORDER BY Prezime

Ime Prezime (no column name)


Hrvoje Antic 2.7500
Tomislav Butorovic 4.0000
Ivo Ivic 4.0000
Marko Markovic 2.7500
Ana Matic 3.0000
Ana Marija Tomic 3.0000
Helena Topic 4.0000
Ante Zelic 3.7500

h) Isto tako, možemo ispisati sve studente, čija je prosječna ocjena veća ili jednaka 3.5:

SELECT Ime, Prezime, AVG(Ocjena*1.0) As ProsječnaOcjena

FROM Studenti S
LEFT OUTER JOIN StudentiOcjene SO ON S.StudentID=SO.StudentID

GROUP BY Ime, Prezime

HAVING AVG(Ocjena*1.0) >= 3.5

ORDER BY Prezime

Ime Prezime ProsječnaOcjena


Tomislav Butorovic 4.0000
Ivo Ivic 4.0000
Helena Topic 4.0000
Ante Zelic 3.7500

i) Konačno, ispišimo sve studente s adresom 21000 ( Split ) koji imaju prosječnu ocjenu 3.5
ili veću, te ukupan zbroj ocjena i prosječnu ocjenu svakog studenta, a rezltate poredajmo po
abecednom redu prezimena:

SELECT Ime, Prezime, PostaID, SUM(Ocjena) As ZbrojOcjena,

AVG(Ocjena*1.0) As ProsječnaOcjena

FROM Studenti S

LEFT OUTER JOIN StudentiOcjene SO ON S.StudentID=SO.StudentID

WHERE PostaID=21000

GROUP BY Ime, Prezime, PostaID

HAVING AVG(Ocjena*1.0) >= 3.5

ORDER BY Prezime

Ime Prezime PostaID 1.2.7 ZbrojOcjena ProsječnaOcjena


Tomislav Butorovic 21000 16 4.0000
Ivo Ivic 21000 16 4.0000
Uočimo da kod upita grupiranja, projekcija( klauzula SELECT ) sadrži kolone iz temeljnih
tablica, kao Ime, Prezime i PostaID, te funkcije grupiranja,count(), SUM, AVG. Operacija
grupiranja ( klauzula GROUP BY ) mora sadržavati sve kolone po kojima se grupiranje
obavlja, dakle, Ime, Prezime i PostaID. Isto tako, rezultat grupiranja može se sortirati samo
po kolonama koje su navedene SELECT klauzuli, jer one jedino i postoje u radnoj tablici,
koja se naknadno sortira.

1.2.8 Logički složeni uvjeti

a) Ispišimo sve studente Studijske čije ime ili prezime započinje slovom a :

SELECT Ime, Prezime

FROM Studenti

WHERE Ime LIKE 'a%' OR Prezime LIKE 'a%'

Ime Prezime
Ana Matic
Ana Marija Tomic
Hrvoje Antic
Ante Zelic

Uvjet će biti zadovoljen ako Ime ili prezime započinje slovom A, pa su ova dva uvjeta
povezana logičkim operatorom OR.

b) Ispišimo sve studente kojima Ime započinje slovom A a prezime slovom Z:

SELECT Ime, Prezime

FROM Studenti

WHERE Ime LIKE 'a%' AND Prezime LIKE 'z%'

Ime Prezime
Ante Zelic

Uvjet je zadovoljen samo u slučaju kada ime započinje slovom A, a prezime slovom Z, pa su
ova dva uvjeta vezana logičkim operatorom AND.

c) Prikažimo studente, čije ime NE započinje slovomA i prezime započinje slovom A:

SELECT Ime, Prezime

FROM Studenti

WHERE Ime NOT LIKE 'A%' AND Prezime LIKE 'A%'

Ime Prezime
Hrvoje Antic

Bilo koji od logičkih izraza može biti negiran, odnosno, rezultirat će istinom kada ne-negirani
uvjet daje laž.

d) Potrebno je izlistati sve studente, kojima ima ili prezime započinje slovom A, a da im
je PostaID=22000:

SELECT Ime, Prezime, PostaID

FROM Studenti

WHERE Ime LIKE 'A%' OR Prezime LIKE 'A%' AND PostaID=22000

Ime Prezime PostaID


Ana Matic 22000
Ana Marija Tomic NULL
Ante Zelic 53000

Gornji upit nije dao očekivani rezultat, jer vidimo da samo jedan od tri studenta prebiva na
PostaID=22000. Problem je uzrokovan logičkim povezivanjem elementarnih uvjeta. Naime,
kao što kod računskih operacija množenje ima veći prioritet od zbrajanja, tako logički
operator AND ima veći prioritet od OR operatora.

Zato gornji uvjet zadovoljava svaki redak, čim ime započinje slovo A.
Redoslijed razvijanja pojedinih elementarnih uvjeta možemo odrediti upotrebo zagrada, pa je
ispraljeni upit :

SELECT Ime, Prezime, PostaID

FROM Studenti

WHERE ( Ime LIKE 'A%' OR Prezime LIKE 'A%' ) AND PostaID=22000

Ime Prezime PostaID


Ana Matic 22000

Uočavamo da se najprije izračunava vrijednost logičkog izraza u zagradama.

1.2.9 Pobrojane vrijednosti

Ispišimo sve studente upisane na StudijID 1, 3 ili 5 :

SELECT Ime, Prezime, StudijID, PostaID

FROM Studenti

WHERE StudijID IN ( 1, 3, 5 )

Ime Prezime StudijID PostaID


Ivo Ivic 1 21000
Ana Matic 1 22000
Tomislav Butorovic 1 21000
Ana Marija Tomic 3 NULL
Ante Zelic 3 53000

Isti upit moguće je napisati ina ovaj način:

SELECT Ime, Prezime, StudijID, PostaID

FROM Studenti

WHERE StudijID=1 OR StudijID=3 OR StudijID=5


Da se izbjegne ponavljanje imena kolone StudijID, prvi oblik upita, kod kojeg se nabroji lista
traženih vrijednosti, je mnogo prikladniji i razumljiviji, te se redovito koristi. RDBMS izvodi
oba upita na isti način.

1.2.10 Ugniježđeni upiti

a) Prikažimo sve studente koji studiraju na istoj studijskog grupi kao student čije je prezime
Ivić.

Ovaj zadatak bismo mogli odraditi pomoću dva uipta:

Upit 1:

SELECT StudijID

FROM Studenti

WHERE Prezime='Ivic'

Zatim očitamo vrijednost StudijID i izvedemo

Upit 2:

SELECT Ime, Prezime, StudijID

FROM Studenti

WHERE StudijID=1

Oba upita moguće je definirati kao jedinstveni, ugniježđeni upit:

SELECT Ime, Prezime, StudijID

FROM Studenti

WHERE StudijID IN (SELECT StudijID

FROM Studenti

WHERE Prezime='Ivic')

Ime Prezime StudijID


Ivo Ivic 1
Ana Matic 1
Tomislav Butorovic 1
Dakle, umjesto da pobrojimo konstantne vrijednosti, možemo definirati upit koji vraća listu
pobrojanih vrijednosti. Najprije se izvodi upit u zagradama, dakle ugniježđeni, a zatim
vanjski. Može se ugnijezditi veći broj upita.

b ) Komplementarno gornjem upitu, možemo ispisati sve studente koji nisu upisani na isti
studij kao student Ivić:

SELECT Ime, Prezime, StudijID

FROM Studenti

WHERE StudijID NOT IN (SELECT StudijID

FROM Studenti

WHERE Prezime='Ivic')

Ime Prezime StudijID


Ana Marija Tomic 3
Marko Markovic 2
Helena Topic 2
Hrvoje Antic 2
Ante Zelic 3

Uočimo, upotrebu ključne riječi NOT, kojom se označava da uvjet zadovoljavaju svi studenti,
čija je vrijednost StudijID različita od 1, tj. nemaju StudijID isti kao student Ivić.

Često se ugnježđuju upiti grupiranja, kao u primjeru:

c) Ispišimo sve studente, koji studiraju na studijskim grupama, na kojima je upisano više od 2
studenta.

SELECT Ime, Prezime, StudijID

FROM Studenti

WHERE StudijID IN (SELECT StudijID

FROM Studenti

GROUP BY StudijID
HAVING count(*) > 2)

Ime Prezime StudijID


Ivo Ivic 1
Ana Matic 1
Tomislav Butorovic 1
Marko Markovic 2
Helena Topic 2
Hrvoje Antic 2

2.9 Jedinstvene vrijednosti redaka

a) Želimo znati početna slova ( inicijale ) imena studenata:

SELECT LEFT(Ime, 1)

FROM Studenti

ORDER BY 1

Inicijal
A
A
A
H
H
I
M
T

U slučaju velikog broja redaka u tablici, ovakav prikaz bi bio potpuno nepregledan, pa želimo
vidjeti samo jedinstvene pojave svakog slova, jer nas saznanje da imamo jednog ili više
studenata čije ime započinje s A zadovoljava:

SELECT DISTINCT LEFT(Ime, 1)


FROM Studenti

ORDER BY 1

Inicijal
A
H
I
M
T

Ključna riječ DISTINCT označava da se retci s istom vrijednošću svih kolona, prokažu samo
jednom.

Kako RDBMS izvodi ovaj upit:

 Stvori privremenu radnu tablicu s kolonama kako je navedeno u SELECT klauzuli, dakle
u našem primjeru, s jednom kolonom.

 Izvodi upit pretražujući tablicu, provjeravajući zadovoljenje uvjeta ako postoji, poziva
funkciju LEFT, koja vraća prvo slovo imena.

 Upisuje vrijednosti projeciranih kolona onih redaka koji zadovoljavaju uvjet u radnu
tablicu

 Sortira retke u radnoj tablici po svim kolonama

 Pretraži radnu tablicu ispisujući svaki put samo prvu pojavu retka, preskačući retke koji
imaju iste vrijednosti u svim kolonama, kao već ispisani redak.

2.10 Null vrijednost

Pri upisu retka u tablicu, vrijednosti nekih kolona mogu biti nepoznate, te ih moramo ostaviti
nedefiniranim. Naravno, neke kolone moraju imati obavezno unijete vrijednosti, pa se pri
kreiranju tablice zahtijeva obavezan unos vrijednosti. U našem primjeru tablice Studenti, ime,
prezime i studijska grupa moraju biti unijete, a PostaID, te datum rođenja mogu ostati
nedefinirane. Nedefinirana vrijednost naziva se Null vrijednost.

a) Ispišimo sve studente koji imaju PostaID = Null :


SELECT Ime, Prezime, StudijID, PostaID

FROM Studenti

WHERE PostaID IS Null

Ime Prezime StudijID PostaID


Ana Marija Tomic 3 NULL
Marko Markovic 2 NULL

Uočimo da se Null vrijednost testira ključnom rječju IS Null i da test = Null, gdje je znak
jednakosti zamijenio ključnu riječ IS, ne mora dati očekivani rezultat. Naime, o postavkama
baze podataka ovisi rezultat test = Null, no to prelazi okvire ovih skripta.

b) Prikažimo sve studente koji imaju definiranu vrijednost PostaID, dakle PostaID IS
NOT Null :

SELECT Ime, Prezime, StudijID, PostaID

FROM Studenti

WHERE PostaID IS NOT Null

Ime Prezime StudijID PostaID


Ivo Ivic 1 21000
Ana Matic 1 22000
Tomislav Butorovic 1 21000
Helena Topic 2 20000
Hrvoje Antic 2 23000
Ante Zelic 3 53000
1.3 SQL komande za definiciju objekata relacijske baze
podataka

U prethodnom poglavlju smo izvodili upite nad već definiranim tablicama u koje su
prethodno unijeti podaci. U ovom poglavlju ćemo definirati i izvoditi komande kojima se
stvaraju, mijenjaju i uništavaju objekti relacijske baze. Različiti sustavi za upravljanje
relacijskim bazama ( RDBMS ) pružaju mogućnost definiranja nekih specifičnih objekata, no
svi sigurno podržavaju mogućnost kreiranja, mijenjanja i uništavanja tablica, pogleda ( views)
i indeksa.

Isto tako, valja napomenuti da je mnogo prokladniji način stvaranja objekata korištenjem
grafičkog korisničkog sučelja. Lakše je klikom miša odabrati željenu akciju ili tip podatka,
nego pamtiti sintaksu komandi, te ćemo najvjerojatnije objekte baze kreirati koristeći grafički
interfejs i pokazivačku jedinicu ( miš ) na razvojnom računalu. U fazi implementacije baze na
ciljnom računalu ili većem broju ciljnih računala, bilo bi veoma neprikladno ponavljati niz
već odrađenih «klikova». Srećom, danas korišteni sustavi relacijskih baza mogu generirati
komande za stvaranje bazbih objekata. Mi moramo komande razumjeti i biti u stanju zadati ih
ručno.

U ovo poglavlju ćemo se upoznati samo s komandama u tekstualnom obliku.

1.3.1 Stvaranje, promjena i uništavanje tablice

Tablica sadrži kolone i retke. Kolone se moraju definirati prigodom stvaranja tablice, a retci
se stvaraju unosom vrijednosti u tablicu. Tablica predstavlja fizičku implementaciju entiteta, a
kolone atributa. Tablica je određena korisničkim imenom kreatora i imenom tablice. Isti
korisnik mora svakoj tablici odabrati jedinstveno ime. Različiti korisnici mogu koristiti ista
imena za svoje tablice. Kako jedan sustav za upravljanje relacijskim bazama može u isto
vrijeme upravljati s više baza na istom stroju, kažimo da je tablica određena preko tri
komponente:

Baza.Korisnik.Tablica

Jasno je, da u slučajevima kada se radna baza i korisnik podrazumijevaju, nije


potrebnonavoditi bazu i korisnika.
1.3.1.1 Stvaranje tablice Studenti

Entitet Studenti opisan je atributima:

Atributi Opis
Ime Slobodno unijeti tekst, maksimalne dužine 30 znakova,
obavezan unos
Prezime Slobodno unijeti tekst, maksimalne dužine 30 znakova,
obavezan unos
DatumRodjenja Datum, unos nije obavezan
StudijID Cio broj, s vrijednostima od 1 do 255, obavezan unos. Opis
brojčane oznake pogledati u tablici Studiji
PostaID Cio broj, s vrijednostima od 10000 ( Zagreb) do 99999, unos
nije obavezan. Opis brojčanih vrijednosti pogledati u tablici
Poste

Kod kreiranja tablice je veoma važno odabrati odgovarajući tip podatka svake kolone.

Na taj način onemogućavamo unos nesuvislih ili nemogućih podataka, barem u onoj mjeri
koliko je to moguće. Pojasnimo primjerom: ako bi kolona DatumRodjenja bila tekstualnog
tipa, onda bi bo moguć unos datuma 30.02.2002, no znamo da veljača ne može imati 30 dana.
Zato je važno da kolona DatumRodjenja bude datumskog tipa, pri čemu baza neće dopustiti
unos nemogućeg datuma. Dakle, pravilnim izborom tipa podatka kolone sprečavamo
nemoguće unose, no neispravni unosi još su uvijek moguću: npr. osobi rođenoj 2. siječnja
1980, još je uvijk moguće nepažnjom unijeti datum rođenja 1. veljače 1980.

Dakle, tablica Studenti imat će kolone:

Kolona Tip podatka Null vrijednost Opis tipa podatka


Ime varchar(30) NOT Null tekstualni,
maksimalna dužina
30 znakova. Unosi
«troše» onoliko
byte-ova koliko je
znakova unijeto, uz
dodatk 2 byte za
dužinu unijetog
podatka
Prezime varchar(30) NOT Null tekstualni,
maksimalna dužina
30 znakova
DatumRodjenja datetime Null Datumski podatak,
8 byte-ova ( ovisno
RDBMS)
StudijID tinyint NOT Null brojčani podataka
između 0 i 255, 1
byte
PostaID int Null brojčani podatak, 4
byte

Opisanu tablicu kreirajmo komandom:

CREATE TABLE Studenti (

Ime varchar(30) NOT Null,

Prezime varchar(30) NOT Null,

DatumRodjenja datetimeNull,

StudijID tinyint NOT Null

Tablicu Studenti, stvorenu gornjom komandom mogli smo kreirati i preko grafičkog
korisničkog sučelja.

Kreiranje tablice preko GUI


1.3.1.2 Uništavanje tablice

Tablicu koju više ne trebamo možemo uništiti, komandom:

DROP TABLE Studenti

Želimo li ponovno stvoriti tablicu s istim imenom, postojeću moramo najprije uništiti, jer nisu
moguće dvije tablice s istim imenom.

1.3.1.3 Izmjena strukture tablice

Pri kreiranju tablice Studenti, propustili smo kreirati kolonu PostaID. Vrlo je čest slučaj da se
tijekom eksploatacije baze podataka moraju dodati neke kolone, kao posljedica naknadog
proširenja zahtjeva. Uništavanje, radi ponovnog kreiranja tablice nije moguće jer su podaci
već upisani, a to bi značilo njihov gubitak. Dapače, tablicu će koristiti postojeća aplikacija, pa
ona ne smije biti nedostupna. Zato su nam na raspolaganju komande za dodavanje novih
kolona, te za promjenu postojećih. Iz praktičnih razloga, nastojimo nikada ne uništiti
postojeće kolone, jer neki segment aplikacije koji se poziva na stara imena kolona, neće raditi.
Kolone možemo dodavati bez bojazni po greške postojećih aplikacija, naravno ako se
pridržavamo i nekih drugih «praktičnih pravila» o kojima će biti riječi u slijedećem poglavlju.

Dodajmo kolonu PostaID int Null :

ALTER TABLE Studenti ADD PostaID int Null

Kolonu nije moguće dodadi uz zabranu Null vrijednosti ( NOT NULL ), ako nije definirana
predefinirana ( default) vrijednost.

Navedimo i komandu za uništavanje kolone, iako je dobro izbjegavati takvu praksu, iz ranije
opisanih razloga:

ALTER TABLE Studenti DROP COLUMN PostaID

Promijenimo tip podatka kolone StudijID iz tinyint u smallint ( 2 byte ).

ALTER TABLE Studenti2 ALTER COLUMN StudijID smallint

Pri izmjenama tipa podataka iz tipa većeg opseg vrijednosti u manji opseg, moramo
osigurati da već upisane vrijednosti ne prelaze novi, manji opseg.
Mijenjamo li maksimalno dopušteni broj znakova u kolonama varijabilne širine, može doći do
gubitka dijela unosa koji ne stane u novu, manju dimenziju. Neke RDBMS će prijaviti grešku:

Server: Msg 8152, Level 16, State 9, Line 1

String or binary data would be truncated.

The statement has been terminated.

1.3.2 Stvaranje i uništavanje pogleda – view-a

U praksi ćemo vrlo često trebati ispise iz tablice Studenti povezane s tablicama Studiji i Poste,
jer nas u pravilu zanima naziv studija i pošte. Da bi olakšali pretraživanje i izbjegli složenost
često korištenih upita, stvorit ćemo pogled ( view) Vstudenti, koji će povezivati potrebne
tablice. Isto tako, javlja se potreba da neke kolone ne budu dostupne stanovitoj grupi
korisnika, dok ih neka druga skupina može čitati. U našem primjeru, zadržat ćemo kolonu
DatumRodjenja skrivenom u pogledu Vstudenti.

CREATE VIEW VStudenti

AS

SELECT Ime, Prezime, Studij, S.PostaID, Posta

FROM Studenti S

INNER JOIN Studiji ST ON S.StudijID=ST.StudijID

LEFT OUTER JOIN Poste P ON S.PostaID=P.PostaID

Sada je ispis imena, prezimena, naziva studija, poštanskog broja i naziva pošte, krajnje
jednostavan:

SELECT *

FROM Vstudenti

Ime Prezime Studij PostaID Posta


Ivo Ivic Matematika - Informatika 21000 Split
Ana Matic Matematika - Informatika 22000 Sibenik
Tomislav Butorovic Matematika - Informatika 21000 Split
Ana Marija Tomic Matematika NULL NULL
Marko Markovic Tehnicka kultura - Informatika NULL NULL
Helena Topic Tehnicka kultura - Informatika 20000 Dubrovnik
Hrvoje Antic Tehnicka kultura - Informatika 23000 Zadar
Ante Zelic Matematika 53000 Gospic

RDBMS pogled tretira kao virtualnu tablicu, dakle ne čita je s medija ( diska ) nego dinamički
izgrađuje za vrijeme izvođenja upita, baš kao da smo zadali upit:

SELECT Ime, Prezime, Studij, S.PostaID, Posta

FROM Studenti S

INNER JOIN Studiji ST ON S.StudijID=ST.StudijID

LEFT OUTER JOIN Poste P ON S.PostaID=P.PostaID

To znači da možemo primijeniti restrikciju i sortiranje:

SELECT *

FROM VStudenti

WHERE Studij LIKE '%Informatika%'

ORDER BY Studij, Prezime

Ime Prezime Studij PostaID Posta


Tomislav Butorovic Matematika - Informatika 21000 Split
Ivo Ivic Matematika - Informatika 21000 Split
Ana Matic Matematika - Informatika 22000 Sibenik
Hrvoje Antic Tehnicka kultura - Informatika 23000 Zadar
Marko Markovic Tehnicka kultura - Informatika NULL NULL
Helena Topic Tehnicka kultura - Informatika 20000 Dubrovnik

Zgodno je ovdje napomenuti, da suvremni sustavi za upravljanje relacijskim bazama


omogućavaju stvaranje materijaliziranih pogleda. Naime, relacijska baza mora biti najmanje u
3. normalnoj formi, a to znači da svaka relacija ( tablica ) mora biti najmanje u toj ili višoj
normalnoj formi. Kod ispisa podataka često moramo spajati veći broj tablica, što značajno
ugrožava odzivna vremena, jer je operacija spajanja u pravilu vremenski zahtjevna, naročito
pri spajanju relacija s velikim brojem unosa (redaka). Stoga se u praksi, nakon normaliziranja
baze, često pristupa denormalizaciji. U tom postupku materijalizirani pogledi igraju značajnu
ulogu, jer oni predstavljaju fizičku kopiju spojenih tablica, pri čemu RDBMS sam održava
redudantne podatke. Korisnici baze vide relacije ( tablice) normalizirane, bez odstupanja od
teoretskih postavki, a materijalizirani pogledi osiguravaju iznimno brze upite.

1.3.2.1 Uništavanje pogleda

Pogled koji više ne trebamo, ili ga želimo ponovno kreirati, možemo uništiti komandom:

DROP VIEW Vstudenti

Jasno je da uništavanje pogleda nema nikakvog utjecaja na bazne tablice i podatke.

1.3.3 Stvaranje indeksa

Cilj ovog poglavlja su naredbe SQL jezika za stvaranje objekata relacijske baze, pa tako i
indeksa. Analizom upita, planiranjem indeksa, te ostalih potankosti vezanih uz indekse se
bavimo u posebnom poglavlju, a ovdje samo kratko pojasnimo pojam i značaj indeksa.

Pretpostavimo da želimo pronaći u telefonskom imeniku splitskog područja sve osobe čije je
prezime Ivić. Zadatak ćemo brzo obaviti, jer je imenik poredan po abecednom redu prezimena
pretplatnika. No, ako bi zadatak bio pronaći sve osobe koje žive u Teslinoj ulici, potrošili bi
mnogo više vremena. Jednostavno, morali bi krenuti od prvog pretplatnika, na prvoj stranici
imenika, te svakom pretplatniku pregledati ulicu. Postupak provjere ulice bi provodili jednom
po jednom, svim pretplatnicima, sve do posljednjeg na zadnjoj stranici imenika. Razlog za
potpuno čitanje imenika leži u činjenici da je imenik sortiran po abecedi prezimena, ali ne i po
ulicama. Dakle, imenik je indeksiran po prezimenu. Kada bi željeli isti imenik sortiran i po
ulicama, to bi radi uštede papira mogli napraviti na ovaj način: dodati stranice s abecednim
popisom ulica, te kod svake ulice nabrojati sve stranice i retke u kojima ćemo pronaći
pretplatnike s adresom u Teslinoj ulici. To bi vjerojatno značilo, da bi brzo pronašli Teslinu
ulicu i onda bismo za svakog pretplatnika morali pronaći stranicu, te ponovno za slijedećeg
pretplatnika skoknuti na stranicu indeksa ulica, pročitati na kojoj se stranici nalazi slijedeći
pretplatnik i tako redom. Dakle, indeksiranjem se značajno ubrzava pretraživanje.

Shvatimo naredbu za kreiranje indeksa kao sortiranje podataka u određenom poretku (slučaj
abecednog poretka po prezimenima), odnosno, kao dodavanje stranica s abecednim poretkom
ulica i pokazivačima stranica i redaka na kojima su pretplatnici date ulice.
Naravno, mi želimo indeksirati tablicu studenti, po prezimenu, kako bismo u tablici s mnogo
redaka brzo pronašli traženo prezime ( naredbom je stvoren indeks koji odgovara indeksiranju
ulica u gornjem tekstu).

CREATE INDEX Prezime_X ON Studenti(Prezime)

Postupak stvaranja indeksa u velikim tablicama, s nekoliko stotina tisuća i miliona redaka,
može potrajati nekoliko minuta.

1.3.4 Uništavanje indeksa

Shvatimo komandu kao «trganje» iz telefonskog imenika dodanih stranica sa sortiranim


ulicama. Srećom, stranice medija za pohranu podataka se proglašavaju slobodnima i bit će
ponovno upotrebljene, dok recikliranje starog papira ipak ne ide tako glatko.

DROP INDEX Studenti.Prezime_X

Uočimo, da se indeks određuje imenom tablice i imenom indeksa, no to se može razlikovati od


jednog do drugog sustava relacijskih baza.

Podrobnije o indeksima govori se u drugim poglavljima ovih skripta.

Opće pravilo stvaranja i uništavanja objekata baze podataka

- stvaranje

CREATE TipObjekta NazivObjekta (

Definicija objekta

- uništavanje

DROP TipObjekta NazivObjekta

1.4 Naredbe za upisivanje, promjenu i brisanje podataka

Cjeloviti informacijski sustav izgrađuje niz ekranskih formi – prozora preko kojih
upisujemno, mijenjamo ili brišemo podatke u tablicama relacijske baze, služeći se
programskim objektima za spajanje na bazu i rad sa skupovima podataka. No, pored toga, u
svim fazama života baze podataka, postavlaju se nepredviđeni upiti, a isto tako se obavljaju
ad hock izmjene podataka, pa stoga treba obratiti potrebnu pažnju i steći potrebnu sigurnost i
samopouzdanje u korištenju naredbi za manipulaciju podacima.

1.4.1 Upisivanje ( insertiranje ) retka

Upišimo novog studenta u tablicu Studenti, čije je ime Marko, prezime Marić, rođen je
07.08.1980. i upisan je na studijsku grupu 1. Poštanski broj njegove adrese za sada nije
poznat.

INSERT INTO Studenti( Prezime, Ime, StudijID, DatumRodjenja)

VALUES( 'Martić', 'Marko', 1, '1980/08/07' )

Primjetimo da nakon ključne riječi INSERT INTO slijedi ime tablice, te lista kolona u koje će
biti upisani podaci, dok ključnu riječ VALUES slijedi lista vrijednosti. Lista kolona i lista
vrijednosti moraju se podudarati po broju i tipu podataka. Sustav će javiti grešku ako:

broj kolona nije jednak broju datih vrijednosti


(There are more columns in the INSERT statement than values specified in the
VALUES clause. )

upisujemo vrijednost čiji tip ne odgovara ili se ne može pretvoriti u tip kolone, npr. ako
bismo u cjelobrojnu kolonu StudijID pokušali upisati tekst 'Marko'.
(Syntax error converting the varchar value 'Marko' to a column of data type
smallint.)

tekstualne konstante nisu zatvorene u jednostrukim navodnicima


(The name 'Marko' is not permitted in this context. Only constants, expressions, or
variables allowed here. Column names are not permitted.)

datum nije ispravan.


(The conversion of a char data type to a datetime data type resulted in an out-of-
range datetime value.)

nije navedena vrijednost za kolonu s obaveznim unosom ( NOT Null ), a da istovremeno


nije zadana ( kod kreiranja tablice ) pretpostavljena (default) vrijednost.
(Cannot insert the value NULL into column 'Prezime', table 'DT.dbo.Studenti';
column does not allow nulls. INSERT fails.The statement has been terminated.)
1.4.2 Upisivanje svih kolona

Kada naredba za upisivanje retka obuhvaća listu svih kolona definiranih u tablici, nije
neophodno navoditi listu kolona, već samo listu vrijednosti, pri čemu poredak vrijednosti
mora odgovarati fizičkom poretku kolona u tablici:

INSERT INTO Studenti

VALUES( 'Slavko', 'Perić', '1980/08/07', 1, 21000 )

Ovakvu naredbu možemo koristiti ad hock, dakle upotrijebimo i izbrišemo, ali nipošto u
programima ili skriptama koje se koriste trajno. Naime, tijekom vremena prpizići će potreba
za dodavanjem jedne ili više kolona u tablicu, što je uobičajena praksa kako primjena baze
napreduje, a onda broj kolona tablice i navedenih vrijednosti se neće podudariti. Stoga je
praktičana neophodnost da se uvijek navodi lista kolona u koje se upisuju vrijednosti.
Naknadno dodane kolone moraju dopuštati Null vrijednost ili imati definiranu pretpostavljenu
( default ) vrijednost.

1.4.3 Upisivanje iz jedne tablice u drugu

Stvorimo li tablicu Studenti2, s kolonama Ime, Prezime i StudijID, tada u nju možemo upisati
dio ili sve retke iz tablice Studenti, naredbom:

INSERT INTO Studenti2( Ime, Prezime, StudijID)

SELECT Ime, Prezime, StudijID

FROM Studenti

WHERE StudijID=1

Dobijena poruka je (5 row(s) affected), te možemo provjeriti sadržaj tablice Studenti2.

1.4.4 Pomjena podataka ( update )

Potrebno je promijeniti DatumRodjenja studentu Ivo Ivić. Ispravan datum je 21.06.1980.

UPDATE Studenti

SET DatumRodjenja='1980/06/21'

WHERE Ime='Ivo' AND Prezime='Ivić'


Prije izvođenja ovakve naredbe, moramo biti sigurni da će se promjena provesti samo
željenom studentu, pa je kod ovakvih promjena najbolje koristiti primarni ključ u WHERE
klauzuli. Česte su greške koje se dese zbog brzopletosti, npr. izvođenjem komande:

UPDATE Studenti

SET DatumRodjenja='1980/06/21'

Učinak je katastrofalan: svim studentima postavljen je isti datum rođenja. Naravno i za


ovakve pogreške moramo predvidjeti lijek, no u svakom slučaju dobro je izbjeći ovako
neugodne situacije, pažljivim zadavanjem naredbe UPDATE.

1.4.5 Promjena podataka tablice vrijednostima druge tablice

Svim studentima koji nemaju definiran poštanski broj, ( PostaID IS NULL), potrebno je
upisati broj čija druga znamenka slijeva odgovara broju StudijID, a prva znamenka je 2.

Kako se radi o zahtjevnoj naredbi, najprije ćemo provjeriti naše razmišljanje izvođenjem
SELECT upita, jer jasno je, pogrešno promijenjene podatke nije lako popraviti:

SELECT StudijID, S.PostaID, P.PostaID

FROM Studenti S, Poste P

WHERE CONVERT(varchar, StudijID)=SUBSTRING(CONVERT(varchar,


P.PostaID), 2,1) AND

P.PostaID BETWEEN 20000 AND 29999 AND S.PostaID IS NULL

StudijID S.PostaID P.PostaID


3 NULL 23000
2 NULL 22000
1 NULL 21000

Kako smo zaista dobropostavili uvjet, to vidimo da su obuhvaćeni samo studenti kojima nije
definirana PostaID ( NULL ), te da je prva znamenka slijeva poštanskog broja 2 i konačno
StudijID i driga znamenka poštanskog broja se uvijek podudaraju.

Stoga, provedimo promjene podataka:


UPDATE Studenti

SET PostaiD=P.PostaID

FROM Studenti S, Poste P

WHERE CONVERT(varchar, StudijID)=SUBSTRING(CONVERT(varchar,


P.PostaID), 2,1) AND

P.PostaID BETWEEN 20000 AND 29999 AND S.PostaID IS NULL

Jasno je, da će nakon izvedene naredbe PostaID dobiti ranijom komandom izlistane
vrijednosti.

1.4.6 Brisanje ( delete ) retka

Možemo brisati pojedinačne retke, grupu redaka koji zadovoljavaju određeni kriterij, ili pak
sve retke u tablici.

1.4.6.1 brisanje jednog retka

Općenito, sigurno ćemo izbrisati samo jedan redak, ako se u WHERE klauzuli testira
vrijednost primarnog ključa, jer on na jedinstven način identificira svaki redak.

Primarni ključ tablice Studenti je StudentID, čije vrijednosti automatski generira sustav
relacijske baze ( Autonumber ).

Brišemo, dakle trajno uklanjamo iz tablice, studenta Hrvoja Antića, čijije StudentID ( u mojoj
tablici ) 7 naredbom:

DELETE FROM Studenti

WHERE StudentID=7

Kako smo upotrijebili primarni ključ kao uvjet, to smo sigurni da je izbrisan najviše jedan
redak.

1.4.6.2 brisanje više redaka koji zadovoljavaju uvjet

Pretpostavimo da su se svi studenti iz Zadarske i Šibenske županije ispisali sa studija, te ih


moramo ukloniti iz tablice. Iskoritit ćemo pogodnost da sve pošte u Zadarskoj županiji
započinju s 23, a u šibenskoj s 22, pa su u opsegu brojeva 22000 do 23999 zaparavo sva mjest
ove dvije županije:

DELETE FROM Studenti


WHERE PostaID BETWEEN 22000 AND 23999

Rezulta je: (3 row(s) affected).

brisanje svih redaka tablice

Vrlo jednostavno, kako se i da pretpostaviti, ispuštanjem uvjeta bit će izbrisani svi retci
tablice.

DELETE FROM Studenti

Skrenimo pažnju, da je nakon izvedene komande, tablica potpuno prazna. Prije izvođenja
ovakvih komandi, moramo biti sigurni što želimo.

You might also like