Mikroandmebaasi ülesande nõuded
Vaata kindlasti lisaks soovitusi ja nõuandeid
Kokkuvõtlikult: loodav programm käivitatakse käsurealt, andes talle ette SQL-keeles päringulause, ning programm leiab seejärel lause tulemuse (kasutades samas kataloogis olevaid
csv-faile tabelitena) ja trükib selle välja.
Päringulauseks on oluliselt lihtsustatud variant SQL SELECT päringust: FROM tabelitena kasutame faile, WHERE päringutingimused on suhteliselt piiratud. Mingeid aliasi anda, alampäringuid teha, agregaatfunktsioone kasutada, sulgudes tehteid anda, or ja not funktsioone tarvitada jne ei saa.
Tekstifailide formaat on CSV (comma separated values, sellisteks saab salvestada näiteks Exceli faile).
Tekstifailidel on päis, selles mõttes, et esimene rida (muidu harilik CSV rida) sisaldab tulpade nimesid.
Programm (oletame, et ta nimeks on pandud myselect) niisiis:
- Võimaldab anda päringu käsurea parameetrina näiteks nii:
java myselect "select * from isik, amet where isik.amet=amet.ametinimi"
mispeale teostatakse päring ja trükitakse tulemus (päisega csv formaadis!) välja.
- Sisaldab kasulikku teeki (st hulka funktsioone), mida saaks kasutada teised programmid (umbes nagu Ecki TextIO klassi):
- SELECT päringu parsimiseks
- andmete lugemiseks failist
- parsitud päringu teostamiseks mälus
- tulemuse väljatrükkimiseks
Sisukord
SELECT päring ja mida sellega teha
Meie programm peab aru saama "hariliku" SQL keele SELECT päringu hästi lihtsustatud variandist. Meie programmi jaoks on see SELECT lihtsalt üks string, mis tuleb lõhkuda vajalikeks tükkideks, tükid salvestada omaette abimassiivides ning seejärel kasutada neid abimassiive vastuse kokkupanekul.
Meie SELECT lause süntaks:
select * from fail1,...,failn where tulp1=vaartus1 and .... and tulpm=vaartusm
kus:
- iga 'fail' vastab kettal samas kataloogis olevale csv-failile sufiksiga csv.
- iga 'tulp' on ühe fail tulba päis, süntaksiga 'fail.tulp'
- iga 'vaartus' on üks kahest:
- konkreetne string apostroofide vahel, näiteks '20'
- omakorda tulp (ilma apostroofideta, näiteks amet.isikukood)
Pane tähele lihtsustavaid asjaolusid:
- lause algab alati fraasiga 'select * from'
- 'from' järel kuni 'where' (või stringi lõpuni) on komadega eraldatud failinime-algused
- 'where' järel on ainult 'and'-ga eraldatud 'tulp=väärtus' kujul tekstitükid.
Näited ja seletused
Toome kõigepelt paar näidet, eeldades, et meil on kettal kaks faili
isikud.csv:
ikood,eesnimi,pereknimi,vanus,pikkus 10,Jaan,Mets,32,170.5 50,Mihkel,Karu,21,180.4 30,Anna Marie,Rebane,22,165
ametid.csv:
amet,isikukood,palk koristaja,10,5000 lektor,10,5000 direktor,30,9000
Päring
select * from isikud
trükib välja esimese tabeli (isikud.csv) täpselt, nagu ta on, kuid lisab päisetulpadele failinime algusotsa:
isikud.ikood,isikud.eesnimi,isikud.pereknimi,isikud.vanus,isikud.pikkus 10,Jaan,Mets,32,170.5 50,Mihkel,Karu,21,180.4 30,Anna Marie,Rebane,22,165
Päring
select * from isikud where isikud.vanus='21'
trükib ühe päisega rea esimesest tabelist:
isikud.ikood,isikud.eesnimi,isikud.pereknimi,isikud.vanus,isikud.pikkus 50,Mihkel,Karu,21,180.4
Päring
select * from ametid where ametid.palk='5000'
trükib kaks päisega rida teisest tabelist:
ametid.amet, ametid.isikukood, ametid.palk koristaja,10,5000 lektor,10,5000
Päring korraga kahest tabelist ilma where-piiranguteta ehitab tabeli, kus on kõigi esimese tabeli ja teise tabeli ridade kombinatsioonid (nn ristkorrutis):
select * from isikud, ametid
trükib järgmise üheksa reaga tabeli (päiserida peab olema üksainus, aga järgnevas ta lihtsalt ei mahu ühele reale välja näitamiseks):
isikud.ikood,isikud.eesnimi,isikud.pereknimi,isikud.vanus,isikud.pikkus, ametid.amet,ametid.isikukood,ametid.palk 10,Jaan,Mets,32,170.5,koristaja,10,5000 10,Jaan,Mets,32,170.5,lektor,10,5000 10,Jaan,Mets,32,170.5,direktor,30,9000 50,Mihkel,Karu,21,180.4,koristaja,10,5000 50,Mihkel,Karu,21,180.4,lektor,10,5000 50,Mihkel,Karu,21,180.4,direktor,30,9000 30,Anna Marie,Rebane,22,165,koristaja,10,5000 30,Anna Marie,Rebane,22,165,lektor,10,5000 30,Anna Marie,Rebane,22,165,direktor,30,9000
Pane tähele, et:
- Nii päis kui iga rida tulemuses on lihtsalt kahe sisend-tabeli rea järjest-summa
- Igale reale esimeses tabelis vastab kolm rida tulemuses (sest teises tabelis on samuti kolm rida: kui teises tabelis oleks seitse rida, siis vastaks igale esime tabeli reale seitse rida tulemuses).
Oletame, et meil on veel üks, kaherealine tabel:
koolid.csv:
ikood,kool 10,tty 30,peda
ja päring üle kolme tabeli:
select * from isikud, ametid, koolid
Siis tulemuses oleks juba 18 rida:
isikud.ikood,isikud.eesnimi,isikud.pereknimi,isikud.vanus,isikud.pikkus, ametid.amet,ametid.isikukood,ametid.palk,koolid.ikood,koolid.kool 10,Jaan,Mets,32,170.5,koristaja,10,5000,10,tty 10,Jaan,Mets,32,170.5,koristaja,10,5000,30,peda 10,Jaan,Mets,32,170.5,lektor,10,5000,10,tty 10,Jaan,Mets,32,170.5,lektor,10,5000,30,peda 10,Jaan,Mets,32,170.5,direktor,30,9000,10,tty 10,Jaan,Mets,32,170.5,direktor,30,9000,30,peda 50,Mihkel,Karu,21,180.4,koristaja,10,5000,10,tty 50,Mihkel,Karu,21,180.4,koristaja,10,5000,30,peda 50,Mihkel,Karu,21,180.4,lektor,10,5000,10,tty 50,Mihkel,Karu,21,180.4,lektor,10,5000,30,peda 50,Mihkel,Karu,21,180.4,direktor,30,9000,10,tty 50,Mihkel,Karu,21,180.4,direktor,30,9000,30,peda 30,Anna Marie,Rebane,22,165,koristaja,10,5000,10,tty 30,Anna Marie,Rebane,22,165,koristaja,10,5000,30,peda 30,Anna Marie,Rebane,22,165,lektor,10,5000,10,tty 30,Anna Marie,Rebane,22,165,lektor,10,5000,30,peda 30,Anna Marie,Rebane,22,165,direktor,30,9000,10,tty 30,Anna Marie,Rebane,22,165,direktor,30,9000,30,peda
Võtame uuesti kahe tabeliga näite ja lisame talle ühe päringutingimuse, mis ütleb,
et isikud.ikood ja ametid.isikukood väärtused reas peavad kokku langema:
select * from isikud, ametid where isikud.ikood=ametid.isikukood
trükib järgmise kolme sisureaga tabeli (päiserida peab olema üksainus, aga järgnevas ta lihtsalt ei mahu ühele reale välja näitamiseks):
isikud.ikood,isikud.eesnimi,isikud.pereknimi,isikud.vanus,isikud.pikkus, ametid.amet,ametid.isikukood,ametid.palk 10,Jaan,Mets,32,170.5,koristaja,10,5000 10,Jaan,Mets,32,170.5,lektor,10,5000 30,Anna Marie,Rebane,22,165,direktor,30,9000
Kui viimast päringut veelgi piirata, näiteks nii:
select * from isikud, ametid where isikud.ikood=ametid.isikukood and ametid.palk='5000'
saame tulemusse ainult kaks rida:
isikud.ikood,isikud.eesnimi,isikud.pereknimi,isikud.vanus,isikud.pikkus, ametid.amet,ametid.isikukood,ametid.palk 10,Jaan,Mets,32,170.5,koristaja,10,5000 10,Jaan,Mets,32,170.5,lektor,10,5000
Kui aga paneme where-tingimusse vastuolulise piirangu, näiteks:
select * from isikud, ametid where ametid.palk='5000' and ametid.palk='keskmine'
siis (kuna string '5000' alati erineb stringist 'keskmine') saame alati vastuseks tühja tabeli:
isikud.ikood,isikud.eesnimi,isikud.pereknimi,isikud.vanus,isikud.pikkus, ametid.amet,ametid.isikukood,ametid.palk
Olulised lihtsustused
Selles praktikumiülesandes eeldame, et meil on kettal üks või mitu faili andmetega, ning realisatsioon loeb nad hakatuseks vajaduse järgi mällu ja alles seejärel asub mälust vajalikke andmeid otsima.
Andmete kirjeldamist, muutmist ja lisamist olemasolevatesse failidesse selles ülesandes programmeerida ei ole vaja.
Kuna praktikumis ei jõuaks keegi väga palju asju valmis programmeerida, on vaja teha valmis ainult mõned, suhteliselt lihtsad funktsioonid.
Andmete esitus kettal
Meie süsteem eeldab, et andmed on kettal failides, iga fail esitab ühte tabelit:
- Iga fail koosneb tulpadest.
- Faili iga rida (v.a. esimene rida) sisaldab ühte rida tabelist, ning tulpade vahel on kas koma või semikoolon: kumbat sinu programm eeldab (alati ühte kahest), see peab olema sinu programmi ühe globaablse muutujaga määratav.
- Esimene rida on muidu harilik CSV rida, kuid sinu teegifunktsioonid eeldavad, et esimene rida sisaldab tulpade nimesid, ja mitte sisulisi andmeid. Andmete sisselugemisel ja trükkimise juures loetakse ja trükitakse esimene rida loomulikult ka, samamoodi, kui kõik ülejäänud.
- Iga andmeühik on string ja ta ei ole failis pandud jutumärkide vahele.
- Üheski andmeühikus (stringis) ei tohi esineda jutumärke ega eraldajat - koma või semikoolonit - muidu läheks rea struktuur sassi.
Näide nelja tulba ja nelja reaga (neis esimene päiserida) failist kettal:
eesnimi,pereknimi,vanus,pikkus Jaan,Mets,32,170.5 Mihkel,Karu,21,180.4 Anna Marie,Rebane,22,165
Pane tähele, et stringides tohivad olla tühikud (näiteks nimes Anna Marie).
NB!
- Selline andmete esitamise formaat on väga harilik: seda nimetatakse CSV (comma separated values) ja te saate MS Exceli tabeleid selliselt kettale salvestada (Save as -> vali CSV formaat) ja ka lugeda.
- Eesti settingute korral kasutab Excel CSV formaadi salvestamise korral koma asemel semikoolonit ; (põhjus: komaga numbrid Eesti settingutes on komaga, kuid normaalsetes settingutes on komaga numbrid punktiga)
- Kui mõni string Exceli tabelis sisaldab koma, siis paneb Excel CSV-formaadis salvestamisel selle ümber erandina jutumärgid.
- Kui mõni string Exceli tabelis sisaldab ise jutumärki, siis asendab Excel CSV-formaadis salvestamisel selle topelt-jutumärgiga.
Meie oma praktikumitöös eeldame lihtsuse mõttes,
et stringides komasid ja jutumärke ei ole.
Sellega pääseme äsjakirjeldatud eranditest,
st olukorrast, kus vahel stringidel jutumärgid
ümber ja stringi sisemised jutumärgid on
asendatud topelt-jutumärgiga.
Vigade töötlus
Mistahes vigade ilmnemisel ei tohi programm nö kokku kukkuda või anda Java enda, süsteemset veateadet, millest kasutaja aru ei saa.
Vead tuleb kinni püüda (kas if-dega kontrollides või try ... catch-i kasutades) ning anda kasutajale arusaadav veateade.
Millised on vead, mis võivad juhtuda (näited: ei pea kasutama täpselt sellist vigade "kataloogi" ja veateateid):
- päringu süntaks on vale
- päringus nõutud faili ei leitud
- päringus nõutud faili ei saa avada
- faili ridades on erinev tulpade arv
- faili päisereas puudub päringus nõutud tulp