# Teema: Andmebaasi kavandamise sisulised küsimused ## Küsimus: Andmebaaside aine pöörab palju tähelepanu süsteemianalüüsile. Miks see on oluline? **Vastus:** Oma iseseisva töö projekti tegemise käigus tuleb Teil ennast panna süsteemianalüütiku rolli. Siin on 15.02.2017 Postimehes ilmunud artikkel analüüsi olulisusest süsteemide loomisel ning sellega seotud valikutest haridusmaastikul. Tööelus võite puutuda infosüsteemide arendamisega kokku tellijana, täitjana või näiteks tellija esindajana, kes täitjat igapäevaselt konsulteerib. Hästi toimiva infosüsteemi loomine algab õige ülesandepüstituse koostamisest. Elu näitab, et "IT-probleemide püstitamine ja kirjeldamine viisil, mis tagaks efektiivse tööprotsessi ja tõhusad lahendused", ei tule sageli nii hästi välja kui võiks. Seega ei jookse mööda külge maha oskus ülesandepüstitust (nõudeid) kirja panna. Arendaja rollis on jällegi vajalik oskus kirjapandud nõuetest aru saada. Üheks suure infosüsteemi ebaõnnestunud arendamise näiteks on Ruumilise planeeringu infosüsteem (RPIS). See loodi detailplaneeringutete avaliku väljapaneku kättesaadavuse parandamiseks ning planeeringute kooskõlastamise kiiremaks, jälgitavamaks ja mugavamaks muutmiseks. Süsteemi arendatakse alates 2009. aastast, sellele on kulutatud peaaegu miljon eurot, kuid kasutajaid peaaegu ei ole. Kohalikud omavalitsused eelistavad teisi turul saadaolevaid süsteeme. Selle asemel, et hakata suure hooga nullist uut süsteemi tegema oleks tulnud kõigepealt aru saada, kas ning mida on vaja - võibolla oleks piisanud mõne turul oleva süsteemi kohandamisest. Sellistele küsimustele annab vastuse süsteemianalüüs. Võibolla oleks olnud ka abi tööprotsesside lihtsustamisest - sellega tegeleb ärianalüüs (business analysis), millega käesolev kursus ei tegele. Jaakkola et al. (2016) kohaselt kasvavad nõuete kogumise (analüüsi) faasis tehtud vigade parandamiseks kuluv pingutus iga järgmise süsteemiarenduse faasiga kolm korda. Disaini faasis on neid 3, realiseerimise faasis 9 ja testimise faasis 27 korda kulukam parandada kui nõuete kogumise faasis. Jaakkola, H., Henno, J., Welzer-Druzovec, T., Thalheim, B., Mäkelä, J., 2016. Why Information Systems Modelling Is Difficult. In SQAMIA. pp. 29– 39. Ehk olete kuulnud sotsiaalkaitse infosüsteemi uue versiooni (SKAIS2) arendamise saagast. Praeguseks on kulud kasvanud kaugelt üle algselt planeeritu ja projekti lõppu ei paista. 2019. aasta jaanuaris kuulutati välja järjekordne riigihange süsteemi uute osade tegemiseks ning olemasolevate parandamiseks. Hanke dokumendid on avalikkusele kättesaadavad riigihangete registris ja neid tasub huvi korral sirvida selle pilguga, et: kui mahukas on keerulise infosüsteemi kirjeldus, milliseid dokumente peavad pakkumise koostajad, sh majandusinimesed oskama kirjutada, milliseid dokumente peavad pakkumisele reageerijad ja ka hiljem analüütikud ning arendajad oskama lugeda. Huvi korral vaadake näiteks "Lisa 3. Nõuded infosüsteemi dokumentatsioonile", "Lisa 2. Mittefunktsionaalsed nõuded", "Lisa 1. Arhitektuuri ülevaade". Mitmed soovitud dokumentidest (sh mittefunktsionaalsed nõuded, kuid mitte arhitektuuri kirjeldus) on ka iseseisva töö projektis. "Lisa 5. Tehniline kirjeldus" esitatud tekstilise jutu süsteemilt oodatavatest funktsionaalsustest peab süsteemianalüütik oskama tõlkida täpsemate mudelite keelde (kasutusjuhtude mudelid, protsessimudelid, seisundidiagrammid, andmemudel jne). "Lisa 11.1. Ärianalüüs" dokumendis on väljatoodud põhimõisted ja nende definitsioonid. Selleks, et midagi koos arendada on oluline, et kõik arendusest huvitatud osapooled mõistetest võimalikult täpselt ja ühtemoodi aru saavad. Teie projektis on selliseks mõistete kataloogiks kontseptuaalse andmemudeli osaks olev olemitüüpide ja atribuutide definitsioon.Veel üks sarnane näide on 2024. aasta veebruaris Põhja-Eesti Regionaalhaigla uue elektroonilise haigla infosüsteemi riigihange, mille hankedokumente saab samuti vaadata riigihangete registrist. "Tehniline kirjeldus lisa 1 - Funktsionaalsed nõuded" loetleb nimekirjana nii funktsionaalseid kui mittefunktsionaalseid nõudeid. "Tehniline kirjeldus lisa 2 - Protsessianalüüs" toob näitena välja mõned keerukad protsessid, mille läbiviimist uus infosüsteem toetama peab. Protsessimudelid on ülesjoonistatud BPMN (Business Process Modelling Notation) modelleerimiskeeles.Informaatika (ilmselt ka äriinfotehnoloogia) lõputööde kaitsmiskomisjonid peavad oluliseks seda, et arenduse teemaline lõputöö ei oleks etteantud tööülesannete (nõuete) täitmise aruanne, vaid et töö käigus tegeletakse ka nõuete kogumise ja väljendamisega. Kui arendaja peab kellegi teise etteantud nõuete järgi kirjutama koodi, siis see ei sobi lõputööks või vähemasti tõmbab see hindajate silmis töö väärtust väga palju alla. Õppekavades, kus on "Andmebaasid I", on see praktiliselt ainus aine, mis puudutab süsteemianalüüsi. Seega kus siis veel kui mitte siin.Siin, siin, siin ja siin on näide äriinfotehnoloogia lõputöödest, mille sisuks oli mahukas süsteemianalüüs. Kuid ka informaatika arenduse teemalistes lõputöödes ei tohi süsteemianalüüs puududa. Siin ja siin on näited informaatika lõputöödest, kus süsteemianalüüs on hästi olemas. Lõpetuseks veel üks pildirida, mis illustreerib seda, mis võib süsteemi arendamise, sh analüüsi käigus valesti minna. **Märksõnad:** süsteemianalüüs, analüütik, detailanalüüs, strateegiline analüüs, ärianalüüs, nõuded ## Küsimus: "Andmebaasid I" õppeaines kasutame infosüsteemi ja selle osaks oleva andmebaasi kirjeldamiseks UML modelleerimiskeelt. Milliseid allikaid soovitate UMLiga tutvumiseks või selle kohta teadmiste värskendamiseks lugeda? **Vastus:** Ma olen ka koostanud ühe eestikeelse konspekti, mida huvilised saavad lugeda lisamaterjalide lehelt (kasutajanimi: SIS2 ja parool: SIS2) SELLEST MATERJALIST. Raamatutest soovitan eestikeelset raamatut: Fowler, M., 2007. UMLi kontsentraat. 3. redaktsioon. Objektmodelleerimise standardkeele UML2.0 lühijuhend. Cybernetica AS. [WWW] https://www.ester.ee/record=b2282809~S1*est Kaanepilt: https://www.apollo.ee/umli-kontsentraat.html Seda raamatut on paraku väga vähe saadaval. Kui näete kuskil pakkumist või saate laenutada, siis soovitan sellest kinni haarata. Järgnevatest allikatest leiate ingliskeelse ülevaate UML 2.X erinevatest diagrammitüüpidest: Larman, C., 2013. Applying UML and patterns : an introduction to object-oriented analysis and design and iterative development, Prentice Hall. 703 p. [WWW] https://www.ester.ee/record=b2048056*est Raamatut saab lugeda O'Reilly digitaalselt platvormilt SIIN Kuidas kasutada O'Reilly digitaalset platvormi? http://agilemodeling.com/essays/umlDiagrams.htm https://www.uml-diagrams.org/ **Märksõnad:** tegevusdiagramm, kasutusjuhtude diagramm, seisundidiagramm, klassidiagramm, olemi-suhte diagramm, andmebaasi diagramm, olekumasin, olekumasina skeem ## Küsimus: Andmebaasis on tabelid, millesse võib olla vaja teha muudatusi. Osadel kasutajatel on muudatuste tegemise õigus, neil kellel pole, peaks olema aga võimalus muudatusi soovitada, need soovitused jõustuksid peale muutmisõigusega kasutaja heakskiitu. See süsteem oleks inspireeritud sellest, kuidas toimivad pull request'id / merge request'ed GitHub ja GitLab keskkondades. Samasugune loogika on olemas ka näiteks Google Docsis (inimese saab lisada soovituse, mis vajab dokumeni omaniku heakskiitu). Kasutaja ei pruugi siinjuures tähistada andmebaasi kasutajat, tegemist võib olla rakenduse kasutajatega, ehk siis kirjetega tabelis `User`. Hea oleks, kui tegemist ei oleks mitte ühe tabeli spetsiifilise lahendusega, vaid üldise lahendusega, mida saaksid kasutada erinevad tabelid. Kuidas võiks sellist asja PostgreSQLiga teha? **Vastus:** Üks võimalus oleks luua soovitatud muudatuste jaoks tabelid.Soovituse_seisundi_liik(soovituse_seisundi_liik_kood, nimetus)Primaarvõti (soovituse_seisundi_liik_kood)Alternatiivvõti (nimetus)Tabelis Soovituse_seisundi_liik on registreeritud seisundid "esitatud", "vastuvõetud" ja "tühistatud".Muutmise_soovitus (soovitus_id, skeemi_nimi, tabeli_nimi, veeru_nimi, võti, väärtus, soovituse_aeg, soovitaja, soovituse_seisundi_liik_kood)Primaarvõti (soovitus_id)Alternatiivvõti (skeemi_nimi, tabeli_nimi, veeru_nimi, võti, soovituse_aeg, soovitaja)Välisvõti (soovituse_seisundi_liik_kood) Viitab Soovituse_seisundi_liik(soovituse_seisundi_liik_kood)Välisvõti (soovitaja) Viitab Kasutaja (kasutaja_id) Tabeli Muutmise_soovitus veerul soovituse_seisundi_liik_kood on vaikimisi väärtuseks seisundile "esitatud" vastav kood. Tabeli Muutmise_soovitus veerul soovituse_aeg on vaikimisi väärtuseks ajatempli leidmiseks mõeldud funktsiooni poole pöördumine. (skeemi_nimi, tabeli_nimi, veeru_nimi) identifitseerivad tabeli+veeru, kus soovitakse muudatust teha ning veerus võti olev väärtus identifitseerib rea tabelis, milles soovitakse muudatust teha. Muutmise_soovitus veerg võti võiks näiteks olla massiivitüüpi text[][] ning seal oleks registreeritud võtmeveergude nimede ja nende väärtuste tekstiliste esituste paarid. Alternatiiv oleks see esitada JSON objektina ja siis oleks veerg võti tüüpi JSONB. Variant oleks ka kasutata tüüpi hstore, millesse kuuluvad väärtused on võti-väärtus paaride hulgad. Tabeli Muutmise_soovitus veerg väärtus on tekstitüüpi (PostgreSQL puhul tüüpi TEXT), et registreerida soovitatud väärtuse tekstiline esitus. Kas soovituse esitamisel või ülevaatamisel tuleb kontrollida, et see on teisendatav sobivat tüüpi väärtuseks (a'la, keegi soovitab kuupäeva 31. veebruar 2022). Veeru tüübi saab kindlaks teha päringu abil INFORMATION_SCHEMA.columns süsteemikataloogi vaate põhjal, sest soovituse tabelis on skeemi, tabeli ja veeru nimi registreeritud. Tabel Muutmise_soovitus on mõeldud selleks, et soovitada UPDATE operatsioone. Kui soovitada saaks ka ridade lisamist (INSERT) või kustutamist (DELETE), siis selleks looksin eraldi tabelid (Lisamise_soovitus ja Kustutamise_soovitus). Tabelis Kustutamise_soovitus ei ole vaja veerge veeru_nimi ja väärtus. Tabelis Lisamise_soovitus ei ole vaja veerge veeru_nimi ja võti. Veerus väärtus peab olema lisatava rea esitus (sõltuvalt kasutatavast tüübist kas massiivina, JSON objektina või võti-väärtus paaride hulgana).Keerukust soovituste ülevaatamisele lisab see, kui samale väljale/reale on tehtud mitu soovitust. Ilmselt peaks ülevaatajale kõiki näitama ja andma talle võimaluse ühe valida või enda poolt mingi kombineeritud väärtus sisestada.Edasiarenduseks on näiteks võimalus määrata, kas kasutajale või kasutajate rollile (mida võib omada mitu kasutajat) veerud, mille jaoks on tal üldse lubatud muudatusi soovitada.Kastutaja (kasutaja_id, ....)Primaarvõti (kasutaja_id)Kasutaja_roll (kasutaja_roll_kood, nimetus)Primaarvõti (kasutaja_roll_kood)Alternatiivvõti (nimetus)Kasutaja_rolli_omamine (kasutaja_id, kasutaja_roll_kood)Primaarvõti (kasutaja_id, kasutaja_roll_kood)Välisvõti (kasutaja_id) Viitab Kasutaja (kasutaja_id)Välisvõti (kasutaja_roll_kood) Viitab Kasutaja_roll (kasutaja_roll_kood)Muutmise_soovituse_luba (skeemi_nimi, tabeli_nimi, veeru_nimi, kasutaja_roll_kood)Primaarvõti (skeemi_nimi, tabeli_nimi, veeru_nimi, kasutaja_roll_kood)Kui soovitada saab ka ridade lisamist või kustutamist, tuleks luua ka tabelid Lisamise_soovituse_luba ja Kustutamise_soovituse_luba.Õiguste poolelt soovitaksin lahendust, kus igale rakenduse lõppkasutajale (mille kohta on rida tabelis Kasutaja) vastaks ka eraldi andmebaasi kasutaja (seda on muide tehtud selles näiteprojektis) nii nagu soovitakse  SELLES artiklis andmebaasipõhise turvalisuse tagamise mudeli kohta. See võimaldab teha nii, et rakenduse kasutajatel, kes saavad soovitada muudatusi, on INSERT õigus tabeli Muutmise_soovitus suhtes, kuid ei ole UPDATE õigust tabelite suhtes, mille jaoks muudatusi soovitatakse. Rakenduse kasutajatel, kes saavad ise otse muudatusi teha on UPDATE õigus muudetava tabeli suhtes, kuid ei ole INSERT õigust tabeli Muutmise_soovitus suhtes. Muudatuste kinnitamiseks võiks luua plpgsql keeles kirjutatud funktsiooni, mis koostab muudatuste soovituse andmete põhjal dünaamiliselt SQL lause, mille abil muudatus ära teha, käivitab selle lause ja muudab ühtlasi soovituse seisundit. Kui funktsioonis kasutada SECURITY DEFINER määrangut, siis saab teha nii, et ülevaatajal on funktsiooni käivitamise õigus, kuid tal ei ole muutmisõiguseid soovituste tabeli ja tegelike andmetega tabeli suhtes. **Märksõnad:** PostgreSQL ## Küsimus: Igal isikul on null või rohkem meiliaadressi. Võib juhtuda, et mitu isikut jagavad ühte ja sama meiliaadressi. Kas selliste andmete hoidmiseks peaks tegema kokku kolm tabelit: meiliaadresside tabeli, isikute tabeli ja meiliaadresside ja isikute vahelist M:N seost esitava vahetabeli? **Vastus:** Ma arvan, et ei peaks.Kui andmebaasis oleksid tabelid:Isik (isik_id, ...)Primaarvõti (isik_id)E_meil (e_meil_id, e_meil)Primaarvõti (e_meil_id)Alternatiivvõti (e_meil)Isiku_meiliaadress (isik_id, e_meil_id)Primaarvõti (isik_id, e_meil_id)Välisvõti (isik_id) Viitab Isik (isik_id)Välisvõti (e_meil_id) Viitab E_meil (e_meil_id), siis päring, mis seob isikuandmed meiliaadressidega, peab lugema kolme tabelit. Eraldi meiliaadresside tabelil oleks mõtet, kui meiliaadressi kohta oleks vaja talletada veel andmeid - näiteks oleks tegemist põhiobjektiga, mille korral tuleb fikseerida selle seisund/staatus. Analoogiana võiks mõelda isiku nimele. Igal isikul on üks või rohkem nime komponenti (nt eesnimi, perenimi, isanimi) ning üks ja sama nimi võib kuuluda mitmele isikule. Lahendus, mille korral on eraldi tabel Isikunimi, kus oleksid näiteks registreeritud nimed nagu "Mari" ja "Maasikas", mida tuleks vahetabeli kaudu siduda tabeliga Isik, ei tundu mulle otstarbekas ja ma pole ka sellist lahendust kuskil kohanud. Selle asemel võiks luua tabelid.Isik (isik_id, ...)Primaarvõti (isik_id)Isiku_meiliaadress (isik_id, e_meil)Primaarvõti (isik_id, e_meil)Välisvõti (isik_id) Viitab Isik (isik_id)Kui primaarvõtme kitsenduses on veerud just selles järjekorras, siis tekib andmebaasis automaatselt liitindeks, kus isik_id on esimene veerg. Sellisel juhul pole vaja luua välisvõtme toetuseks veerule isik_id eraldi indeksit. Ühtlasi tagab selline primaarvõti, et sama meiliaadressi ei saa sama isikuga korduvalt siduda.Isiku_meiliaadress oleks antud juhul nn nõrk olemitüüp (weak entity type), mille eksemplari eksistents sõltub seotud tugeva olemitüüpi (strong entity type) Isik eksemplari olemasolust. Seega sobib Isik tabelile viitavale välisvõtmele ON DELETE CASCADE kompenseeriv tegevus. See  on loogiline, sest meiliaadress on lisainfo isiku kohta ja kui kustub isik, siis peaks kustuma ka lisainfo.Sellise kahe tabeliga lahenduse eelis ühe tabeliga lahenduse ees (meiliaadressid on salvestatud tabelis Isik kui massiivi väärtused, json objekt või XML objekt) on näiteks see, et lihtsam on jõustada reeglit, mille kohaselt samal isikul ei tohi olla sama meiliaadressi korduvalt. ## Küsimus: Kas ja millised probleemid võivad tekkida andmebaasirakenduse tegemisel kasutades mõnda ORM (Object-Relational Mappers, objekt-relatsioonvastenduse) vahendit? **Vastus:** SIIN (Sulaoja, K.M., Saarep, A. Cognate kasutajamugavuse parandamine ja arendustöö lihtsustamine) on 2024. aasta bakalaureusetöö, mille sisuks oli ühe Tallinna Tehnikaülikoolis õppetöö läbiviimist abistava süsteemi parandamine ning edasiarendamine. Ka süsteemi eelmine versioon tehti üliõpilaste poolt. Süsteemi realiseerimiseks kasutati Django ORMi. Jaotises 3.3.1 (lk 26-27) kirjutatakse ORM probleemidest ning jaotises 3.3.2 tuuakse näide, et need probleemid päriselt esinevad. ORM probleemide hulka kuulub see, et vahendi oskamatu kasutuse korral tehakse andmebaasi põhjal liiga palju päringuid ja see aeglustab süsteemi tööd. Autorid tõdesid, et süsteemi puhul "oli reageerimiskiiruse pudelikaelaks tagarakenduse kood ning Djangosse sisseehitatud objekt-relatsioonvastanduse ehk ORM-i (object-relational mapping) valekasutus".Autorid uurisid enne paranduste tegemist rakenduse tööd 63 registreeritud projekti ning hindamissüsteemi kaheksa tähtpunkti korral. "Selgus, et 63 projekti puhul tehakse 12124 erinevat baasipäringut, mille kogupikkus jäi keskmiselt vahemikku 6400-6700ms. Sealjuures 12117 neist olid märgitud sarnasteks, millest omakorda 7862 olid duplikaadid. Kogu aeg lokaalselt, mis kulus alates päringu vastuvõtust kuni vastuse saatmiseni (Total CPU time, andmete saatmine üle võrgu ei ole sisse arvestatud), jäi vahemikku 20-22 sekundit. Tootekeskkonna kogu ajakulu oli vahemikus 12-14 sekundit".Autorid kirjutasid rakenduse paranduste kohta: "Kõige suurema mõjuga neist oli baasipäringute viimine tsüklitest väljapoole. Varasemalt tehti tsüklites kokku mitutuhat duplikaadist baasipäringuid. Tsüklites päringute tegemine tõi esile ka jõudlust suuresti mõjutava N+1 probleemi, mis lahendati baasolemiga seotud andmete kohese baasist välja pärimisega. Lisaks üritati võimalikult palju eemaldada Django Model tüüpi objektide kasutust, kuna nende loomine on väga kulukas protsess. Selle asemel küsiti välja ning kasutati andmeid primitiivsete väärtustena. Optimeerimise tulemusena toodi baasipäringute arv alla 9-le päringule, mille tegemiseks kulus 10-14ms. Kusjuures enam ei tehta mitte ühtegi sarnast või duplikaadist baasipäringut. Lokaalselt kulub varasema 20-22 sekundi asemel päringule nüüd 140-160ms. Tootekeskkonnas aga veidi üle 300ms, mis tähendab, et päring on ligi 70 korda kiirem."ORMis tulenevaid probleeme: tabelite struktuuri kirjeldamine ORMi koodis võib viia halvasti struktureeritud andmebaasini, päringute kirjeldamine ORMi koodis võib viia vigaste või ebaefektiivsete andmebaasi päringute täitmiseni, suunab tegema valikuid, mis on rakenduse kiire valmimise seisukohast mugavad, kuid teises olukorras vähendab andmete kasutamise mugavust, surrogaatvõtme veeru nimega id automaatne lisamine,  kas on ikka meeles teisi võtmeid leida ja jõustada? tabelite ühendamise päringute käsitsi kirjutamine on tänu sellisele nimevalikule ebamugavam. oskamatu kasutus võib viia liigsete andmebaasipäringute käivitamiseni, loetakse rida ühest tabelist ja siis tsüklis seotud read teisest tabelist (iga rea küsimiseks eraldi lause), selle asemel, et kõiki neid andmeid ühe lausega küsida. Mõttearendus sellel teemal, kuidas ORM pakutav (objektorienteeritud) mõtteviis ja relatsiooniline mõtteviis on põhimõtteliselt erinevad, sest esimene nendest töötab üksikute olemitega teine aga nende hulkadega ning kuidas ORM propageeritav mõtteviis viib selleni, et andmebaasisüsteem peab tegema liigselt tööd (täitma liiga palju SQL lauseid) ning selle all kannatab süsteemi jõudlus.. ORM vahendi(te) probleemidele osutab see uuring 67 avatud lähtekoodiga tarkvara põhjal. Siin on veel üks suure hulga põhjendustega selgitus, miks üks arendaja loobus ORMi kasutamisest ning eelistab ise SQL lauseid kirjutada. Siin on arutelu, kus kõrvutatakse ORMi ja andmebaasiserveris talletatud rutiinidest, vaadetest ja hetktõmmistest koosneva virtuaalse andmete kihi kasutamist.Isegi ORMi kasutamise korral saab teha nii, et  rakendus kasutab andmebaasi läbi avaliku andmebaasi liidese e virtuaalse andmete kihi. Sellisel juhul loeks rakendus andmeid vaadetest (näiteks Djangos on see võimalik) ning muudaks andmeid kasutades andmebaasiserveris talletatud rutiine (näiteks Djangos on see võimalik). Andmete kitsendustele vastavuse kontroll toimuks andmebaasi tasemel (kasutades deklaratiivseid kitsendusi ja reegleid), mitte rakenduse tasemel nagu ORM vahendid üldiselt propageerivad. Rakenduse tasemele andmete kontrolli probleemiks on: üleliigsed päringud andmebaasi põhjal, mis kokkuvõttes aeglustavad ORM abil loodud programmi tööd, kontrollide ebapiisavus selles mõttes, et juhul kui samu andmeid kasutab samaaegselt mitu kasutajat, siis võivad need kontrollid lasta läbi reeglitele mittevastavaid andmeid. Kuigi eelnev näitab, et ORMi ja andmebaasi avalikku liidest saab koos kasutada, siis praktikas on need alternatiivid. Alternatiiv 1: Rakendus kasutab andmebaasi läbi ORMi. ORM vahend genereerib ise SQL koodi, millega loetakse ja muudetakse andmebaasis andmeid otse baastabelites. Selleks, et piirata kasutajate juurdepääsu teatud tingimustega tabeli ridadele, pakuvad andmebaasisüsteemid vahendeid nagu turvapoliitikad (PostgreSQL) või peeneteralised juurdepääsupiirangud. Alternatiiv 2: Rakendus kasutab andmebaasi läbi avaliku andmebaasi liidese, mille realiseerimiseks kasutatakse andmebaasis loodud vaateid, rutiine ja materialiseeritud vaateid e hetktõmmiseid. Rakendus ei pöördu otse baastabelite poole, vaid kasutab nendes olevaid andmeid läbi avaliku liidese. **Märksõnad:** rutiin, funktsioon, protseduur, hetktõmmis, materialiseeritud vaade, virtuaalne andmete kiht, andmebaasi avalik liides ## Küsimus: Kas kuskil on nähtav andmebaasitehnoloogiate suur pilt? **Vastus:** Suur pilt (1. juuni 2015 seisuga) erinevatest andmebaasitehnoloogiatest ning neid realiseerivatest tarkvarasüsteemidest. Siin ja siin aga on iga kuu uuendatav andmebaasisüsteemide populaarsuse indeks. ## Küsimus: Kas leidub kergesti kättesaadavat eestikeelset kirjandust SQL-andmebaaside kavandamisel ettetulevatest probleemidest ja nende lahendustest? **Vastus:** Tallinna Tehnikaülikooli üliõpilased on lõputöödena koostanud mustrite katalooge. Need lõputööd on kättesaadavad Tallinna Tehnikaülikooli digikogust. Muster on nimega kirjeldus, milles on esitatud probleem ja lahendus sellele probleemile. Samuti on kirjeldatud, millal seda lahendust rakendada ja kuidas rakendada lahendust uues kontekstis. Antimustrid, vastupidiselt, kirjeldavad probleemide halbu lahendusi, koos soovitustega, kuidas probleemi paremini lahendada. Analüüsi mudelite antimustrid. Disainimustrid üldistusseoste esitamise kohta SQL-andmebaasides. Disainimustrid kitsenduste jõustamise kohta PostgreSQL andmebaasis. Disainimustrid klassifikaatorite esitamiseks SQL-andmebaasides. Mitmekeelsete SQL-andmebaaside disainimustrid. Disainimustrid isikunimede hoidmiseks SQL‑andmebaasides. Selles töös on hea ülevaade nii maailma rahvaste kultuurilisest rikkusest nimede andmisega seoses kui ka nimede hoidmise tehnilistest lahendustest. Hierarhiliste andmete esitamine SQL-andmebaasides. Graafide esitamine SQL-andmebaasides. Infosüsteemi põhiolemite seisundite esitamine SQL-andmebaasides. Mõned failide salvestamise disainimustrid SQL-andmebaasi kasutavate andmebaasirakenduste jaoks. Mustrite teemaga seostub ka: Andmebaasi loogilise ja füüsilise disaini antimustrite esinemine mõnedes vaba tarkvara poolt kasutatavates SQL-andmebaasides. Lisaks sellele on tehtud lõputöid, kus mustreid pole kirja pandud, kuid kus on uuritud andmebaaside disaine ja tehtud nendega eksperimente. Mitme väite ühe andmeväärtusena esitamise eelised ja puudused SQL-andmebaasides. Mõned uuritavad disainid kasutavad JSON, JSONB või massiivitüüpi veergu. Lisan, et peale selle lõputöö kirjutamist on lisandunud PostgreSQLi arsenali jsonb_set funktsioon, mis muudab andmete muutmise lihtsamaks, st ei ole enam vaja tervet hierarhia väärtust uuesti andmebaasi kirjutada. Universaalne andmebaasi disain ja selle probleemid. Puuduvate andmete esitamine SQL-andmebaasides. Sisulise tähendusega võtmed vs. surrogaatvõtmed SQL-andmebaasides. Mõned võimalused ridade ajaloo säilitamiseks SQL-andmebaasides. Denormaliseerimise praktika uurimine ühe SQL-andmebaasi näitel. SQL-andmebaasides olevate andmebaasiobjektide nimetamine. Töös keskendutakse kitsendustele, kuid tehakse ka üdisemaid tähelepanekuid nimede andmise kohta. Andmebaasi optimeerimine ning selles toimuvate operatsioonide jõudluse analüüs ühe Oracle andmebaasi näitel. Päringu filtri predikaadi automaatne lihtsustamine kahe SQL-andmebaasisüsteemi näitel. Reapõhise ja veerupõhise andmete salvestamise võrdlus kahe SQL-andmebaasisüsteemi näitel. Vaadete mõju päringute täitmisplaanide koostamisele kahe andmebaasisüsteemi näitel. Isikute nime alusel otsimise erinevad võimalused PostgreSQLis. Andmebaasis kirjutamise skeemi ja JSON dokumentide kasutamise mõju PostgreSQL ja MongoDB andmebaasirakenduste loomisele. **Märksõnad:** bakalureusetöö, magistritöö, teemad, eesti keel ## Küsimus: Kas olemasolevate "päriselu" SQL-andmebaaside disaini kvaliteet on hea? **Vastus:** Selliseid andmebaase on loodud nii palju, et üldistavalt kõigi kohta midagi öelda on võimatu. Saan öelda, et andmebaasides, mida olen ise lähemalt uurinud, mida on uurinud minu juhendatavad üliõpilased või mida on uuritud avaldatud teadustöödes, leidub kahjuks palju probleeme.Järgnevaga tahan ma öelda, et Te saate, võite ja isegi peate tegema paremini! Hästi kavandatud andmebaasi on palju lihtsam ja mugavam kasutada kui halvasti kavandatud andmebaasi. Hästi kavandatud andmebaasile on lihtsam ja mugavam luua andmebaasirakendust kui halvasti kavandatud andmebaasile.Toon järgnevalt näiteid.Magistritöös "E-kaubandusettevõtte X andmekvaliteedi analüüs ja parendamine" uuriti e-kaubanduse ettevõtte andmebaasi andmekvaliteedi seisukohast, pakuti välja protseduur selle püsivaks parandamiseks ning viidi parandusi ka ellu. Ettevõtte e-poe andmebaas põhineb maailmas ülipopulaarsel sisuhaldusprogrammil WordPress ning pistikprogrammil WooCommerce ja teistel väiksematel pistikprogrammidel. Autor kirjutab, et "W3techs andmete järgi on 2022. aasta oktoobrikuu seisuga sisuhaldussüsteemi WordPressi turuosa sisuhaldussüsteemide hulgas 64.2%. 43% maailma veebisaitidest on loodud WordPressi põhjal. WordPressil põhineva WooCommerce tarkvaral on suurim – 29% suurune – turuosa e-poe tarkvarade hulgas." Teiste sõnadega - kõik leitud andmebaasi disaini probleemid ja nende esinemise võimalikud tagajärjed kummitavad kõiki nende süsteemide kasutajaid, keda on palju. Autor toob välja kuus erinevat tüüpi probleemi (vt jaotis 9.1), kusjuures igal probleemi tüübil on hulk erinevaid alamprobleeme e märke nende probleemide esinemisest.Bakalaureusetöös "Ettevõttesisese tarkvara täiendamine - kasutajaliidese ja andmebaasi kavandamine ning sobivuse hindamine" täiendati tuntud ettevõtte poolt enda tarbeks loodud tarkvara inimressursside planeerimise funktsionaalsusega. Töö üheks osaks oli olemasoleva andmebaasi dokumenteerimine (dokumentatsioon puudus) ja selle andmebaasi analüüsimine disainiprobleemide seisukohalt. Autorid leidsid 20 erinevat tüüpi probleemi (vt jaotis 4.2).Bakalaureusetöös "E-poe andmete migreerimine PostgreSQL andmebaasist Microsoft SQL Serveri andmebaasi" kanti e-poe tarkvara asendamise raames e-poe andmed PostgreSQL andmebaasist Microsoft (MS) SQL Serveri andmebaasi. Lähteandmebaas oli osa valmislahendusest ehk karbitootest ja sihtandmebaas oli ettevõtte enda arendajate kätetöö. Töö ühe tulemusena analüüsiti sihtandmebaasis olevat nelja tabelit, kuhu andmesiirde tulemusel andmeid üle kantakse. Autor leidis sihtandmebaasi tabelite disainis 20 erinevat tüüpi probleemi (vt jaotis 5.1). Töös dokumenteeriti ka lähteandmebaasi (karbitoote) andmebaas. Igaüks võib ise seda uurida, kuid ka seal on palju andmebaasi disaini probleeme.Bakalaureusetöös "Andmebaasi loogilise ja füüsilise disaini antimustrite esinemine mõnedes vaba tarkvara poolt kasutatavates SQL-andmebaasides" otsitakse andmebaasi disaini antimustrite esinemisi avatud lähtekoodiga rakenduste Postbooks (ettevõtte ressursside planeerimise süsteem; andmebaas tehtud PostgreSQLis) ja OpenEMR (arstipraksise haldustarkvara; andmebaas tehtud MySQLis) andmebaasidest. Autor leidis uuritud andmebaasides 12 erineva andmebaasi disaini antimustri esinemisi. Autor kirjutas: "Mõlema andmebaasi disain kannatab liigse denormaliseerimise, paralleelsete veergude, välisvõtmete ebapiisava deklareerimise ja klassifikaatorite tabelite puudumise tõttu.". Töös viidatakse M. Blaha 2001. aastal avaldatud uurimusele 35 päriselu andmebaasi disaini kvaliteedi kohta. Blaha leidis nendest andmebaasidest palju vigu nagu näiteks erinevat tüüpi kitsenduste puudumine. Lõputöö autor tõdeb: "Võib väita, et alates Blaha uurimuste avaldamisest on olukord mingil määral paranenud, aga mitte palju."Bakalaureusetöös "EE Tele2 müügiandmete andmetabelite kvaliteedikontroll ja dokumenteerimine" kontrolliti ja parandati Tele2 olulise müügiprogrammi poolt kasutatud andmetabelites olevate andmete kvaliteeti. Andmekvaliteedi probleeme oli palju. Lk 20 toodi autori poolt välja ka mõned andmebaasi disaini probleeme (kokku viis erinevat tüüpi probleemi). Paljud autori viidatavad andmekvaliteedi probleemid osutavad sellele, et süsteemis on ebapiisavalt realiseeritud andmete reeglitele vastavuse kontroll, sh ilmselt on andmebaasides palju deklaratiivseid kitsendusi puudu. Samuti esineb liigset andmete dubleerimist (sama info erinevates veergudes) ja puudub klassifikaatorite tabeleid.PostgreSQL andmebaaside disainivigade otsimise päringute abil tehtud uurimuste kohta kirjutatud teadusartiklites (Eessaar, 2021; Eessaar, 2022; Eessaar 2023) on uuritud nelja pika arenduse ajalooga ja endiselt aktiivselt kasutuses oleva rakenduse PostgreSQL andmebaasi. Kolm nendest rakendustest on avatud lähtekoodiga. Need programmid on FusionForge (avatud lähtekoodiga arenduse haldamise tarkvara; andmebaasis 206 baastabelit), LedgerSMB (avatud lähtekoodiga ettevõtte ressursside planeerimise tarkvara; andmebaasis 162 baastabelit), OTRS Community Edition (avatud lähtekoodiga lahendamist vajavate probleemide haldamise tarkvara; andmebaasis 116 baastabelit) ja Stansoft (finantsarvestuse tarkvara; andmebaasis 174 baastabelit). Eessaar (2021) leidis nendest andmebaasidest kokku 36 erinevat tüüpi probleemi seoses deklaratiivsete kitsendustega. Eessaar (2022) leidis nendest andmebaasidest kokku veel 31 erinevat tüüpi probleemi seoses andmebaasi kontseptuaalse (loogilise) skeemiga. Eessaar (2023) leidis 30 erinevat tüüpi probleemi seoses andmebaasiobjektide nimetamisega. Paljudel nendel probleemidel on veel alamprobleeme e märke nende probleemide esinemisest.Artiklis Documenting Database Usages and Schema Constraints in Database-Centric Applications analüüsisid autorid 3113 avatud lähtekoodiga andmebaasirakendust, mis suhtlevad andmebaasisüsteemiga JDBC draiveri vahendusel ja mille korral tuleb andmebaasi skeem luua SQL lausete käivitamise tulemusel, mitte ei looda skeemi automaatselt ORM vahendi poolt. Igal rakendusel oli üks või rohkem SQL faili. Autorid leidsid primaarvõtme deklaratsioone 5086 SQL failist. Primaarvõtmeid deklareeriti 725 rakenduse korral, mis on 23.29% kõigist vaadeldud rakendustest. Autorid leidsid välisvõtme deklaratsioone 2196 SQL failist. Välisvõtmeid deklareeriti 379 rakenduse korral, mis on 12.17% kõigist vaadeldud rakendustest. Mis lahendust autorid sellele probleemile pakkusid? Luua programm, mis analüüsib staatiliselt rakenduse lähtekoodi ja andmebaasi skeemi ning annab tulemuseks rakenduse lähtekoodi dokumentatsiooni selle kohta, millistes meetodites/operatsioonides jõustatakse milliseid piiranguid andmetele. Kui rakenduse lähtekood või andmebaasi skeem muutub, siis saab kohe genereerida parandatud dokumentatsiooni. Seotud tööde all viidatakse uuringutele, kuidas olemasolevas kitsendusteta andmebaasides olevate andmete analüüsimise kaudu leida tabelite kandidaatvõtmeid, välisvõtmeid ja muid piiranguid (assotsiatsioonireeglid - kui kehtib tingimus A, siis peab ka kehtima tingimus B).Nimetatud töödest leiab viiteid veel erinevatele teadusartiklitele, milles on uuritud olemasolevate SQL-andmebaaside disaini. Kõik need uuringud on leidnud palju probleeme. **Märksõnad:** Wordpress, WooCommerce ## Küsimus: Kas olemasolevates "päriselu" SQL-andmebaasides jõustatakse välisvõtme kitsendusi? **Vastus:** Mitte nii palju kui peaks.B. Karwini SQL-andmebaasi disaini antimustrite raamatu peatükis 5 (Keyless Entry) esitatakse antimuster Leave Out the Constraints, et andmebaasis puuduvad välisvõtme kitsendused.M. Blaha 2001. aasta artiklis A Retrospective on Industrial Database Reverse Engineering Projects-Part 2 uuris 35 pöördprojekteeritud andmebaasi. Ta tõdes, et vaid 10% andmebaasidest deklareerib välisvõtmeid ning isegi nendes, kus välisvõtmeid deklareeritakse, on osad puudu.Artiklis Managing Technical Debt in Database Schemas of Critical Software räägitakse andmebaasi tehnilisest võlast ja võla näitena kasutatakse välisvõtme kitsenduste puudumist andmebaasist. Autorid viitavad OSCAR Electronic Medical Record tarkvarale, mida kasutavad sajad Kanada tervishoiuasutused. Selle andmebaasis on üle 450 tabeli ja mõnes tabelis on üle tuhande veeru.  Autorid täheldasid, et suhteliselt palju välisvõtme kitsendusi on andmebaasist puudu ja andmebaasis on seega palju üksteisega sidumata tabeleid. Kasutatav andmebaasisüsteem toetab välisvõtme kitsenduste deklareerimist. Viidete terviklikkuse kontroll toimub enamasti rakenduses.Artiklis Feral Concurrency Control: An Empirical Investigation of Modern Application Integrity kirjeldatakse Ruby on Rails raamistikus loodud 67 avatud lähtekoodiga rakenduse uurimise tulemusi. Artiklis uuritakse unikaalsuse ja viidete terviklikkuse kitsenduste jõustamist rakenduse tasemel olukorras, kus andmeid muudab korraga mitu kasutajat. Stressitestil väga suure samaaegsete kasutajate arvuga (64) muutus rakenduse tasemel realiseeritud viidete terviklikkuse kontroll peaaegu väärtusetuks, sest andmebaasi jõudis väga palju viidete terviklikkust rikkuvaid andmeid. Samas, kui tabelites olid deklareeritud välisvõtme kitsendused, siis ei juhtunud seda kunagi.  Artikli järeldustes tõdeti: "Andmete samaaegse kasutamise reguleerimise lahenduste sisseehitamine rakendusraamistikesse või üksikutesse rakendustesse on kallis, veaohtlik ja raske ettevõtmine, mis eirab andmebaaside valdkonnas aastakümneid sellel suunal tehtud tööd. Kuigi see lähenemine on piisav, et tagada meie analüüsitud süsteemide puhul umbes 87% kitsenduste korrektne jõustamine, võib ülejäänute puhul andmete kontrollimine paljudes kaasaegsete ORMides viia kitsendustele mittevastavate andmete registreerimiseni." Bakalaureusetöös "Ettevõttesisese tarkvara täiendamine - kasutajaliidese ja andmebaasi kavandamine ning sobivuse hindamine" täiendati tuntud ettevõtte poolt enda tarbeks loodud tarkvara inimressursside planeerimise funktsionaalsusega. Töö üheks osaks oli olemasoleva andmebaasi dokumenteerimine (dokumentatsioon puudus) ja selle andmebaasi analüüsimine disainiprobleemide seisukohalt. Autorid leidsid 20 erinevat tüüpi probleemi (vt jaotis 4.2). Üks nendes probleemidest (vt jaotis 4.2.14) on mõned puuduvad välisvõtme kitsendused (st enamik nendest kitsendustest on siiski jõustatud).Bakalaureusetöös "Andmebaasi loogilise ja füüsilise disaini antimustrite esinemine mõnedes vaba tarkvara poolt kasutatavates SQL-andmebaasides" otsitakse andmebaasi disaini antimustrite esinemisi avatud lähtekoodiga rakenduste Postbooks (ettevõtte ressursside planeerimise süsteem; andmebaas tehtud PostgreSQLis) ja OpenEMR (arstipraksise haldustarkvara; andmebaas tehtud MySQLis) andmebaasidest. Autor leidis uuritud andmebaasides 12 erineva andmebaasi disaini antimustri esinemisi. Autor kirjutas xTuple Postbooks kohta: "Välisvõtmed on üldiselt deklareeritud, samas on palju kohti, kus oleks võinud kasutada välisvõtit." Samas OpenEMR andmebaasis välisvõtme kitsendused puudusid.Magistritöös "E-kaubandusettevõtte X andmekvaliteedi analüüs ja parendamine" oli eesmärgiks saavutada väikese e-kaubandusettevõtte andmekvaliteedi püsiv paranemine. Ettevõte peab e-poodi kasutades ülipopulaarset sisuhaldussüsteemi WordPress ja selle pistikprogrammi WooCommerce. Ettevõtte andmebaas oli realiseeritud MySQLis ja ja see moodustus WordPressi ning selle pistikprogrammide tabelitest. Ühelgi ettevõtte andmebaasi tabelil ei olnud välisvõtme kitsendusi. Autor kirjutas: "Andmebaasi 52 tabelist 39 põhinevad salvestumootoril MyISAM, mis ei toeta välisvõtmete kitsendusi. Ülejäänule 13-le andmebaasi tabelile oleks võimalik välisvõtme kitsendusi määrata."PostgreSQL andmebaaside disainivigade otsimise päringute abil tehtud uurimuste kohta kirjutatud teadusartiklites (Eessaar, 2021; Eessaar, 2022) on uuritud nelja pika arenduse ajalooga ja endiselt aktiivselt kasutuses oleva rakenduse PostgreSQL andmebaasi. Kolm nendest rakendustest on avatud lähtekoodiga. Need programmid on FusionForge (avatud lähtekoodiga arenduse haldamise tarkvara; andmebaasis 206 baastabelit), LedgerSMB (avatud lähtekoodiga ettevõtte ressursside planeerimise tarkvara; andmebaasis 162 baastabelit), OTRS Community Edition (avatud lähtekoodiga lahendamist vajavate probleemide haldamise tarkvara; andmebaasis 116 baastabelit) ja Stansoft (finantsarvestuse tarkvara; andmebaasis 174 baastabelit). Eessaar (2021) leidis, et Stansofti andmebaasis ei ole ühtegi välisvõtme kitsendust deklareeritud. Ülejäänud andmebaasides on välisvõtme kitsendusi deklareeritud, kuid uuring leidis, et kindlasti on paljud kitsendused deklareerimata. Näiteks on FusionForge andmebaasis 31.6% (65), OTRS andmebaasis 15.5% (18) ja LedgerSMB andmebaasis 4.9% (8) tabelitest sellised, mis on justkui saared - nendes ei ole ühtegi välisvõtme kitsendust ja nendele ei viita mitte ükski välisvõtme kitsendus. Olemasolevate unikaalsuse kitsenduste ja veerunimede alusel leiti, et FusionForge andmebaasis on 7.9% (87), Stansofti andmebaasis on 4.4% (84), OTRS andmebaasis on 3.7% (36) ja LedgerSMB andmebaasis on 3% (29) veergudest sellised, millel puudub välisvõtme kitsendus. Artiklis Documenting Database Usages and Schema Constraints in Database-Centric Applications analüüsisid autorid 3113 avatud lähtekoodiga andmebaasirakendust, mis suhtlevad andmebaasisüsteemiga JDBC draiveri vahendusel ja mille korral tuleb andmebaasi skeem luua SQL lausete käivitamise tulemusel, mitte ei looda skeemi automaatselt ORM vahendi poolt. Igal rakendusel oli üks või rohkem SQL faili. Autorid leidsid välisvõtme deklaratsioone 2196 SQL failist. Välisvõtmeid deklareeriti 379 rakenduse korral, mis on 12.17% kõigist vaadeldud rakendustest. Miks neid kitsendusi siis ei jõustata? Mõned põhjused. Andmebaasis juba kasutusel olevate lahenduste jäljendamine uute arendajate poolt. Soov realiseerida andmebaasi läbivalt ühes stiilis. Üldine käegalöömine – teised lasevad üle jala, mis siis minagi pingutan. MySQLi MyISAM salvestusmootor, mis oli MySQLis vaikimisi valik kuni 2009. aasta detsembrini ja on ühe valikuna kasutusel praeguseni, ei toeta välisvõtme kitsendusi. InnoDB salvestusmootor, mis on praegu vaikimisi valik, toetab välisvõtme kitsendusi. Välisvõtmed võivad mõnikord puududa ka vanast harjumusest ja teadmatusest uute võimaluste kohta. Artiklis Managing Technical Debt in Database Schemas of Critical Software nimetatakse üleminekut MyISAM salvestusmootorilt InnoDB salvestusmootorile, kui võimalikku põhjust, miks tervishoiutarkvara Oscar andmebaasis on suhteliselt palju välisvõtme kitsendusi puudu - salvestusmootori muutumisel ei muudetud andmebaasi skeemi. Internetiavarustes kohtab endiselt küsimusi, kas välisvõtme kitsendused halvendavad andmete muutmise operatsioonide töökiirust ja arvamusi, et halvendavad ja seega ei peaks neid deklareerima. Kes nii arvavad ei võta muidugi arvesse, et viidete terviklikkuse kontroll rakenduses nõuab päringuid andmebaasist ja kuidas see saaks olla eriliselt kiirem. Samuti ei arvesta niimoodi arvajad, et välisvõtme kitsendused garanteerivad andmebaasisüsteemi jaoks andmete vastavust viidete terviklikkuse reeglile ja võimaldavad selle kaudu andmebaasisüsteemil rakendada tabeli elimineerimise teisendust, mis on üks päringute optimeerimise meetod. Seega väga väike mõju andmete registreerimise kiirusele on igati sobiv hind, et hiljem oleksid päringud nende andmete põhjal kiiremad. Ütleksin, et välisvõtme kitsenduste puudumine on teatud maailmavaate (andmebaas on passiivne koht andmete hoidmiseks, kogu töö andmetega käigu rakenduses), arenduskultuuri ja arendusfilosoofia tunnuseks. Eelnimetatud Oscar tarkvara puhul viidatakse juhtarendajate rakendusekesksele maailmavaatele, kui põhjusele, miks viidete terviklikkuse kontroll selles süsteemis toimub suures osas rakenduse tasemel. **Märksõnad:** võõrvõti, välisvõti, foreign key, fk, deklaratiivne kitsendus, declarative constraint, Wordpress, WooCommerce ## Küsimus: Kas puhta koodi põhimõtted on olulised ka andmebaaside korral? **Vastus:** Jah on! O'Reilly digitaalse platvormi vahendusel pääsete Te ligi Robert C. Martini raamatule Clean Code (Kuidas kasutada O'Reilly digitaalset platvormi?). Selle raamatu ideed kehtivad ning on olulised ka andmebaaside ja infosüsteemide ainete jaoks. See raamat jagab juhiseid vastutustundlikule arendajale. Täpselt nii nagu vastutustundlik arendaja üritab luua võimalikult puhast rakenduse koodi, üritab ta ka luua puhast andmebaasikeele koodi ja puhtaid mudeleid. Üldine idee on täpselt sama! Suure tõenäosusega hakkate neid tehiseid ise tulevikus lugema. Või kui ei hakka ise, siis hakkab keegi teine. Puhast artefakti (tehist) on hea ja meeldiv lugeda, sellest saab kergesti aru ning kokkuvõttes on tehist tänu sellele lihtsam edasi arendada. Samal ajal "räpane" tehis võib küll oma hetke eesmärki täita (hetkel see "töötab" nagu vaja), aga halva arusaadavuse ning loetavuse tõttu on seda raske parandada ja edasi arendada. Sellised tehised vajavad refaktoreerimist. Refaktoreerimist vajavad kohad leiab üles halva lõhna järgi. Eaglesoni seadus ütleb, et kui vaatasite viimati enda kirjutatud koodi rohkem kui kuus kuud tagasi, siis arusaamise mõttes võib see kood olla ka kellegi teise kirjutatud – arusaamiseks/meeldetuletamiseks tuleb sama palju vaeva näha. Mõned ütlevad, et Eagleson oli optimist ja tegelik ajaperiood on palju lühem. Mida puhtam kood, seda lihtsam on aru saada, mida olete ise kunagi teinud. Mida puhtam tehis, seda lihtsam on Teil ja teistel sellest aru saada. Täpselt nagu on olemas halvasti lõhnav lähtekood, leidub ka: halvasti lõhnavaid arhitektuure, halvasti lõhnavaid disaine, halvasti lõhnavaid andmebaasi disaine (Sama raamat elektrooniliselt) ja halvasti lõhnavaid mudeleid. Mudelite halbadest lõhnadest annab ülevaate ka see bakalaureusetöö ja selle töö edasiarendusena loodud kataloog. Kui Te ei taga enda loodavate tehiste puhtust, siis Te kogute tehnilist võlga. Tehniline võlg tähendab, et tehise muutmiseks on vaja liigselt pingutada. Nagu me kõik inimeste elust teame, siis võlg võib kiiresti kasvada ja kontrolli alt väljuda. Laenu võtta (võlgu jääda), võib teadlikult - lootuses, et see tasub ennast ära, aga see on risk. Samamoodi, kui näiteks inimene kodu ei korista ja selle käest ära laseb, siis kui ükskord keegi külla tuleb või on vaja see maha müüa, siis kulub selle uuesti üleslöömiseks väga palju aega ja vaeva. Halvasti lõhnava mudeli illustratsiooniks on teatele lisatud ekraanipilt Enterprise Architect abil loodud modelleerimise projektist. Mudeli elemendid on seal süsteemitult segamini nagu puder ja kapsad ning mida suuremaks see projekt kasvab seda raskem oleks sealt vajalikku üles leida. **Märksõnad:** puhas kood, clean code ## Küsimus: Kas saaksite tuua mõne näite valesti valitud väljapikkustest ja selle põhjustatud probleemidest? **Vastus:** Valed valikud võivad põhjustada kannatusi, segadust, lisatööd ja mainekadu (süsteemi omanikule): https://reisile.postimees.ee/4484884/reisija-pidi-lisatasu-maksma-sest-tema-nimi-ei-mahtunud-lennupiletile. Antud näite korral oli isikunimede registreerimiseks mõeldud tekstiväljades lubatud maksimaalne märkide arv liiga väike. Andmebaasis võiks veergude eesnimi ja perenimi maksimaalne väljapikkus olla 50 märki. See võimaldaks registreerida ka pikemaid nimesid. Teatavasti on mõned isikunimed väga pikad. Kui arvestada väljapikkuste määramisel selliste nimedega, siis peaks nende veergude väljapikkus MS Accessi andmebaasis olema 255 märki (maksimaalne lubatud väljapikkus VARCHAR tüüpi veergude korral) ning andmebaasisüsteemides PostgreSQL ja Oracle võibolla isegi 1000 märki (sest seal pole 255 märgi piirangut nagu MS Accessis). Leian, et sellised väga suured väljapikkused pole siiski mõistlikud, sest: ülipikkade nimedega inimesi on väga vähe, neil on oma nimest ka lühivorm, liiga suur väljapikkus annaks kliendiks registreerijale võimaluse registreerida kahjulikku sisu nagu ründeskripti, kasutajaliideses tuleb sisestusvälja näidata suuremana kui valdava enamiku nimede puhul on vajalik. Leian, et oleks vale kasutada kõikide tekstitüüpi veergude puhul järjekindlalt maksimaalset võimalikkus väljapikkust või suurimat väärtust võimaldavat andmetüüpi ilma täiendavate kitsendusteta. Kui näiteks veerg perenimi on PostgreSQLis tüüpi Text ilma kitsenduseta, et maksimaalne väärtus selles veerus võib olla näiteks kuni 50 märki, siis see jätab skeemi lugejale (programmid, inimesed) vale mulje sellesse veergu oodatavatest andmetest. Rusikareegel: valige iga veeru jaoks selline andmetüüp + täiendavate kitsenduste komplekt, et kõik vajalikud väärtused saaksid sellesse veergu salvestatud, kuid suurim võimalik väärtus oleks võimalikult väike. **Märksõnad:** kitsendus, constraint, väljapikkus, isikunimi, isikunimed ## Küsimus: Kas saaksite tuua näite mõnest andmebaasis puuduvast kitsendusest, mis on tekitanud probleeme? **Vastus:** Hea näite kahe silma vahele jäänud kitsendusest toob Amazoni asutaja ja boss Jeff Bezos. Amazoni algusaastatel avastas ta sellest vea, mis lasi kliendil tellida negatiivse arvu raamatuid, mille järel kanti raha kliendi krediitkaardile. Hr Bezos viskas ühel videol nalja, et ilmselt tuli siis jääda ootama, kuni klient neile raamatud saadab. ## Küsimus: Kas sain aru õigesti, et iga klassifikaatori jaoks pole atribuutide definitsioonide tabelis vaja teha eraldi kirjeldust (et lihtsalt kui mõnel klassifikaatoril on olemas atribuut, mida teistel ei ole, siis lihtsalt täpsustan, millel klassifikaatoril on see olemas) ? **Vastus:** Vaatame näidet. Oletame, et olemi suhte diagrammis on sellised olemitüübid koos neid siduvate üldistustega:[Töötaja_seisundi_liik]-----------|>[Klassifikaator]<|---------[Töötaja_roll]Klassifikaatori atribuudid: kood, nimetusTöötaja rolli atribuut: kirjeldus Olemitüüpide definitsioonide tabelis on olemitüüpide Klassifikaator, Töötaja_seisundi_liik ja Töötaja_roll definitsioonid. Atribuutide definitsioonide tabelis on atribuutide Klassifikaator.kood, Klassifikaator.nimetus, Töötaja_roll.kirjeldus definitsioonid.Töötaja rollil ja töötaja seisundi liigil on pärimise kaudu ka atribuudid kood ning nimetus, kuid neid atribuutide definitsiooni tabelis eraldi välja ei tooda.Kui atribuutidele kood või nimetus kehtivad erinevate klassifikaatori alamtüüpide korral erinevad piirangud, siis tuleb need kirja panna vastavalt Klassifikaator.kood või Klassifikaator.nimetus definitsiooni. Näiteks piirang "Töötaja rolli kood peab olema täisarv, ning kõige väiksem võimalik väärtus on 100" pannakse kirja atribuudi Klassifikaator.kood definitsiooni. ## Küsimus: Kas see on tavapärane praktika koostada registrite vaheliste seoste puhul nn vahetabelid, ning kas on juhte, kus see pole vajalik? **Vastus:** Kui kontseptuaalses andmemudelis on mitu-mitmele seosetüüp, nagu näiteks:   [Protseduur]-0..*---------------0..*-[Protseduuri_kategooria]   , siis selle realiseerimiseks tekib SQL-andmebaasis vahetabel. See on kõige tavapärasem viis, kuidas sellist tüüpi seost realiseerida.   Kui kontseptuaalses andmemudelis on üks-mitmele seosetüüp, nagu näiteks   [Isik]-0..*-------------1-[Riik]   , siis tekib seosetüübi mitu-poolel oleva olemitüübi alusel tekkivasse tabelisse (antud juhul Isik) välisvõtme veerg ja kitsendus.   Mitu-mitmele seosetüübid on kontseptuaalses andmemudelis ülevaatamist vajav koht, sest väga võimalik, et selle taga peidab ennast eraldi olemitüüp koos täiendavate atribuutidega e lisainfo säilitamise vajadusega.   Seega näiteks selle asemel, et modelleerida:   [Töötaja]-0..*------0..*-[Töötaja_roll]   , oleks parem modelleerida   [Töötaja]-1------0..*-[Töötaja_rolli_omamine]-0..*------1-[Töötaja_roll]   ning olemitüübil Töötaja_rolli_omamine on atribuudid nagu alguse_aeg ja lõpu_aeg.   Mis puudutab seosetüübi alusel defineeritud olemitüüpi ja selle alusel tekkinud tabelit, siis see on valiku koht, kumba registrisse see paigutub. Paigutus tuleks otsustada selle järgi, millises funktsionaalses allsüsteemis hallatakse neid andmeid. Kui protseduuride kategooriate omamisi hallatakse protseduuride funktsionaalses allsüsteemis, siis kuuluks Protseduuri_kategooria_omamine protseduuride registrisse. Kui töötajate rolli omamisi hallatakse töötajate funktsionaalse allsüsteemi kaudu, siis kuuluks Töötaja_rolli_omamine töötajate registri alla. **Märksõnad:** kontseptuaalne andmemudel, erd, olemi-suhte diagramm, registrid, allsüsteemid, modelleerimine ## Küsimus: Kas SQL-andmebaasis saab jõustada deklaratiivsete kitsendustena assotisatsioonireegleid? **Vastus:** Jah saab. Vaatame konkreetset näidet. Oletame, et SQL-andmebaasis on tabel Kaup:Kaup(kauba_kood, hind, on_aktiivne)Primaarvõti(kauba_kood)Oletame, et kehtib reegel: Kui kaup on aktiivne, siis selle hind peab olema registreeritud."kaup on aktiivne" ja "hind peab olema registreeritud" on tingimused.Tähistame neid tähtedega P ja Q. Reegel "Kui kaup on aktiivne, siis selle hind peab olema registreeritud" on assotsiatsioonireegel (association rule). See reegel ütleb, et kui kehtib tingimus P, siis peab kehtima ka tingimus Q.Selle saab üldkujul kirja panna P=>Q => on implikatsiooni operaator. Sellist operaatorit SQL keeles kasutada ei saa, küll aga saab kasutada loogikaoperaatoreid AND, OR ja NOT. P=>Q on loogiliselt samaväärne kui NOT (P) OR QSeda, et need on loogiliselt samaväärsed, näitab lisatud failis olev loogikatabel e tõeväärtustabel. Sellises tabelis esitatakse loogikafunktsiooni kõik võimalikud väljundväärtused.  Seega saaks andmebaasis tabeli Kaup luua CHECK kitsenduse:CHECK(NOT (on_aktiivne=TRUE) OR hind IS NOT NULL)Andmete registreerimine ebaõnnestub vaid juhul, kui esimene tingimus (on_aktiivne=TRUE) on täidetud ja teine tingimus (hind IS NOT NULL) ei ole täidetud. Kõikidel ülejäänud juhtudel registreerimine õnnestub. **Märksõnad:** assotsiatsioonireegel, implikatsioon, tingimuslause ## Küsimus: Kas töövihiku järgi projekti tehes (X=teenus) peaks lisama kasutusjuhtude mudelisse kasutusjuhud teenuste broneerimise kohta? **Vastus:** EI! See on õige, et kliendid võiksid saada teenuse tarbimiseks aja kinni panna (teenuse broneerida). Infosüsteemi kui terviku seisukohalt on see vajalik funktsionaalsus. Mõelge sellele, millised oleksid võimalikud broneerimisega seotud kasutusjuhud. Broneeri teenus (Klient) Vaata oma broneeringuid (Klient) Tühista oma broneering (Klient) Broneeri teenus (Broneeringute haldur) (võib registreerida mistahes kliendi broneeringu) Vaata kõiki broneeringuid (Broneeringute haldur) (võib vaadata mistahes kliendi broneeringut) Tühista broneering (Broneeringute haldur) (võib tühistada mistahes kliendi broneeringu) Teavita broneeringuga kliente (Broneeringute haldur) (erakorralise teate saatmine ühele või mitmele kliendile) Vaata broneeringute kokkuvõtet (Juhataja) ... Nagu näete, siis kasutusjuhte on palju. Küsimus on, millise funktsionaalse allsüsteemi alla need koondada. Kui "Teenuste funktsionaalse allsüsteemi" alla, siis selle kasutusjuhtude arv vähemalt kahekordistuks ja see allsüsteem kasvaks liiga suureks. Miks see on halb? Samal põhjusel miks liiga suure meetodite arvuga klassi tegemine (tuntakse nime all "plekk" või "jumal-klass"). Sellisest allsüsteemist oleks raskem aru saada, seda oleks raskem arendada ja arenduse tulemusi taaskasutada. Seetõttu oleks õige paigutada eelnimetatud kasutusjuhud "Broneeringute funktsionaalse allsüsteemi" alla (vastab põhiobjektile Broneering). Seda allsüsteemi Te projektis detailselt ei käsitle. Seega pole ka vaja vastavaid kasutusjuhte kirja panna. ## Küsimus: Kas tühja stringi esinemise keelamine ja NOT NULL kitsendus on üks ja sama asi? **Vastus:** Ei ole! Tühi string on väärtus (kuigi väga lühike).NULL on tähis, et väärtust ei ole.NOT NULL veergu saab seega tühja stringi panna, sest see täidab tingimuse, et väljas peab väärtus olema.Kui näiteks soovida keelata veerus perenimi tühjad stringid, siis tuleb lisada CHECK kitsendusCHECK(perenimi<>'')MS Accessi graafilise kasutajaliidese kaudu määratav Allow Zero Length = No on selle alternatiiv.Tühja stringi ja NULLi võib kasutada selleks, et registreerida erinevad põhjused, miks väärtus puudub. Näiteks kui vastaval olemil ei ole sellist atribuuti (näiteks organisatsiooni perenimi), siis kasutatakse tühja stringi aga kui olemil on atribuut, aga selle väärtus pole teada, siis kasutatakse NULLi. Samas leian, et tühjade stringide lubamine tekitab asjatut segadust. Tabelid tuleks kavandada nii, et kui olemil ei ole mingit atribuuti, siis vastavas tabelis pole ka sellist veergu.CREATE TABLE Isik(isik_id INTEGER PRIMARY KEY,perenimi VARCHAR(50));INSERT INTO Isik (isik_id, perenimi) VALUES (1, '');INSERT INTO Isik (isik_id, perenimi) VALUES (2, NULL);Ülesanne: Leia isikud, kelle perenimi puudub.SELECT * FROM Isik WHERE perenimi=''; --tulemuses üks ridaSELECT * FROM Isik WHERE perenimi IS NULL; --tulemuses üks ridaSeega parem on nii - kui nime ei ole, siis NULL, kui on, siis midagi muud kui tühi string. Siin on võimalik neid lauseid viie andmebaasisüsteemi põhjal testida.NB! Andmebaasisüsteem Oracle käitub SQL standardis ettenähtust ning teistest andmebaasisüsteemidest erinevalt. Nimelt teeb Oracle automaatse asenduse ''=>NULL. Seega korrates eelnevaid lauseid Oracles (testitud nii 12c Enterprise Edition kui 23ai Free) on tulemus:SELECT * FROM Isik WHERE perenimi=''; --tulemuses null ridaSELECT * FROM Isik WHERE perenimi IS NULL; --tulemuses kaks ridaKui Oracles käivitada järgnev kood, siis rea lisamisel tekib NOT NULL kitsenduse viga.CREATE TABLE Isik(isik_id NUMBER(10) PRIMARY KEY,perenimi VARCHAR2(50) NOT NULL);INSERT INTO Isik (isik_id, perenimi) VALUES (1, '');Tulemus: SQL Error: ORA-01400: cannot insert NULL into ("SYSTEM"."ISIK"."PERENIMI") ## Küsimus: Kas välisteks tegutsejateks võivad olla teised infosüsteemid? **Vastus:** Süsteemi välisteks tegutsejateks võivad olla teised infosüsteemid. Selle näiteks majutusasutuste valdkonnas on siseministri poolt 2017. aasta veebruaris esitatud plaan luua majutusasutuste külastajate register. Sellesse registrisse jõuaks automaatselt info kõigi Eesti majutusasutuste külastajate kohta. Registris toimuksid automaatsed päringud, mis otsivad riigile huvipakkuvaid isikuid (nt tagaotsitavaid). Kui vasteid ei saada, kustutakse inimese info omakorda ööpäeva jooksul. Plaani elluviimisega jätkati 2019. aasta sügisel, kui esitati turismiseaduse muutmise eelnõu, mis sellist registreerimist ette näeb. Eelnõu seletuskiri ütleb, et "Eelnõuga ei laiendata registreerimisel esitatavate majutusteenuse kasutajate andmete koosseisu. Isikuandmete kaitse nõuete paremaks täitmiseks luuakse majutusteenuse kasutajate andmekogu." "Tänavu (2019) üheksa kuuga ööbis Eesti majutusettevõtetes pea 3 miljonit külastajat, nende passiandmed kirjutati üles ja tõsteti hotellis kuhugi seifi. Kehtinuks uue seaduseelnõuga plaanitavad muudatused, oleks politsei- ja piirivalveametil juba 3 miljonit sissekannet andmebaasis, mida saaks automaatselt võrrelda 12 andmekogu sisuga, alates töölubade ja Interpoli registrist ja lõpetades kehtivate isikutunnistuste omaga." (artikkel) Võimalik lahendus on, et iga majutusasutuse infosüsteem realiseerib klientide andmeid pakkuva veebiteenuse. Majutusasutuste külastajate registri tarkvara pöördub regulaarselt selle veebiteenuse poole ja "tõmbab" majutusasutuste andmebaasidest külastajate andmeid kesksesse registrisse (näiteks JSON või XML dokumendina). Sellisel juhul on majutusasutuste külastajate register majutusasutuse infosüsteemi üks väline tegutseja. Eesti riigi infosüsteemi moodustavad infosüsteemid vahetavad omavahel infot X-tee andmevahetuskihi kaudu. X-tee mustrikataloogis kirjeldatakse sellist andmete "tõmbamisel" põhinevat lähenemist mustris PM1: andmete päringu teenus. Andmeid omav infosüsteem on teenuse osutaja. Andmeid omaval infosüsteemil on päringutele vastamise teenus, mida andmeid vajav infosüsteem välja kutsub. Võimalik on ka see, et majutusasutuse infosüsteemi tarkvara võtab ise regulaarselt külastajate registri tarkvaraga ühendust ja "lükkab" sinna külastajate andmeid. Sellisel juhul ei ole majutusasutuste külastajate register majutusasutuse infosüsteemi üks väline tegutseja. Eesti riigi infosüsteemi moodustavad infosüsteemid vahetavad omavahel infot X-tee andmevahetuskihi kaudu. X-tee mustrikataloogis kirjeldatakse sellist andmete "lükkamisel" põhinevat lähenemist mustris PM2: andmete saatmise teenus. Andmeid omav infosüsteem on teenuse tarbija. Andmeid vajaval infosüsteemil on andmete vastuvõtu teenus, mida andmeid omav infosüsteem välja kutsub. Pange selle uudise puhul tähele ka seda, et seadustega võivad olla ette nähtud reeglid, milliseid andmeid võib/peab kui kaua säilitama. Kui hakkate mistahes infosüsteemis mõtlema funktsionaalsusele "Kustuta X", siis tuleb selliste nõuetega arvestada. "Kuigi automaatsest registrist kustuvad inimese andmed üldjuhul ööpäevaga, siis majutusasutused ise peavad plaani kohaselt inimeste infot hoidma alles kaks aastat, et ametkonnad saaks vajadusel seda hiljem kontrollida." Rääkides keskse külastajate registri tehnilisest realisatsioonist, siis järgnev pakub välja ühe võimaliku lahenduse. Andmebaasisüsteem PostgreSQL toetab JSON ja JSONB andmetüüpe (tabelites võivad olla seda tüüpi veerud ja nendes veergudes võivad olla JSON dokumendid). Külastajate andmed laetakse veebiteenuse poolt alla ja salvestatakse dokumentidena PostgreSQL andmebaasi. Nende andmete põhjal tehakse päringuid. Kui leitakse huvipakkuv isik, siis tema andmed kirjutatakse eraldi tabelisse, kus võibolla ei ole enam JSON/JSONB tüüpi veergu, vaid selle asemel, on isiku atribuutidele vastavad andmed (eesnimi, perenimi, isikukood, ...) eraldi veergudes. Huvipakkuvate isikute otsimiseks, nende andmete eraldi tabelisse tõstmiseks ja ülevaadatud külastajate andmete kustutamiseks luuakse andmebaasis funktsioonid. Neid funktsioone on vaja regulaarselt käivitada. Kui soovite teha regulaarselt mingit tööd PostgreSQL andmebaasis (näiteks käivitada regulaarselt funktsiooni), siis tuleb selleks kasutada operatsioonisüsteemi vahendeid. Näiteks UNIXI-laadsetes operatsioonisüsteemides saab kasutada deemonit Cron, mis vastutab automaatsete operatsioonide eest. "Deemon on tagaplaanil jooksev programm, mis teostab teatud ettemääratud operatsioone kindlate ajavahemike tagant või vastuseks mingitele sündmustele." (Vallaste, http://www.vallaste.ee/) Majutusasutuse infosüsteemi klientide funktsionaalses allsüsteemi kirjelduses oleks kasutusjuht "Lae alla külastajate andmed", mis on seotud tegutsejaga Majutusasutuste külastajate register. ## Küsimus: Kuidas eristada sisulisi ja administratiivseid allsüsteeme? **Vastus:** Funktsionaalsed allsüsteemid ning registrid liigituvad sisulisteks ja administratiivseteks. Fowler (2010) liigitab tarkvara tarbetarkvaraks (utility software) ja strateegilist eelist andvaks tarkvaraks (strategic software). Fowler hindab, et 95% tarkvarast on tarbetarkvara ja 5% strateegilist eelist andev tarkvara. Fowler võrdleb tarbetarkvara torustikuga - see peab olema olemas ja veatult töötama. Kuni probleeme ei ole, siis kasutajat ei huvita kus see on ja kuidas see seda teeb. Strateegiline tarkvara aitab ettevõttel edendada oma äri ja jõuda uutele turgudele. Selline tarkvara ja selle toetatav äri peaks andma organisatsioonile võistlejate ees eelise, tehes näiteks midagi paremini kui teised sama valdkonna ettevõtted teevad. Selle tarkvaraga seoses peaks toimuma innovatsioon. Leian, et administratiivsed allsüsteemid vastavad tarbetarkvarale ning sisulised allsüsteemid strateegilisele tarkvarale. ## Küsimus: Kuidas jõustada PostgreSQL andmebaasis kitsendus, et tabeli veerus hoitakse rahasummat eurodes? **Vastus:** Kitsendust eurode kohta ei saa ega pea andmebaasi lisama! Oletame, et andmebaasis on tabel:Amet (amet_kood, nimetus, min_palk)Primaarvõti (amet_kood)Alternatiivvõti(nimetus)Veerus min_palk on ametikohal makstav minimaalne palk eurodes. Eeldame, et selles veerus olevad arvud esitavad palka eurodes - see on see, kuidas veerus olevaid andmeid interpreteeritakse ja andmebaasi kasutajale peab selle selgeks tegema. Veerg min_palk peaks olema tüüpi DECIMAL(täpsus,skaala) e NUMERIC(täpsus, skaala) ning ära tuleks määrata täpsus (precision) - kui mitu numbrikohta on väärtuses lubatud ja skaala (scale) - kui mitu numbrikohta on peale koma. Näiteks kui veerg min_palk oleks tüüpi DECIMAL(5,2), siis suurim võimalik minimaalne palk, mida saaks registreerida oleks 999.99 (viis numbrikohta, kaks kohta peale koma).Kui soovime mõne päringu tulemuses näha palka nii, et seal on ka juures euro sümbol, siis tuleb päringu (SELECT lause) tulemuses palga väärtust formaatida. Selleks saab kasutada näiteks to_char funktsiooni.SELECT amet_kood, nimetus, TO_CHAR(min_palk, '99999D99l') AS min_palk_formaaditudFROM AmetORDER BY amet_kood; "l" to_char mustris tähendab, et tuleks kasutada serveri lokaliseeringuga määratud valuutat. Kui päringu tulemuses on näiteks dollari sümbolid, siis saaks teha hoopis sellise päringu. || on stringide ühendamise e konkateneerimise operaator. SELECT amet_kood, nimetus, TO_CHAR(min_palk, '99999D99') || ' EUR' AS min_palk_formaaditudFROM AmetORDER BY amet_kood; **Märksõnad:** euro, valuuta, kitsendus, constraint, konkatenatsioon ## Küsimus: Kuidas määrata kindlaks, millises andmekesksesse allsüsteemi e registrisse (andmebaasi loogilisse alamosasse) mingid andmed kuuluvad? **Vastus:** Kui kasutada lähenemist, et iga registri kohta on infosüsteemi äriarhitektuuris ette nähtud eraldi funktsionaalne allsüsteem, mille kaudu toimub registris olevate andmete haldamine (lugemine ja muutmine), siis tuleks olemitüüp/tabel paigutada registrisse, millele vastava funktsionaalse allsüsteemi kaudu toimub selle andmete haldamine.Oletame, et süsteemis oleks vaja pidada arvet klientide, sadamakaide ning klientide poolt sadamakaide rentimise kohta. Millises registris peaksid olema andmed sadamakaide rentimiste kohta?Kolm valikut: Klientide register Juhul, kui kaide rentimiste andmeid hallatakse klientide funktsionaalse allsüsteemi kaudu. See tähendab, et kaide rentimisega seotud funktsionaalsus kirjeldatakse klientide funktsionaalse allsüsteemi all ning see funktsionaalsus realiseeritakse klientide halduse rakenduses/äpis. Kaide register Juhul, kui kaide rentimiste andmeid hallatakse kaide funktsionaalse allsüsteemi kaudu. See tähendab, et kaide rentimisega seotud funktsionaalsus kirjeldatakse kaide funktsionaalse allsüsteemi all ning see funktsionaalsus realiseeritakse kaide halduse rakenduses/äpis. Kaide rentimiste register Antud juhul arvatavasti parim valik. Kaide rentimistel on infosüsteemi seisukohast huvipakkuv elutsükkel (rentimiste võimalikud seisundid oleksid näiteks tasumata, tasutud, lõpetatud, tühistatud, ...) ja seetõttu oleks süsteemi äriarhitektuuri osaks ka kaide rentimiste funktsionaalne allsüsteem, mis haldab kaide rentimiste registris olevaid andmeid. ## Küsimus: Kuidas salvestada PostgreSQL andmebaasis tabelite muudatuste ajalugu? Lahendus peaks olema üldine, mitte ühe konkreetse tabeli spetsiifiline. Kas siin artiklis toodud lahendus on mõistlik? https://www.cybertec-postgresql.com/en/tracking-changes-in-postgresql/ **Vastus:** Andmebaasi kasutamise (sh andmemuudatuste jälgimist) nimetatakse auditeerimiseks (auditing). Andmebaasisüsteemid pakuvad sageli selleks erinevaid sisseehitatud võimalusi kuid kui neid ei ole või need pole sellised nagu vaja, siis trigerid on andmemuudatuste logimise realiseerimiseks sobilik valik. Artiklis pakutud lahendus on kahtlemata võimalik. Enne selle kasutusele võttu lugege palun siiski järgnevat.Trigeripõhiste lahenduste üldine probleem (mistahes andmebaasisüsteemis) Kuna trigereid ei saa panna reageerima SELECT sündmustele, siis ei saa trigerite abil logida andmete vaatamist. Trigeripõhise lahenduse üldine probleem PostgreSQLis Kui andmemuudatus ebaõnnestub, siis tühistatakse andmebaasisüsteemi poolt kõik vastavast transaktsioonis tehtud andmemuudatused ja kõik nende poolt algatatud muudatused (sh käivitunud trigerite tehtud muudatused). Seega ei saa trigerite abil logida ebaõnnestunud muudatusi. Oracles saaks näiteks andmemuudatuse logimise realiseerida autonoomse transaktsioonina, mis tähendab, et logi kirjutamine õnnestub isegi siis, kui muudatus, mis logi kirjutamise algatas, ebaõnnestub ja rullitakse tagasi. Konkreetse trigeripõhise lahenduse probleemid/nõrkused/mõttekohad. Triger ei logi kõikide ridade kiiret kustutamist (TRUNCATE operatsioon). Kui UPDATE lause reas midagi ei muuda, siis operatsiooni toimumise kohta registreeritakse kirje ikkagi. UPDATE lause puhul logitakse ka need väljad, milles andmed ei muutunud. Tuleks kaaluda, kas veergude old_val ja new_val puhul kasutada tüüpi JSON või JSONB (erinevus on väärtuse sisemises esitusviisis), arvestades kummagi eeliseid ja puuduseis. PostgreSQL juhendmaterjalides on igatahes öeldud: "In general, most applications should prefer to store JSON data as jsonb, unless there are quite specialized needs, such as legacy assumptions about ordering of object keys." Logitabeli maht läheb kiiresti väga suureks ja võiks mõelda selle sektsioonideks jagamisele (partitioning). SIIN kirjeldatakse veel erinevaid võimalusi PostgreSQLi andmebaasis toimuvate andmekäitluse operatsioonide logimiseks. Juttu on: andmebaasisüsteemi sisseehitatud logimise funktsionaalsusest (log_statement = all), mis tuleb administraatori poolt sisse lülitata, universaalsest trigeripõhisest lahendusest (Audit trigger 91plus), Küsimuses pakutud lahendusest eristab seda see, et saab logida TRUNCATE operatsioonide tulemusi, logitakse rohkem metaandmeid muudatuse kohta ja UPDATE operatsiooni puhul logitakse ainult muutunud väärtuseid. pgAudit laiendusest. Veel üheks lahenduseks ajalooliste andmete hoidmisel oleks disainida tabelid nii, et nendes saaks hoida ka ajaloolisi andmeväärtuseid. Sellist lähenemist pakub näiteks ankurmodelleerimine (siin on veidi eesti keeles). Põhimõtteliselt tekib selle kasutamisel iga olemitüübi atribuudi kohta eraldi tabel. Tabelite mugavamaks kasutamiseks luuakse vaated ja funktsioonid. Arendustööd aitab automatiseerida modelleerimiskeskkond, kus on muuhulgas ka koodigeneraator PostgreSQL jaoks (arendatud ühe meie ülikooli magistritöö tulemusena). Kui kartust tekitab see, et suure hulga tabelite ühendamine vähendab jõudlust, siis seda aitab kiirendada tabelite elimineerimise teisendus, mida oskab teha ka PostgreSQL. Selles lõputöös (on küll Oracle näitel, aga siiski) katsetatud ankurmodelleerimise andmebaasi.Selles magistritöös kirjeldatakse veel  ühte võimalust andmemuudatuste ajaloo säilitamiseks ja realiseeritakse märkimisväärne osa seda toetavast taristust (operaatorid, vaated, trigerid) PostgreSQL jaoks. ## Küsimus: Kui Enterprise Architect (EA) ei luba töötada DDLenhace-ga ja mudeli disain tuleb teha DDL-ga, siis kuidas kontrollida millised parameetrid peavad olema kohustuslikud ja millised PK või FK ning millistel parameetritel peab olema vaikimisi väärtus? **Vastus:** Atribuutide alusel tekkivate veergude kohustuslikkus Atribuutide definitsiooni tabelis (jaotises 2.2.1 - peale olemi-suhte diagramme ja olemitüüpide definitsioone) peab iga atribuudi puhul kitsenduste osasse kirjutama, kui see on kohustuslik, st selle väärtus peab olema alati määratud - {Registreerimine on kohustuslik.} Lisaks tuleb Enterprise Architecti abil tehtud olemi-suhte diagrammides ära näidata, millised atribuudid on kohustuslikud (võimsustik (multiplicity) 1) ja millised mittekohustuslikud (võimsustik 0..1). Kui teisendate kontseptuaalse andmemudeli SQL-andmebaasi disaini mudeliks, siis laias laastus vastab igale atribuudile eraldi tabeli veerg. Kui atribuut on kohustuslik, siis vastavale veerule tuleb deklareerida NOT NULL kitsendus. Kui atribuut ei ole kohustuslik, siis seda kitsendust ei ole. Kontseptuaalse andmemudeli mallis olevatest atribuutidest on mittekohustuslikud: Isik.eesnimi Isik.perenimi Isik.elukoht Amet.kirjeldus Ülejäänud atribuudid on kohustuslikud (st vastavatel veergudel peab olema NOT NULL). Võimalik, et lisatud X atribuutide hulgas on ka mõni mittekohustuslik (nt kirjeldus või kommentaar), kuid see valik on juba Teie teha. Seosetüüpide alusel tekkivate veergude kohustuslikkus Mis puudutab välisvõtme veergude kohustuslikkust, siis see sõltub seosetüübi võimsustikest (multiplicity). Näide: [Riik]-1-+isikukoodi riik-----------0..*-[Isik] Iga isik on seotud täpselt ühe isikukoodi riigiga. Järelikult tabelisse Isik tekkival välisvõtme veerul riik_kood peab olema NOT NULL kitsendus. [Riik]-0..1-+isikukoodi riik-----------0..*-[Isik] Iga isik on seotud nulli või ühe isikukoodi riigiga. Järelikult tabelisse Isik tekkiv välisvõtme veerg riik_kood võib lubada NULLe. Malli järgi projekti tehes peaks kõikidele välisvõtme veergudele deklareerima NOT NULL kitsenduse. Vaikimisi väärtused Vaikimisi väärtused on mugavusvahend, juhuks, kui paljudes/kõigis uutes ridades on ühesugune väärtus või ühesugusel viisil leitav väärtus. Vaikimisi väärtus ei ole kitsendus - sellest saab alati jõuga üle sõita. Malli järgi tehtavas projektis peaksid olema järgmised vaikimisi väärtused. Välisvõtme veergudel, mis viitavad seisundiklassifikaatorite tabelitele (Isiku_seisundi_liik, Tootaja_seisundi_liik, Kliendi_seisundi_liik, X_seisundi_liik) - väärtus, mis näitab esimesena saadava seisundi koodi. Näiteks X korral on selleks seisundile "ootel" vastav kood, sest seisundidiagrammi alusel (vt jaotis 2.2.3) läheb iga X kõigepealt seisundisse "ootel". Need vaikimisi väärtused peavad olema tabelites Isik, Tootaja, Klient, X. Isik.reg_aeg ja X.reg_aeg - avaldis, mille poole pöördumisel tagastatakse hetke kuupäev ja kellaaeg (näiteks MS Accessis Now()). Klient.on_nous_tylitamisega - FALSE - tulenevalt vaikimisi andmekaitse põhimõttest. Primaarvõtmed Hästi kavandatud SQL-andmebaasi tabelis tuleb jõustada kõik kandidaatvõtmed - üks primaarvõtmena (PRIMARY KEY kitsendus) ülejäänud alternatiivvõtmetena (UNIQUE+NOT NULL kitsendus). Kontseptuaalses andmemudelis tuleb atribuutide definitsiooni kirja panna, kui mingi atribuut või atribuutide kombinatsioon on unikaalne identifikaator. Primaarvõti tuleb kas jõustada ühele nendest vastavate veergude alusel või defineerida surrogaatvõti. Surrogaatvõtme väärtused on süsteemi poolt genereeritud unikaalsed täisarvud, mida kasutatakse olemitele viitamiseks ainult tarkvarasüsteemi siseselt, mitte inimeste maailmas. Malli alusel tehtavas projektis on surrogaatvõti mõistlik ainult tabelis Isik - (isik_id). Ülejäänud tabelites saab valida sisulise võtme - näiteks tabelis Riik (riik_kood), tabelis X (X_kood) jne. Tabelites Klient ja Tootaja peaks primaarvõti (isik_id) kokku langema välisvõtmega, mis viitab tabelile Isik. Välisvõtmed Üks-mitmele seosetüübi korral tekib välisvõti mitu poolel olevasse tabelisse. [Riik]-1-+isikukoodi riik-----------0..*-[Isik] - välisvõti on tabelis Isik. Mitu-mitmele seosetüübi korral tekib vahetabel koos kahe välisvõtmega. **Märksõnad:** teisendus, mudeliteisendus, DDLEnhanched, DDL_enhanced ## Küsimus: Kui tabelis Riik on (nimetus) alternatiivvõti, siis miks ei piisa selle jõustamiseks UNIQUE kitsendusest? Miks on vaja veerule nimetus ka NOT NULL kitsendust? **Vastus:** Hästi kavandatud tabelis peaks olema üks või rohkem kandidaatvõtit. Kandidaatvõtme väärtus + kandidaatvõtme veergude nimed + tabeli nimi on loogiline aadress, mille järgi andmebaasist tabeli rida üles leida. Kui aadressi pole või see on väärtuste puudumise tõttu mittetäielik, siis rida leida ei saa.Tüüpiliselt valitakse üks kandidaatvõti primaarvõtmeks e esmasvõtmeks, ülejäänud on alternatiivsed võtmed e alternatiivvõtmed.Primaarvõtme väärtus peab SQL reeglite järgi olema alati registreeritud. Isegi kui primaarvõtme veerule ei deklareerita NOT NULL, siis kontrollib andmebaasisüsteem, et igas reas oleks primaarvõtme väärtus olemas. Alternatiivvõti pole millegi poolest halvem. See oli võrdväärne kandidaat primaarvõtmeks, aga jäi valimata. Unikaalsuse tagamiseks on veerule vaja UNIQUE. Kuna vaikimisi on SQLis kõik mitte-primaarvõtme veerud valikulised (lubavad NULLe), siis on vaja veerule ka NOT NULL.Teiste sõnadega, kui süsteemianalüüs oleks näidanud, et mõnel riigil võib nimetus puududa, siis poleks (nimetus) selles tabelis kandidaatvõti ega ka alternatiivvõti. ## Küsimus: Kui teha töövihiku järgi projekti, siis millistele veergudele oleks mõistlik lisada vaikimisi väärtus? **Vastus:** Vaikimisi väärtused võiks lisada: Isik.isiku_seisundi_liik_kood - välisvõtme veerg; seisund, millesse isik läheb registreerimisel (elus) Isik.reg_aeg - hetke kuupäev + kellaaeg Isik.viimase_muutm_aeg - hetke kuupäev + kellaaeg Isikuandmete muutmisel jääb registreerimisaeg samaks, kuid viimase muutmise aeg muutub Kuna viimase muutmise aeg lisatakse juba rea lisamisel, siis saab veeru deklareerida kohustuslikuks ja vähendada andmebaasis seega NULLide kasutamist Klient.on_nõus_tülitamisega - vaikimisi andmekaitse põhimõttest lähtuvalt FALSE - see nõue on ka töövihikus Klient.kliendi_seisundi_liik_kood - välisvõtme veerg; seisund, millesse klient läheb registreerimisel (valige ise) Töötaja. töötaja_seisundi_liik_kood - välisvõtme veerg; seisund, millesse töötaja läheb registreerimisel (valige ise) X.x_seisundi_liik_kood - välisvõtme veerg; seisund, millesse x läheb registreerimisel (ootel) - selle määrab ära X seisundidiagramm X.reg_aeg - hetke kuupäev + kellaaeg X.viimase_muutm_aeg - hetke kuupäev + kellaaeg Kasutajakonto ning kõik klassifikaatorite tabelid - veerg on_aktiivne - pigem TRUE, sest selle väärtuse kasutamine uue rea lisamisel on tõenäolisem kui väärtuse FALSE kasutamine Töötaja_rolli_omamine.lõpu_aeg - kui kasutate PostgreSQLi, siis spetsiaalväärtus 'infinity' Nii saab lõpu aeg olla kohustuslik veerg ning päringud selle kohta, milline töötaja omab praegu millist rolli, on lihtsamad Kontseptuaalse andmemudeli atribuutide definitsioonides peaks kõigil atribuutidel, millel on vaikimisi väärtus, selle definitsioonis ära märkima. Meenutan, et kontseptuaalne andmemudel ei kajasta "välisvõtme" atribuute: Isik.isiku_seisundi_liik_kood, Klient.kliendi_seisundi_liik_kood, Töötaja. töötaja_seisundi_liik_kood, X.x_seisundi_liik_kood **Märksõnad:** töövihik, vaikimisi väärtus, default value ## Küsimus: Kui tekstilist väärtust hoidev väli või olla ka tühi, kas parem on lubada NULL väärtust või tühja stringi? Kas võib olla põhjust lubada ka mõlemat? **Vastus:** Tabeli väljast võivad väärtused puududa erinevatel põhjustel. Näiteks väärtus ei ole veel andmete sisestajateni jõudnud või sellist väärtust kunagi ei tekigi.  Üheks põhjenduseks, miks lubada tekstilises veerus NULLi ja tühja stringi oleks see, et need kodeerivad erinevaid puudumise põhjuseid.Siiski võib kergesti juhtuda, et NULLid ja tühjad stringid satuvad tabelisse juhuslikult ja kokkuvõttes on vaja kirjutada keerukamaid päringu tingimusi.SELECT isik_id FROM Isik WHERE eesnimi='' OR eesnimi IS NULL;(leia isikud, kellel eesnimi puudub)SELECT isik_id FROM Isik WHERE eesnimi<>'' AND eesnimi IS NOT NULL;(leia isikud, kellel on eesnimi olemas), selle asemel, et kirjutada lihtsalt:SELECT isik_id FROM Isik WHERE eesnimi IS NULL;SELECT isik_id FROM Isik WHERE eesnimi IS NOT NULL;Minu soovitus:- Keelake tekstilises veerus tühjad stringid ja tühimärkidest koosnevad stringid.- Kui väärtused võivad puududa, siis lubage NULLe.- Kui tabelis on veerg, millele vastavasse välja teatud ridade puhul väärtust kunagi ei teki, siis tuleb parandada andmebaasi disaini. liigutada veerg teise tabelisse ja muuta seal see veerg kohustuslikuks või luua algses tabelis seda olukorda kirjeldavad kitsendused Näiteks oletame, et tabelis Subjekt, kus on andmed nii füüsiliste isikute kui organisatsioonide kohta, on selline veerg nagu isiku isikukood. Parem oleks, kui oleks eraldi tabelid Osapool (isikute ja organisatsioonide ühiste atribuutide/seosetüüpide jaoks), Isik ja Organisatsioon. Veerg isikukood peaks olema tabelis Isik kohustuslik veerg. Kui tabelite struktuuri muutmine pole võimalik, siis tuleks jõustada reeglid nagu: kui (organisatsiooni) registrikood on määratud, siis isikukood peab puuduma. kui (isiku) isikukood on määratud, siis peab (organisatsiooni) registrikood puuduma. P => QKui kehtib tingimus P, siis peab ka kehtima tingimus QLoogiliselt samaväärne kui: NOT (P) OR QCHECK (NOT (reg_kood IS NOT NULL) OR isikukood IS NULL)CHECK (NOT (isikukood IS NOT NULL) OR reg_kood IS NULL)Puuduvate andmete kohta saab pikemalt lugeda SIIT. **Märksõnad:** puuduvad andmed, tühi string, empty string, allow zero length ## Küsimus: Küsimus kontseptuaalse andmemudeli kohta. Ma saan aru, et peame atribuute lisama X'le ja näiteks kliendile (on_nõus_tülitamisega), aga kuidas on erinevate standartsemate atribuutidega teiste olemitüüpide puhul. Nagu näiteks Töötaja_seisundi_liik, X_seisundi_liik või Riik: kas neile peaks ka lisama atribuudid nagu näiteks seisundi_liik_id, nimetus, kirjeldus. Vaadates vastuvõtuaegade näidisprojekti, siis seal näiteks pole neid atribuute kontseptuaalses andmemudelis välja toodud, kuid füüsilises disainis on. Samas X'i jaoks toome me ka kontseptuaalses andmemudelis selle koodi ja nimetuse välja. Seetõttu olen veidi segaduses ja lootsin, et ehk oleks võimalik natukene selgitust või suunamist saada sellele, missugused parameetrid lähevad kontseptuaalsesse andmemudelisse ning mis ainult füüsilisse disaini. **Vastus:** Kõikidel klassifikaatoritel (sh Riik, X_seisundi_liik, Töötaja_seisundi_liik jne) on pärimise kaudu atribuudid kood ja nimetus. Need atribuudid on kirjeldatud olemitüübis Klassifikaator ja alamtüüpide juures ei ole vaja neid uuest kirjeldada. Alamtüübi juures tuleb kirjeldada täiendavad atribuudid, mis on spetsiifilised konkreetsele alamtüübile - nii nagu Amet puhul on esitatud atribuut kirjeldus. Kirjeldusi on plaanis registreerida ainult ametite puhul, kuid mitte näiteks riikide ja töötaja seisundi liikide puhul. Teisendusreeglite rakendamise tulemusena tekivad taolisest kontseptuaalsest andmemudelist sellised tabelid nagu Töötaja_seisundi_liik (töötaja_seisundi_liik_kood, nimetus) ja Amet (amet_kood, nimetus, kirjeldus). Eraldi tabelit Klassifikaator ei looda, sest sellel oleks palju puuduseid. Kontseptuaalne andmemudel kirjeldab nõudeid andmetele, mitte andmebaasi tehnilist realisatsiooni konkreetse andmemudeli põhjal ja konkreetses andmebaasisüsteemis. Kontseptuaalses andmemudelis EI ESITATA:- "välisvõtme" atribuute - näiteks riigi_kood EI OLE Isik atribuut,- "surrogaatvõtme" atribuute - näiteks kui isik_id väärtused on kasutusel tarkvara siseselt, kuid mitte lõppkasutajate maailmas, siis olemitüübi Isik puhul atribuuti isik_id ei kirjeldata. X_kood on X atribuut seepärast, et see on sisuline ja tarkvara välises maailmas tähendust omav kood (nagu isikukood, auto registrikood, VIN kood, ainekood, üliõpilaskood jne). Kuna X_kood on sisuline atribuut, siis seda kirjeldatakse kontseptuaalses andmemudelis. **Märksõnad:** kontseptuaalne andmemudel, olemi-suhte diagramm, atribuut, atribuudid ## Küsimus: Ma olen informaatika üliõpilane. Ma arvan, et kursuse töö töövihik on suur dokument mida keegi ei kasuta päris elus. Aine projekti tegemine on täielik ajaraisk, sest kogu info mida õppejõud näha tahab tuleb temalt ning kui ise sellest väga õppida ei saa. Milliseid kasulikke teadmisi, lisaks andmebaasidele, see projekt annab? **Vastus:** Kõik järgnev kehtib endisel, aga selle mõtte lisasin juurde 2024. aasta lõpus. Nüüdseks olete Te kõik tuttavad suurte keelemudelitega ning kuulnud lugusid ja ilmselt ka ise kogenud, kuidas need saavad koodi genereerimisega hästi hakkama KUI neile anda ette hästi sõnastatud küsimus. Programmeerimine on muutumas prompt engineeringuks.  Minu väide on, et kasutajate nõuetest arusaamine ja nende kirjapanemine on loomulik osa sellest protsessist.  Tulevikus kirjutab koodi programm ja inimese ülesanne on programmile sobiv sisend ette anda. Väga oluliseks muutub valdkonna tundmine, mille jaoks programmi luuakse, sest nii osatakse anda keelemudelile piisavalt põhjalik sisend. Üks võimalik viis, kuidas tarkvara tükeldada. Tükeldamine on vajalik tarkvara keerukusega toimetulekuks ja töö paremaks organiseerimiseks. Ülevaade võimalikest mudelitest, mida saab kasutada tarkvara kirjeldamiseks. Ka agiilne süsteemiarendus ütleb, et modelleerimine on vajalik. Tuleb luua mudeleid, millest on kasu, mitte linnukese pärast. Erinevates olukordades, võib olla kasu erinevatest mudelitest. Selleks, et osata otsustada, kas mingit tüüpi mudel mingis olukorras sobib või mitte, tuleb esmalt neid mudeli tüüpe teada. Samuti tuleb arendajal osata aru saada nõuetest ja seega ka mudelitest, mida võidakse kasutada nende nõuete väljendamiseks. Inimesed, kes ei näe oma tulevikku arendajana (analüütikud, andmeteadlased, ettevõtjad, projektijuhid, raamatupidajad jne), võivad tulevikus vabalt sattuda infosüsteemi/tarkvara tellija rolli või kaasatud tulevase kasutaja rolli, kellega tellimuse koostamisel ja süsteemi arendamisel konsulteeritakse. Eriti riigiasutuste puhul on kogu rahastamise loogika selline, et enne arenduse algust soovitakse sõlmida võimalikult täpne leping selle kohta, mida süsteem peab tegema. Seega on kõigepealt vaja teha terve süsteemi analüüs ja sisuliselt tähendab see, et arendus vähemasti algab koskstiilis (edasine arendus võib kuid ei pruugi toimuda iteratiivselt). Tark tellija peab teadma, milliseid süsteemianalüüsi mudeleid saab koostada ning ta peab oskama neid mudeleid lugeda. Kaasatud kasutaja peab samuti oskama mudeleid lugeda. SIIN on üks eestikeelne intervjuu targa tellija olulisuse kohta. Puhta koodi põhimõtted on universaalsed ja kehtivad ka mudelite ning andmebaasi disaini puhul. Andmebaasis kitsenduste loomine on üks kaitsva programmeerimise meetod. Kaitsev programmeerimine üritab tagada koodi toimimist ka ettenägematute asjaolude ilmnemisel ja see aitab parandada süsteemi käideldavust ja turvalisust. Siin on raamat, mis on pühendatud kaitsvale andmebaasi programmeerimisele. Informaatika bakalaureuseõppe lõputööde kaitsmiskomisjoni 2024. aasta kevadisel tagasivaataval kohtumisel avaldati kahetsust selle üle, et tarkvara arendamise teemalistes lõputöödes esitati väga vähe mudeleid, samas kui mudelid oleksid hea ning erineva taustaga lugejatele mõistetav viis loodava süsteemi keerukuse selgitamiseks ning oma töö skoobi väljatoomiseks. Selleks, et osata tööriistakastist (erinevat tüüpi mudelite hulgast) kõige sobivamaid tööriistu (mudelite tüüpe) valida, peaks neid tööriistu tundma või olema nendega vähemalt kokku puutunud. Kirjutan järgnevalt täpsemalt ja toon näiteid.1. Tänapäeval on üheks lööksõnaks e "kuumaks teemaks" mikroteenuste arhitektuur. See tähendab, et tarkvara peaks koosnema üksteisest võimalikult vähe sõltuvatest "tükkidest" e teenustest, mida saaks arendada ülejäänud "tükkidest" võimalikult sõltumatult, mida saaks kerge vaevaga asendada uue realisatsiooniga ja mida ei peaks (palju) muutma, kui mõnes teises "tükis" midagi muutub. Iga funktsionaalse allsüsteemi saaks realiseerida mikroteenusena. Selle funktsionaalse allsüsteemi teenindatava registri saaks realiseerida rakenduse andmebaasina.Mikroteenused üritatakse luua üksteisest võimalikult sõltumatuna, eelistades dubleerimist üksteisest ilmutatud viisil sõltumisele. Andmebaaside mõttes tähendaks see, et erinevate teenuste andmebaasides dubleeritaks põhiandmeid (master data) nagu andmed klientide, toodete ja teenuste kohta ja klassifikaatoreid. Kommentaariks ütlen, et see võib tunduda teenuse autonoomsuse mõttes ahvatlev, kuid andmete dubleerimine tähendab suuremat tööd nende sünkroniseerimiseks (nii suuremat tööd arendajatel selle realiseerimiseks/testimiseks kui ka suuremat koormust süsteemile läbiviimisel) ja suuremat võimalust vastuoluliste väidete registreerimiseks. Kas see on sobiv hind või mitte jäägu igaühe enda otsustada ja kindlasti sõltub ka oludest. (Eesti) Riigi infosüsteemide kohta ütleb avaliku teabe seadus selge sõnaga: "§ 43 3.   Andmekogu asutamine (2) Keelatud on asutada ühtede ja samade andmete kogumiseks eraldi andmekogusid." Põhiobjektidest lähtuv allsüsteemide leidmine on üks võimalik viis mikroteenuste kindlaks määramiseks ja põhiobjekti elutsüklist lähtuv funktsionaalsuse leidmine on üks võimalik viis selle teenuse funktsionaalsuse tuvastamiseks. Kui soovida luua mikroteenused võimalikult autonoomsena ja vajadusel dubleerida andmeid erinevate teenuste andmebaasides, siis saaks teenused luua põhiobjektidele, mis vastavad transaktsioonilistele andmetele ning põhiandmetele ja klassifikaatoritele vastavaid andmeid erinevates andmebaasides dubleerida. Siin on näide hotelli infosüsteemi põhiobjektidest andmete liigituse järgi.2. See on väga vähetõenäoline, et mõni ettevõte kasutab süsteemide kirjeldamiseks just sellist dokumendi struktuuri nagu on aineprojektis. Kuid see, et mingil määral kasutatakse modelleerimist ja mudeleid ning mõnda antud projekti mudeli tüüpidest, on väga palju tõenäolisem.Hea allikas, kust saab lugeda erinevate aineprojekti mudelitüüpide kohta, on: Larman, C., 2013. Applying UML and patterns : an introduction to object-oriented analysis and design and iterative development, Prentice Hall. 703 p. Seda saab ka lugeda O'Reilly digitaalse platvormi kaudu elektrooniliselt. Kuidas kasutada O'Reilly digitaalset platvormi? See raamat on pühendatud objektorienteeritud analüüsile ja disainile (eesmärgiga luua objektorienteeritud programmeerimiskeeles tarkvara), kuid räägitakse ka arendusprotsessist. Mudelite koostamine ei ole mitte kuidagi vastuolus iteratiivse arendamisega. Lihtsalt mudeleid ei looda ühekorraga, vaid neid luuakse ja täiendatakse järk-järgult erinevate iteratsioonide käigus. Raamatus kirjutatakse muuhulgas põhjalikult: klassidiagrammidest, mida kasutades luuakse valdkonnamudeleid (domain model), Kontseptuaalne andmemudel ja valdkonnamudel on sugulased ja kontseptuaalse andmemudeli loomise võtted ning mustrid on kõik kasutatavad ka valdkonna klassidiagrammide koostamiseks. Sama kehtib ka antimustrite kohta, mis esitavad esmapilgul häid lahendusi, mis hiljem viivad probleemideni. Need klassidiagrammid on omakorda sisendiks tarkvaraklasside leidmisele (nii nagu kontseptuaalne andmemudel on sisendiks tabelite leidmisele), seisundidiagrammidest, tegevusdiagrammidest, kasutusjuhtude mudelist, paketidiagrammidest, Saab kasutada arhitektuuri kirjeldamiseks. süsteemi operatsioonide lepingutest Need on sarnased andmebaasi operatsioonide lepingutega. Süsteemi operatsioonid kirjeldavad teenuseid, mida funktsionaalsed allsüsteemid (tarkvara) pakuvad pädevusaladele (lõppkasutajatele). Andmebaasi operatsioonid kirjeldavad teenuseid, mida andmebaasi alamosad (registrid) pakub funktsionaalsetele allsüsteemidele (tarkvarale). Nii nagu süsteemi operatsioonide lepingutest tekivad tarkvara klasside meetodid, tekivad andmete muutmise operatsioonide lepingutest andmebaasiserveris talletatud rutiinid (funktsioonid ja protseduurid). Operatsioonide lepingud võiksid huvi pakkuda ka seetõttu, et need lähtuvad lepingprojekteerimise (design by contract) põhimõttest. See põhimõte töötati välja seoses objektorienteeritud programmeerimiskeelega Eiffel ning esitab tarkvara elementide käitumist viisil, mida ideaalis saaks hiljem kasutada tarkvara kontrollimiseks või koodi genereerimiseks. Sellel teemal mõtlejaid on teisigi (vaadake History alamosa Larmani raamatu süsteemi operatsioonide lepingute peatükist) ja nende idee on kasvanud välja arvutiteaduse (computer science) ringkondadest. Järgnev raamat argumenteerib, miks kontseptuaalse andmemudeli ja andmebaasi disainimudeli loomine ei ole ka agiilse andmebaasi arenduse mõttes ajaraisk, vaid igati kasulik ettevõtmine.Burns, L., 2011. Building the Agile Database. How to Build a Successful Application Using Agile Without Sacrificing Data Management, Technics Publications. 276 p. CRUD maatrikseid on arvutiteaduses üritatud kasutada süsteemide struktuuri leidmiseks ja see on huvitav uurimissuund (vaadake näitena seda artiklit ja ka seda).Tüüpiliselt kulub tarkvara hooldamisele igal aastal 15–20% tarkvara loomiseks tehtud kulutustest. Seega tarkvarale, mis on olnud kasutusel 10 aastat, on hooldamiseks kulunud kaks korda rohkem raha kui algseks loomiseks.  Edukaid süsteeme hooldatakse tavaliselt 10 kuni 20 aastat. Täpsed, kooskõlalised ning süsteemi tegelikku seisu peegeldavad mudelid aitavad tarkvara hooldusega tegelejatel (kes võivad, kuid ei pruugi, olla süsteemi loojad) tarkvarasüsteemist (sealhulgas andmebaasist) aru saada.Tarkvara ja andmebaas peavad ajaga kaasas käima – evolutsioneeruma. Tarkvara/andmebaas pole nagu kivi, mis on miljoneid aastaid ühesugune, vaid nagu elusloodus, mis peab kohanduma ja muutuma. Muudatuste tegemisele aitab kaasa kvaliteetse dokumentatsiooni olemasolu.3. Lugege näiteks siit, kuidas peaaegu igale koodi halvale lõhnale vastab mingi analoogiline probleem seoses infosüsteemi/tarkvara mudelitega. Samamoodi esinevad andmebaasis ja tekitavad sellest arusaamisel, õppimisel, hooldamisel ja edasiarendamisel probleeme näiteks halvad andmebaasiobjektide nimed, kasutama andmebaasiobjektid, ebatäpsed kommentaarid, üleliigne dubleerimine ja järjekindlusetus disainiotsuste tegemisel.Veel mõtteid dokumenteerimise vajalikkuse kohta Dokumenteerimine aitab süsteeme edasi arendada. Viimasel ajal kaitstakse üha rohkem lõputöid, kus üksinda või rühmas arendatakse edasi mingit tarkvara (näiteks erinevad ülikooli õppesüsteemid), mida eelnevad üliõpilased on juba oma lõputöödes arendanud. Kuulates 2023. aasta kevadel selliste lõputööde kaitsmisi oli esinemisest esinemisesse korduv väide, et eelmine tegijate rühm ei olnud oma tööd piisavalt dokumenteerinud (sh polnud kirja pandud nõudeid ja kirjeldatud loodud tabeleid), mistõttu kulus väga palju (liigselt palju) aega süsteemi eelmise versiooni arenduskeskkonnas ülespanekule ja sellest arusaamisele ning vastavalt jäi loodetust vähem aega süsteemi edasiarendamisele. Kaks tsitaati lõputöö ülesandepüstitusest - järjekorras kolmas tarkvara tegijate meeskond hakkas tarkvara nullist ümber tegema. Nad kirjutasid: „Eelmise projektiga tegelenud tiimid hakkasid kohe arendama, millest tulenevadki praeguse lahenduse vead ning vajadus projekti ümbertegemisele.“ Veel lisasid nad: "Arenduse käigus paneme suurt rõhku koodi dokumenteerimisele mis oli eelnevate lahenduste puhul väga suureks probleemiks." Eelmised tegijad hakkasid kohe suure hooga arendama, kuid lõpuks polnud ei korralikult toimivat tarkvara, ega ka korralikku dokumentatsiooni selle kohta. Veel üks eluline näide. Tootmisettevõte tahab oma töö efektiivsemaks muutmiseks võtta kasutusele tehisintellekti, mis kliendi hinnapäringu alusel koostab automaatselt hinnapakkumise ja tootmise plaani. Tehisintellekt vajab oma tööks andmeid. Andmed tulevad andmebaasist. Info andmebaasi ülesehituse kohta (mis andmed on mis tabelites ja veergudes) on andmebaasi tegija peas. Enne kui saab süsteemi arendamisega pihta hakata tuleb see info peast kätte saada ning ilmutatult kirja panna. Dokumenteerimine aitab tagada süsteemide turvalisust. Eesti infoturbestandard esitab nõuded ning juhised organisatsiooni infoturbe halduse süsteemi käivitamiseks, rakendamiseks, käigushoiuks ja täiustamiseks. Eesti avalikke ülesandeid täitavad organisatsioonid peavad E-ITSi nõudeid täitma, eraettevõtted võivad neid täita. Teiste sõnadega e-riigi süsteemides peab igal juhul E-ITSi nõudeid järgima. "E-ITSi eesmärk on tagada avalike ülesannete täitmiseks kasutatavate äriprotsesside ja infosüsteemide kõikehõlmav kaitse ning saavutada infoturbe ühtlane tase nende kõigis osades kogu elutsükli jooksul." Nende eesmärkide täitmiseks tuleb E-ITSi rakendaval ettevõttel muuhulgas äriprotsessid kirjeldada ja arvele võtta (st teemaks on modelleerimine ja dokumenteerimine). See on standardi rakendamise eeldus. E-ITS kirjeldab turvameetmed, mis jagunevad põhimeetmeteks ja standardmeetmeteks. Põhimeetmeid tuleb rakendada igal juhul, sest see on absoluutne miinimum mida turvalisuse tagamiseks teha. Standardmeetmete rakendamiseni jõudmine tagab suurema turvalisuse ja nende rakendamiseni jõudmine peaks olema iga organisatsiooni eesmärk. E-ITS pakub etalonturbe süsteemi, kus väljapakutud meetmed on jagatud erinevatele teemadele vastavatesse moodulitesse. Moodulirühmas "Kontseptisoonid ja metoodikad" olevas moodulis "Tarkvaraarendus" on üks standardmeede "Detailne tarkvara dokumentatsioon". Meetme kirjelduses tuuakse välja, et tarkvara kohta peab olema üksikasjalik ja põhjalik dokumentatsioon ning loetletakse selle dokumentatsiooni minimaalselt nõutavad osad. Ühtlasi rõhutatakse, et dokumentatsiooni detailsus peab olema piisav, et nõutava tasemega tehniline ekspert suudaks dokumentatsioonile tuginedes tarkvaratoote halduse ja arendamise üle võtta. Samuti tuleb valida selline tarkvaraarenduse metoodika, mis näeb ette dokumentatsiooni loomise. Moodulirühmas "Rakendused" olevas moodulis "Tellimustarkvara arendus" on üks standardmeede "Tellimustarkvara nõuete põhjalik dokumenteerimine". Meetme kirjelduses tuuakse välja vajadus dokumenteerida nii funktsionaalsed kui ka mittefunktsionaalsed nõuded, kusjuures mittefunktsionaalsete nõuete juures nimetatakse ka nõuete liigid, mis tuleb kindlasti välja tuua. Samuti rõhutatakse, et "pärast tarkvaramuudatuste ja funktsionaalsete uuendite installimist kontrollitakse nõuetele vastavust ning vajadusel uuendatakse tarkvara nõuete dokumentatsiooni." See, et taolistest asjadest turvalisuse tagamise standardis kirjutatakse, on loogiline, sest üks kolmest infoturbe põhikomponendist on käideldavus. Käideldav süsteem on ettenähtud ajal ettenähtud mahus kättesaadav. Selle tagamiseks tuleb süsteemi pidevalt hooldada ja vajaduse tekkides edasiarendada ning selleks on omakorda vaja süsteemist detailideni aru saada (vt esimene mõte). Dokumenteerimine aitab vältida pärandsüsteemidest (legacy system, taakvara) tulenevaid probleeme.  Riigi Infosüsteemi Ameti (RIA) küberturvalisuse 2022. aasta aastaraamatus kirjutatakse: "Taakvara vaevab paljusid pikka aega tegutsenud ettevõtteid ja asutusi. Näiteks ei pruugi kümme aastat tagasi arendatud süsteemi praegustel omanikel olla täielikku teadmist selle ülesehitusest ega funktsioonidest. Organisatsioonid muutuvad ajas, inimesed  vahetuvad ning pahatihti ei ole kunagi kasutusele võetud lahendused „järeltulijatele“ korralikult dokumenteeritud. Seetõttu pole sageli täpselt teada, millise doominoefekti võib ühe osa uuendamine kuskil süsteemi teises otsas kaasa tuua." Iga tarkvara, mida piisavalt pikka aega kasutatakse, muutub ühel hetkel taakvaraks. Dokumenteerimine aitab kaasa taaskasutamisele. Erinevate Eesti riigiasutuste koostöös valminud tehisintellekti ja andmete valges raamatus aastateks 2024-2030 kirjutatakse: "Andmete taaskasutus saab toimida ainult siis, kui erinevate osapoolte poolt hallatavad andmed on standardiseeritud, korrastatud, kirjeldatud, avalikustatud, kontrollitud kvaliteediga ning varustatud andmete taaskasutust toetava dokumentatsiooni ja toega." Samas dokumendis kirjutatakse, et Eesti e-riigis ei ole sellega sugugi kõik korras, sest "vaid 8% riigiasutustest on juurutanud andmekirjelduse standardi, 28% on kaardistanud kõik oma andmed, põhiandmed on kaardistanud ja kirjeldanud 36% asutustest". Sama dokumendi kohaselt puudub 2023. aasta seisuga 58%-l asutustest täielik ülevaade oma andmestikest ja 55% asutustest ei uuenda ja avalikusta regulaarselt andmekirjeldusi. Kokkuvõtteks, päriselu ei ole AINULT idufirmad. Nendes võibolla tõesti on eesmärk kiiresti midagi tööle saada, et enne konkurente turule jõuda. Kui firma jääb püsima, siis pigem varem kui hiljem tuleb hakata arvestama eelnevalt kirjeldatud probleemidega. **Märksõnad:** iseseisev töö, projekt, dokument, dokumentatsioon, mudelid, project, diagramm, diagrammid, puhas kood, allsüsteem, funktsionaalne allsüsteem, register, andmebaasioperatsioon, andmebaasioperatsioonide lepingud ## Küsimus: Meie töövihiku projekti teemaks on treeningute funktsionaalne allsüsteem. Dokumendi punktis 1.2.3 (Allsüsteemi poolt vajatavad registrid) me kirjutame, et kasutame saalide registrit. Kas see tähendab, et meie projekti kontseptuaalse andmemudeli osaks peab olema saalide registri olemi-suhte diagramm? **Vastus:** Jah! Kommentaarid: 1. Töövihiku korral, kui X=Treening, siis Treening = Ainekaart Öelda, et iga treening on seotud täpselt ühe saaliga oleks sama, kui öelda näiteks ÕISis "Andmebaasid I" ainekaardil, et seda õpetatakse ainult ruumis ICT-404. Tegelikult saab seda ainet õpetada paljudes ruumides. Võimalik on anda sellele seosetüübile uus tähendus ja öelda, et tegemist on eelistatud saaliga selle treeningu läbiviimiseks. Selleks saab mudelis määrata saali rolli selle seosetüübi kontekstis. [Treening]-0..*-----+eelistatud saal-1-[Saal] 2. Igal põhiobjektil on elutsükkel ja infosüsteemis peab olema võimalik jälgida, millises seisundis on selle eksemplarid. Sellest sõltuvad süsteemis tehtavad tegevused. Näiteks ma ei tohiks saada siduda treeningut "Suletud" seisundis saaliga. Seega peab kontseptuaalses andmemudelis olema: [Saal]-0..*-----------1-[Saali seisundi liik] Samuti tuleb treeningu registreerimise ja treeningu andmete muutmise andmebaasioperatsioonide eeltingimustes ära kirjeldada, millises seisundis saalidega saab treeningut siduda. 3. Võimalik lihtsustus on käsitleda saali klassifikaatorina. Sellisel juhul oleks mudelis Saal Klassifikaatori alamtüübiks ja eraldi saalide registrit pole äriarhitektuuris vaja. Selline lahendus sobib, kui saalide andmete haldamiseks tehtavad toimingud ei erine teiste klassifikaatorite andmete haldamiseks tehtud toimingutest ja saalide elutsükkel ei erine teiste klassifikaatorite elutsüklist. Sellisel juhul puudub mudelist olemitüüp Saali_seisundi_liik. ## Küsimus: Meil on küsimus aadressi kohta. Kuidas on parem viis pakiautomaadi (kaupluse/kino/treeningsaali/...) aadressi andmebaasis salvestada? Me nägime, et Omniva lehel näidatakse seda niimoodi: "Ida-Viru maakond, Kohtla-Järve linn, Ahtme linnaosa, Maleva tn, 23". Tundub, et iga koma vahel on eraldi veerg, kuhu kirjutatakse andmed ja veerude nimed oleksid "asukoht_maakond, asukoht_linn, asukoht_linnaosa, asukoht_tänav, asukoht_tänava_nr". Kas me kasutame selle viisi, või saame parema loetavuse jaoks lihtsalt salvestada kogu stringi ühe veergu nimega "asukoht"? **Vastus:** Aadressiandmetel on keeruline struktuur ja palju erinevaid võimalikke komponente (riik, maakond, linn, vald, küla, talu, linnaosa, tänav, korter, hooneosa, ...). Erinevates riikides on võimalike komponentide hulk erinev. Kui ülesanne oleks pakkuda kasutajatele detailset aadresside otsimise võimalust, siis andmebaasi mõttes tähendaks see märkimisväärset hulka täiendavaid tabeleid, mille vahel komponentideks jagatud aadress ära jagada. Näitena saab Eesti Aadressiandmete Süsteemiga liidestumise juhendi jaotisest 3.2.4 Aadressi komponendid (tasemed) vaadata Eesti aadresside komponente.Kui eesmärk on pakkuda taustainfot pakiautomaadi kohta (nagu antud projektis), siis piisab vabatekstilisest atribuudist aadress."Sulgude ette" võib tõsta Maakonna. Maakond on klassifikaator.[Pakiautomaat]-0..*---------+asukoht-1-[Maakond]​Siit näete maakondade klassifikaatori väärtuseid. Kui pakiautomaadid võivad olla eraldi riikides, siis tõstaksin maakonna asemel "sulgude ette" riigi.​[Pakiautomaat]-0..*----------+asukoht-1-[Riik]Saaksite kasutada sama riikide klassifikaatorit, mis on juba seotud olemitüübiga Isik. Maakonna klassifikaatorit ma siis ei kasutaks, sest kõigis riikides ei pruugi olla haldusüksust "maakond" ning erinevate riikide maakondade üle võib olla raske arvet pidada.​    Kokkuvõttes oleks näite korral pakiautomaadi atribuudi aadress väärtuseks "Kohtla-Järve linn, Ahtme linnaosa, Maleva tn, 23" ning pakiautomaat oleks seotud maakonnaga Ida-Virumaa. ## Küsimus: Mida kujundab endast elementaarvõtme normaalkuju (EVNK)? **Vastus:** Kui ma vaatan C.J Date ja J. Celko töid, siis nad mainivad seda normaalkuju lühidalt, ajaloolise tagasivaate ja esitluse täielikkuse huvides. C.J. Date osundab, et EVNK-le viidatakse kirjanduses vähe.EVNK on kolmanda normaalkuju (3NK) ja Boyce/Coddi normaalkuju (BCNK) vahel - kui tabel on elementaarvõtme normaalkujul, siis on see ka kolmandal normaalkujul. Eesmärk on ikkagi jõuda Boyce/Coddi normaalkujuni. Muide, see artikkel, kus EVNK välja pakutakse, annab head 3NK ja BCNK definitsioonid. EVNK käsitleb olukorda, kui tabelil on rohkem kui üks liitvõti ja need võtmed osaliselt kattuvad (st neil on ühiseid veerge). Sellisel juhul võib kattuvates veergudes olla korduvaid andmeid.C. J. Date defineerib EVNK järgnevalt: "Tabel on elementaarvõtme normaalkujul (EVNK) siis ja ainult siis kui iga mittetriviaalse funktsionaalse sõltuvuse X=>Y korral on kas a) X tabeli supervõti või b) Y on mõne elementaarvõtme alamvõti. K on tabeli T elementaarvõti siis ja ainult siis kui tabelis T on selline veerg V, mille puhul funktsionaalne sõltuvus K=>{V} on mittetriviaalne ja täielik." (https://learning.oreilly.com/library/view/database-design-and/9781449330187/ch13.html#concluding_remarks-id4)J. Celko esitab tabeli sellele normaalkujule viimise kohta näite.https://learning.oreilly.com/library/view/joe-celkos-sql/9780123693792/9780123693792_ch02lev1sec5.html Aine_deklareerimine (yliopilaskood, ainekood, aine_nimetus)Primaarvõti (yliopilaskood, ainekood)Alternatiivvõti (yliopilaskood, aine_nimetus)Mittetriviaalsed täielikud funktsionaalsed sõltuvused selles tabelis:(yliopilaskood, ainekood) => aine_nimetus(yliopilaskood, aine_nimetus) => ainekoodainekood=>aine_nimetusaine_nimetus=>ainekoodÜlekanduvaid sõltuvusi selles tabelis ei ole ja seega on see tabel kolmandal normaalkujul.Leidub funktsionaalseid sõltuvusi, mille determinant ei ole kandidaatvõti ning seega pole see Boyce/Coddi normaalkujul.ainekood=>aine_nimetusaine_nimetus=>ainekoodLähemal vaatlemisel ilmneb, et tabelis võivad ainete andmed olla erinevates ridades dubleeritud, st selles tabelis on andmete liiasust, mida saaks täiendava normaliseerimisega vähendada.Tabeli elementaarvõtmed on minu arusaamise kohaselt. (yliopilaskood, ainekood) (sest leidub veerg aine_nimetus, nii et (yliopilaskood, ainekood) => aine_nimetus) (yliopilaskood, aine_nimetus) (sest leidub veerg ainekood, nii et (yliopilaskood, aine_nimetus) => ainekood) Need on kandidaatvõtmed, st nende atribuutide pärisalamhulk ei ole enam võti. Järelikult eelnevalt välja kirjutatud neljast funktsionaalsest sõltuvusest kaks viimast ei rahulda EVNK tingimusi.Lahendus oleks luua tabelidAine (ainekood, aine_nimetus)Primaarvõti (ainekood)Alternatiivvõti (aine_nimetus)Aine_deklareerimine (yliopilaskood, ainekood)Primaarvõti (yliopilaskood, ainekood)Välisvõti (ainekood) Viitab Aine (ainekood)Need tabelid on ka BCNK-l. **Märksõnad:** elementary key normal form, EKND, normaliseerimine, normalization ## Küsimus: Mida ma võiksin teada NoSQL süsteemidest? **Vastus:** Teemas 1 ja 11 on juttu NoSQL süsteemidest. Kes tahab nende kohta rohkem teada saada, siis võiks alustada sellest Martin Fowleri umbes tunni pikkusest videost. Kes eelistab lugeda, saab vaadata seda materjali, laenutada raamatukogust raamatu, mille kokkuvõtteks see materjal on või lugeda seda sama raamatut elektrooniliselt (Kuidas kasutada O'Reilly digitaalset platvormi?). Hilisemast ajast tasub vaadata arvutiteadlase Michael Stonebrakeri ettekannet suurandmete ja nendega töötamise vahendite (sh NoSQL süsteemid) kohta. Vastukaaluks positiivsele "uus ja lahe läikiv mänguasi" tüüpi käsitlusele võiksid huvilised vaadata ka 2013. aastast pärit artiklit "History repeats itself: sensible and NonsenSQL aspects of the NoSQL hoopla", mis annab minu arvates realistliku vaate NoSQL süsteemide headele ja mitte nii headele külgedele. Kokkuvõte artiklist - kes minevikku ei mäleta, on määratud selle vigu kordama (väide, mis kehtib igal elualal). NoSQL and Technical Debt. Ajaveebi postitus, mis selgitab, miks NoSQL süsteemide ilmumine pole muutnud väärtusetuks SQLi ning andmebaaside projekteerimise õppimist. Nende oskuste puudumine on arendajatel võlg, mis tuleb hiljem intressidega tagasi maksta. NoSQL oma "skeemitute" andmetega loob tegelikult tehnilist võlga. Aina rohkemates NoSQL süsteemides saab andmebaasi tasemel kirjeldada ja jõustada andmebaasi struktuuri (näide) (kirjutamise skeemi e schema-on-write). Saadakse aru, et struktuur on eelis mitte puudus. Aina rohkemates NoSQL süsteemides saab kasutada deklaratiivset andmebaasikeelt (näide), mis paraku (SQL pole just kõige paremini disainitud keel) enamasti meenutab SQLi. Saadakse aru, et deklaratiivset keelt on palju kergem kasutada ja õppida kui imperatiivset. Irvhambad juba ütlevad, et NoSQL = Not Yet SQL.Siin on päris pikk ja põhjalik eestikeelne materjal, mille teine pool on pühendatud NoSQLil. ## Küsimus: Miks ei ole hea mõte kasutada kõikides tabelites surrogaatvõtit? **Vastus:** Surrogaatvõti on lihtvõti, mille väärtused on süsteemi genereeritud unikaalsed täisarvud. Need väärtused on kasutusel tarkvara siseselt ridade identifitseerimiseks, kuid andmebaasi kasutavatele inimestele ei tähenda need väärtused midagi ja ta ei oska nende alusel olemeid üksteisest eristada. Näide: kes on töötaja, kelle id=34583?Sisulise tähendusega võtme väärtus on seevastu ka arusaadav inimkasutajale ja ta oskab nende väärtuste alusel olemeid üksteisest eristada. Näide: kes on töötaja, kelle meiliaadress on Erki.Eessaar@taltech.ee?Vaatleme kahte tabelite disaini.Disain 1 (kõikides tabelites surrogaatvõti - "id" veerg).Riik (riik_id, riik_kood, nimetus)Primaarvõti (riik_id)Klient (klient_id, riik_id, e_meil, eesnimi, perenimi)Primaarvõti (klient_id)Välisvõti (riik_id) Viitab Riik (riik_id)Toode (toode_id, toote_kood, hind)Primaarvõti (toode_id)Tellimus (tellimus_id, klient_id, reg_aeg)Primaarvõti (tellimus_id)Välisvõti (klient_id) Viitab Klient (klient_id)Tellimuse_rida (tellimus_id, toode_id, kogus)Primaarvõti (tellimus_id, toode_id)Välisvõti (tellimus_id) Viitab Tellimus (tellimus_id)Välisvõti (toode_id) Viitab Toode (toode_id)Disain 2 (kõikides tabelites, kus võimalik, on sisulise tähendusega võtmed).Riik (riik_kood, nimetus)Primaarvõti (riik_kood)Alternatiivvõti (nimetus)Klient (e_meil, riik_kood, eesnimi, perenimi)Primaarvõti (e_meil)Välisvõti (riik_kood) Viitab Riik (riik_kood)Toode (toote_kood, hind)Primaarvõti (toote_kood)Tellimus (tellimus_id, e_meil, reg_aeg)Primaarvõti (tellimus_id)Välisvõti (e_meil) Viitab Klient (e_meil)Tellimuse_rida (tellimus_id, toote_kood, kogus)Primaarvõti (tellimus_id, toote_kood)Välisvõti (tellimus_id) Viitab Tellimus (tellimus_id)Välisvõti (toote_kood) Viitab Toode (toote_kood)Millised on disaini 1 probleemid võrreldes disainiga 2?Probleem 1: Päringud on keerukamad, sest tuleb lugeda andmeid suuremast hulgast tabelitest. Päringutes tuleb ühendada rohkem tabeleid. Lause täitmine võtab rohkem aega.Ülesanne: Leia PostgreSQL andmebaasis kordusteta selliste toodete koodid, mida on ostnud Eesti kliendid.Disain 1SELECT DISTINCT toote_koodFROM Riik INNER JOIN Klient USING (riik_id)INNER JOIN Tellimus USING (klient_id)INNER JOIN Tellimuse_rida USING (tellimus_id)INNER JOIN Toode USING (toode_id)WHERE Riik.riik_kood='EST';Disain 2SELECT DISTINCT toote_koodFROM Klient INNER JOIN Tellimus USING (e_meil)INNER JOIN Tellimuse_rida USING (tellimus_id)WHERE Klient.riik_kood='EST';Disain 2 korral leian riigi koodi tabelist Klient ja toote koodi tabelist Tellimuse_rida. Disain 1 korral tuleb lugeda viit tabelit, disain 2 korral tuleb lugeda kolme tabelit.Probleem 2: Surrogaatvõtmete läbival kasutamisel tekib sageli olukord, et sisulised võtmed lähevad andmebaasi arendajal täiesti meelest ära ja neid ei jõustata andmebaasis. Disain 1 korral peaksid Riik tabelis olema unikaalsed (riik_kood) ja (nimetus). Klient tabelis peaks olema unikaalne (e_meil). Toode tabelis peaks olema unikaalne (toode_kood). Enamikes andmebaasisüsteemides tekivad PRIMARY KEY ja UNIQUE kitsenduste toetuseks indeksid, seega suureneb indeksite ja nende kasutatav kettaruumi hulk. ## Küsimus: Miks mitte luua klassifikaatoritele ühist tabelit Klassifikaator, kus on kõikide klassifikaatorite koodid ja nimetused? **Vastus:** Vastuse leiate selle artikli esimesest punktist.Selle ülevaate alajaotus "One True look-up Table" on pühendatud ühisele klassifikaatorite tabelile:https://www.red-gate.com/simple-talk/databases/sql-server/t-sql-programming-sql-server/look-up-tables-in-sql/Kes tunneb teema vastu sügavamat huvi võib vaadata bakalaureusetööd: Vellemaa, A.S., 2015. Mõned disainimustrid klassifikaatorite esitamiseks SQL andmebaasides. Bakalaureusetöö. TTÜ Informaatikainstituut [WWW] https://digi.lib.ttu.ee/i/?3484. ## Küsimus: Miks on halb mõte kasutada erinevates tabelites ühesuguse nimega (id, kood või code) primaarvõtme veergu? **Vastus:** See muudab keerulisemaks tabelites olevatest andmetest arusaamise ja tabelite põhjal päringute tegemise.Sellise nimega primaarvõtme veerud on üks sümptom, mis viitab sellele, et andmebaasi disainis esineb "Üks suurus kõigile" andmebaasi disaini antimuster. Antimuster on struktuurse kirjutamise viis, kuidas panna kirja halbu lahendusi levinud probleemidele.Selline nimi on liiga üldine ja tuleb päringute tulemuses enamasti ümber nimetada. Vastasel juhul tekib päringu tulemusse mitu sama nimega veergu, mis vormiliselt on küll SQLis lubatud, kuid sisuliselt muudab see päringu tulemuse raskesti kasutatavaks.Oletame, et andmebaasis on tabelid:Mark (id, nimetus)Primaarvõti (id)Auto (id, mark_id, registri_nr)Primaarvõti (id)Välisvõti (mark_id) Viitab Mark (id)Kui ülesandeks on leida iga auto kohta margi identifikaator, nimetus, auto identifikaator ja registri number, siis tuleks kirjutada päringSELECT Mark.id AS mark_id, nimetus, Auto.id AS auto_id, registri_nrFROM Mark INNER JOIN Auto ON Mark.id=Auto.mark_id;Samas, kui andmebaasis oleksid tabelid:Mark (mark_id, nimetus)Primaarvõti (mark_id)Auto (auto_id, mark_id, registri_nr)Primaarvõti (auto_id)Välisvõti (mark_id) Viitab Mark (mark_id), siis saab selle ülesande lahendada SQL standardit hästi järgivas andmebaasisüsteemis (nt PostgreSQL) oluliselt lühema lausega. USING võimaldab teha ühendamist üle samanimeliste veergude. Ühendamise tulemuses on see veerg (antud juhul mark_id) ühekordselt, st SELECT klauslis pole veeru nime ees vaja täpsustada tabeli nime.SELECT mark_id, nimetus, auto_id, registri_nrFROM Mark INNER JOIN Auto USING (mark_id);Veel üks, veidi pikem näide, kus koodi kirjutamise mugavus tuleb paremini välja. Leia ilma kordusteta milliseid kaupu on millised kliendid ostnud.SELECT DISTINCT klient.id AS klient_id, klient.perenimi, kaup.id AS kaup_id, kaup.nimetus AS kauba_nimetusFROM Klient INNER JOIN Tellimus ON Klient.id=Tellimus.klient_idINNER JOIN Tellimuse_rida ON Tellimus.id=Tellimuse_rida.tellimus_idINNER JOIN Kaup ON Tellimuse_rida.kaup_id=Kaup.id;Tuleb olla tähelepanelik, et mitte valesid veerge kokku ühendada (tegin ka ise selle vea seda näidet kirjutades).vs.SELECT DISTINCT klient_id, klient.perenimi, kaup_id, kaup.nimetus AS kauba_nimetusFROM Klient INNER JOIN Tellimus USING (klient_id)INNER JOIN Tellimuse_rida USING (tellimus_id)INNER JOIN Kaup USING (kaup_id);Vastukaaluks saab öelda, et võtmeveeru nimi id võib lihtsustada mingites rakenduse ehitamise vahendites andmebaasi kasutuse realiseerimist. Lõppkokkuvõttes, nagu väga sageli (andmebaasi) tehnilise lahenduse loomise juures, on kõik valikute küsimus ning igal valikul on oma head ja halvad tagajärjed. ## Küsimus: Miks on kasulik tükeldada infosüsteemi allsüsteemideks? **Vastus:** Juhin Teie tähelepanu Postimehe 21.02.2017 artiklile "Riigi olulisema infosüsteemi seis: tengelpung lõhki, kalender ribadeks, aga lootust on". Paljude infosüsteemide arendamisel tekib kahjuks olukord, et arendus läheb oodatust kallimaks ja võtab eeldatust rohkem aega. Selles artiklis on sellise olukorra tekkimise ja põhjuste väga ilmekas kirjeldus Eesti pensionide ja sotsiaaltoetuste maksmise infosüsteemi (SKAIS) uue versiooni (SKAIS2) näitel. Seda infosüsteemi kasutatakse igapäevaselt 110 erinevat liiki toetuse ja pensioni maksmiseks kokku 700 000 inimesele. Kokkuvõtlikult: Arenduse valmimine lükkus edasi vähemalt 1,5 aastat . Projekt läks kallimaks vähemalt 1,5 miljonit. Arendajad olid artikli kirjutamise ajaks maksnud riigile 180 000 eurot trahve. Otsene seos käesoleva aine temaatikaga tekib sellest, et algselt asuti kogu keerulist süsteemi arendama tervikuna. See oli korraga närimiseks liiga suur suutäis. Tõmmake paralleele sellega, et võtate suu täis mingit kõva maiustust ja siis ei saa isegi hambaid liigutada. Nüüdseks on otsustatud arendamist jätkata osade kaupa. Need osad vastavad funktsionaalsetele allsüsteemidele. Süsteemi jagamine allsüsteemideks võimaldab allsüsteemide arendamist järk-järgult, arenduse tellimist erinevate hangetega ja võimalik, et erinevatelt firmadelt - täpselt nii nagu nüüd plaanitakse. Kuna iga hanke tulemusena tuleb teha valmis väiksem "tükk", siis on ka tähtajad paremini saavutatavad. 11.08.2017 sai see lugu kurva jätku, kui tehti teatavaks, et riik katkestab lepingu süsteemi senise arendajaga ja kuulutab välja uue hanke. Kokkuvõttes läks arendus algselt plaanitust vähemalt kaheksa miljonit EURi kallimaks (algne plaanitud maksumus 7.1 miljonit EURi) ja valmimine lükkus viis aastat edasi. 15.04.2018 kirjutati, et uues SKAIS2 arendamise lepingus pandi paika eeldatav tööde kestus (neli aastat), kuid ei fikseeritud täpseid tähtaegu ega arendamise graafikut. Täpne ajagraafik pannakse paika pärast infosüsteemi arhitektuuri analüüsi. Näib, et see analüüs meenutab siin aines kirjeldatavat strateegilist analüüsi. Strateegiline analüüs määrab süsteemi skoobi, leiab arhitektuuri (või arhitektuuri variandid), tuvastab riskid ja paneb paika arendamise ajakava. Lepingus määrati ära üldine tegevuste järjekord: SKAISi arhitektuuri analüüs, olemasolevate teenuste vastavusse viimine uue arhitektuuriga, uute teenuste arendamise alustamine. 28.01.2019 kirjutas ajakirjandus, et juba 15 miljonit maksma läinud projekti jätkamiseks kuulutati 2019. aasta jaanuari keskel välja riigihange mahus 8 miljonit eurot. Olemasolevad arenduspartnerid jätkavad tööd vastavalt sõlmitud lepingule. Uue hanke eesmärk on samaaegselt arendada täiendavat funktsionaalsust.25.09.2020 tegi ajakirjandus vahekokkuvõtte, et selleks ajaks on süsteemile kulunud 12 miljonit eurot, kuid lepinguid on töödele kokku 44 miljoni euro eest. Projektiga tegeleb kuus IT-ettevõtet. Mõned asjad nagu iseteeninduskeskkond koos proaktiivse (ennetava) perehüvitise teenusega on valmis jõutud. ## Küsimus: Miks on vaja klassifikaatorite funktsionaalset allsüsteemi? **Vastus:** Eluline näide, kuidas klassifikaatorite väärtuste hulk võib ajas täieneda. See näide on soo klassifikaatori kohta. Selliste täienduste tegemine (hetkel uute väärtuste lisamine) toimuks infosüsteemi äriarhitektuuri mõttes läbi klassifikaatorite funktsionaalse allsüsteemi. Kasutajatele esitatavate klassifikaatori väärtuste nimetused peaksid olema ühes inimkeeles. Kui süsteem peaks võimaldama kasutajaliidese keelt muuta, siis lõppkasutaja jaoks peaks keele muutmisel muutuma nii kasutajaliidese kui klassifikaatori nimetuste keel. Viimase saavutamiseks on erinevaid SQL-andmebaasi disaine. Süsteemide mitmekeelsuse küsimusi puudutab ka järgnev töö: Hövel, E., 2017. Mõned mitmekeelsete SQL-andmebaaside disainimustrid. Bakalureusetöö. TTÜ Tarkvarateaduse instituut [WWW] https://digi.lib.ttu.ee/i/?8271 ## Küsimus: Miks suurte IT-süsteemide arendamine pahatihti ebaõnnestub? **Vastus:** 2019. aasta sügisel avaldas riigikontroll aruande (kokkuvõte) selle kohta, miks riigi tarkvaraarenduse projektid (mis enamasti on suuremahulised) nii mõnigi kord ebaõnnestuvad. Viimasel ajal on selle kohta päris mitmeid näiteid. See aruanne oli üheks ajendiks, miks Andres Kütt pidas 4. oktoobril 2019 Tallinna Tehnikaülikoolis avaliku loengu teemal "Õppetunnid suurtest IT projektidest". Tundub, et riigikontrolli aruanne tabas valusalt närvi, sest arvajaid ning kaasamõtlejaid oli palju. Tõstaksin veel esile Kaimar Karu arvamusloo teemal "Riigi tarkvaraprojektide õnnestumise võimalikkusest". **Märksõnad:** arendus, infosüsteem ## Küsimus: Millal kasutada kontseptuaalses andmemudelis kompositsiooniseost (seose ühes otsas on täidetud romb e täidetud teemant)? **Vastus:** Kompositsioon tähistab osa-terviku seost, kus osad sõltuvad eksistentsiaalselt tervikust e terviku kadumine/hävimine tähendab ka osade kadumist/hävimist.Romb oleks selle olemitüübi poolel, millesse kuuluva olemi kustutamine tingib seotud olemite kustutamise.[Käsi]<*>-1------------0..*-[Sõrm]NB! Pange tähele võimsustikku (0..*), sest mitte kõigil inimestel pole käel täpselt viite sõrme. Näiteks sellele küsimusele/vastusele lisatud joonisel (vt vastuse lõpust) on kompositsiooniseoseid kindlasti liiga palju.Mulle meeldib kõige rohkem nõuanne, et kui kahtled, siis jäta osaks/tervikuks olemine märkimata.Andmebaaside taustaga inimest võiks nende määramise juures aidata küsimus: Milliste seoste puhul kasutaksin ma SQL-andmebaasis ON DELETE CASCADE (e kustutades terviku kustuvad automaatselt ka selle osad)? Nende puhul võib (ei pea) UMLi klassidiagrammis kasutada täidetud rombi (kompositsiooni).Kindlasti kasutaksin mina seda joonisel oleva näite puhul vaid ühes kohas: Isik-Isik roll.Isik-Isiku roll puhul kasutaksin kontseptuaalses andmemudelis kompositsiooni ja SQL-andmebaasis ON DELETE CASCADE, sest tegemist on registri põhiobjekti ning sellega seotud selle sama registri mittepõhiobjektiga.Valikukoht on minu arvates, kas kasutada kontseptuaalses andmemudelis kompositsiooni ja andmebaasis ON DELETE CASCADE ka järgnevate puhul:Koer-Varjupaigas_viibimineKoer-Koera_tervise_ankeetKoer-AdopteerimisavaldusLoogiline oleks, et kas kasutada seda kõigi kolme puhul või mitte ühegi puhul. **Märksõnad:** kompositsioon, UML, olemi-suhte diagramm ## Küsimus: Millal modelleerida kontseptuaalses andmemudelis mingit olemitüübi omadust atribuudina ja millal klassifikaatorina (eraldi olemitüübina)? **Vastus:** Selle üle otsustamine, mida modelleerida olemi-suhte diagrammis atribuudina ja mida eraldi olemitüübina, on selle mudeli tüübi kasutamise üks põhilisi keerukusi.Modelleeri klassifikaatorina kui vähemalt üks tingimus on täidetud: kasutaksite vastavate andmete registreerimise kasutajaliideses väärtuste valimist nimekirjast (nt liitboksist või hüpikanast), kusjuures kasutaja näeb valiku tegemiseks nimetust, kasutaksite rakenduse lähtekoodis vastavas tarkvaraklassis atribuudi tüübina loendustüüpi, lisaks tekstilisele nimetusele on omaduse väärtusega seotud täiendavaid andmeid, mida on vaja andmebaasis hoida ja mis võivad ka aidata valikut teha (näiteks töötaja rollil on lisaks nimetusele kirjeldus, näiteks riigil on lisaks nimetusele rahvusvahelised suunakoodid telefoniga helistamisel), näete ette, et andmebaasis võib tulevikus tekkida vajadus täiendavate eelmises punktis nimetatud andmete registreerimiseks, omaduse võimalike väärtuste hulk on määratud mingi standardiga (näiteks riigid, keeled, valuutad, isikute sood). Muudel juhtudel modelleeri atribuudina. Näiteks modelleeri atribuudina juhul kui: omaduse väärtus on vabatekst (näiteks kirjeldus, kommentaar), omaduse väärtus on kuupäev, kellaaeg või ajatempel (näiteks registreerimise aeg, sünni kuupäev), omaduse väärtus on tõeväärtus (true või false), omaduse väärtus on arv arvude vahemikust (näiteks sünniaasta vahemikus 1900 kuni 2100, pikkus vahemikus 100 kuni 250, kõrgus vahemikus 1 kuni 2000). **Märksõnad:** olemitüüp, atribuut, olemi-suhte diagramm, kontseptuaalne andmemudel, ERD, klassifikaator, klassifikaatorid ## Küsimus: Mille alusel otsustada olemite vaheliste seoste alustel leitud olemitüüpide kuuluvuse üle konkreetsesse registrisse? **Vastus:** Vastan sellele küsimusele näite põhjal. Oletame, et andmebaasi kontseptuaalses struktuuris on olemitüübid:[Kaup]-1----0..*-[Kauba laoseis]-0..*----------1-[Ladu]Olemitüübil Kauba laoseis on atribuut kogus. Süsteemi äriarhitektuuris on sellised allsüsteemid nagu: kaupade register (ja selles andmeid haldav kaupade funktsionaalne allsüsteem), ladude register (ja selles andmeid haldav kaupade funktsionaalne allsüsteem). Olemitüüp Kaup kuulub kaupade registrisse. Olemitüüp Ladu kuulub ladude registrisse. Millisesse registrisse peaks kuuluma olemitüüp Kauba laoseis? Kas olemitüübil Kauba laoseis on oma elutsükkel, erinevate võimalike süsteemile huvipakkuvate seisunditega (midagi rohkem kui seisundid "aktuaalne" ja "mitteaktuaalne")? Kui  jah, siis võib Kauba laoseis olla eraldi põhiolemitüüp. Sellisel juhul oleks süsteemi äriarhitektuuris ka eraldi kauba laoseisude register ning kauba laoseisude funktsionaalne allsüsteem. Kui ei, siis kuulub Kauba laoseis kas kaupade registrisse või ladude registrisse, ning nende andmete haldamine käib vastava funktsionaalse allsüsteemi kaudu. Mõeldes kasutajaliidesele, siis kuidas peaks toimuma põhiliselt laoseisude haldamine? Kui nii, et otsitakse konkreetne kaup ja siis registreeritakse selle kauba kogused erinevates ladudes, siis kuulub Kauba laoseis kaupade registrisse. Kui nii, et otsitakse konkreetne ladu ja siis registreeritakse selles laos olevate kaupade kogused, siis kuulub Kauba laoseis ladude registrisse. Millisele teisele olemitüübile viidatakse olemitüübi nimes või kui viidatakse kahele erinevale olemitüübile, siis millise nimi on esimene? Kui nimi on Kauba laoseis või Kaup laos, siis ilmselt kuulub see olemitüüp kaupade registrisse. Kui nimi on Lao kaup, siis ilmselt kuulub see olemitüüp ladude registrisse. Kas peaks saama kustutada konkreetse kauba andmed, kui selle kaubaga on seotud ladusid? Kui jah, siis see on märk, et Kauba laoseis kuulub kaupade registrisse. Kas peaks saama kustutada konkreetse lao andmed, kui selle laoga on seotud kaupasid? Kui jah, siis see on märk, et Kauba laoseis kuulub ladude registrisse. On ka võimalik, et vastus küsimusele 1 on "ei". Küsimusele 2 on vastus, et mõlemat pidi peab saama. Vastused küsimustele 4 ja 5 on kas mõlemad "jah" või mõlemad "ei". See on tunnus, et olemitüübi Kauba laoseis paigutuse registrisse saab vabalt valida.Antud juhul paigutaksin ma olemitüübi Kauba laoseis kaupade registrisse. ## Küsimus: Milleks läheb vaja kontseptuaalses andmemudelis olevaid olemitüüpide ja atribuutide definitsioonide tabeleid? **Vastus:** Kontseptuaalse andmemudeli (on ka Teie projektis) üheks osaks on olemitüüpide ja atribuutide definitsioonid. Seal tuleb täpselt lahti selgitada, milliste andmete vajadusele kontseptuaalne andmemudel osundab. Näiteks hotelli "ruum" - kas mõeldakse kõiki ruume (ka köök ja fuajee) või ainult ööbimiseks mõeldud numbritubasid või hoopis numbritubades sisalduvaid ruume (vannituba, hoiuruum, eluruum). Näiteks kauba "tootja" - kas mõeldakse brändi (nt Apple, Olympus) või hoopis tehast, mis selle kauba kokku paneb. Kontseptuaalne andmemudel ning olemitüüpide ja atribuutide definitsioonid osutuvad näiteks kasulikuks siis, kui on vaja hakata andmeid integreerima - erinevates andmebaasides olevatest andmetest tervikpilti kokku panema. Siis on näiteks vaja aru saada, kas "Klient" andmebaasis A ja "Klient" andmebaasis B on üks ja sama asi või mitte. Lõpetuseks näide tänasest päevast, mis osutab infosüsteemide vahelise koostöö ja andmete integreerimise vajadusele. Intervjuu ajal justiitsminister olnud Urmas Reinsalu hinnangul pole normaalne olukord, kus tagaotsitav võib saada endale autojuhiload kätte. "Esimene loogiline lahendus peaks e-riigis olema suuremate andmebaaside omavaheline seotus, et kui tagaotsitav isik ilmub kasvõi e-tervisesüsteemi, siis lööb punane tuluke põlema," leidis Reinsalu. (Reinsalu: korduvalt karistatud inimesi tuleks vähemal määral usaldada. ERR Uudised 10.03.2016) ## Küsimus: Milleks läheb vaja olemitüüpide ja atribuutide tähenduse e semantika kirjeldusi? **Vastus:** Olemitüüpide ja atribuutide definitsioonid: aitavad saavutada arenduse osalistel ühise arusaama valdkonna mõistetest, aitavad luua kasutajaliidest ja kasutusjuhendeid, on aluseks valikute tegemisel andmebaasi andmestruktuuride disainimise e tehnilise kavandamise käigus, on vajalik sisendinfo, kui soovida erinevatest allikatest saadud andmeid kokku panna e integreerida (näiteks, kas klient andmebaasis A on sama, mis tarbija andmebaasis B?). Toon näiteid selle kohta, kui selline informatsioon puudus.1. Bakalaureusetöös "Ettevõttesisese tarkvara täiendamine - kasutajaliidese ja andmebaasi kavandamine ning sobivuse hindamine" täiendatakse ettevõttesisest tarkvara inimressursside planeerimise funktsionaalsusega. Lõputöös pakutakse välja uue funktsionaalsuse jaoks vajalik kasutajaliides ning samuti andmebaasi täiendused . Selleks, et neid täiendusi saaks välja pakkuda, tuli kõigepealt aru saada, milliseid andmeid täiendatava tarkvara andmebaasi juba kogutakse. Näiteks, kui tahta kasutajale uues kasutajaliideses mingit aruannet kuvada, siis peab teadma, kas vajalikke lähteandmeid võimaldab olemasolev tarkvara juba koguda või tuleb nende andmete kogumise võimalus alles lisada.  Paraku selgus töö tegemise käigus, et olemasoleva andmebaasi dokumentatsioon puudus täielikult. Seetõttu tuli töö tegemise käigus olemasolev andmebaas dokumenteerida ja see võttis palju aega. 40% töö tegemiseks kulunud ajast oli pühendatud dokumenteerimisele, mille alla kuulus ka olemasoleva andmebaasi dokumenteerimine. Töö üks autor kirjutas  (lk 134): "Kõige keerulisemaks osutus olemasoleva andmebaasi dokumenteerimine, eelkõige andmeväljade defineerimine. Esmalt oli keeruline leida ettevõttes isikut, kes oskaks konkreetse andmebaasi kohta detailset informatsiooni jagada. Samuti selgus hiljem, et nii mõndagi tabelit andmebaasis enam ei kasutatagi."2. Bakalaureusetöös "E-poe andmete migreerimine PostgreSQL andmebaasist Microsoft SQL Serveri andmebaasi" kirjutatakse e-poe tarkvara uuendamise käigus toimuvast andmete ülekandmisest PostgreSQL andmebaasist MS SQL Serveri andmebaasi. Lähteandmebaas oli osa valmislahendusest ehk karbitootest ja sihtandmebaas oli ettevõtte enese arendajate käsitöö. Selleks, et ülekannet läbi viia, oli vaja saada aru, milliseid andmeid hoitakse lähteandmebaasis ja milliseid sihtandmebaasis. Ettevõttel puudus nende andmebaaside kohta dokumentatsioon ja autor pidi kulutama märkimisväärse osa töö tegemise ajast selle dokumentatsiooni loomisele. Alles siis kui see töö oli tehtud, sai hakata koostama vastavustabeleid lähte- ja sihtandmebaasi tabelite/veergude vahel ning seejärel kirjutama andmete ülekandeks mõeldud SQL lauseid.3. Bakalaureusetöös "EE Tele2 müügiandmete andmetabelite kvaliteedikontroll ja dokumenteerimine" kontrolliti ja parandati Tele2 olulise müügiprogrammi 4sale poolt kasutatud andmetabelites olevate andmete kvaliteeti. Ka selle töö tegemise käigus selgus, et müügiprogrammi aktiivselt kasutavad tabelid (61 kokku) olid korralikult dokumenteerimata (töö sellega algas ettevõttes alles 2020. aastal) ja töö pühendas suure osa ajast selle dokumentatsiooni loomisele. Autor kirjutas: "Puuduliku 4sale dokumentatsiooni tõttu lisatakse loodavatesse raportitesse andmed teistest schemadest, asendades 4sale tabelite puuduvaid andmeid. Selliselt toimides tekib olukord, kus saadakse sarnased andmed teistest keskkondades, mille korral andmete terviklikus ei ole kindel." Puuduva dokumentatsiooni koostamiseks kulus kolm nädalat. Kuna tabelite haldajad ei osanud kõigile küsimustele ise vastata, pidi autor taotlema juurdepääsu nendele tabelitele, et vajalikud vastused saada. Samuti pidi autor suhtlema juba töölt lahkunud andmeanalüütikutega. Konsultatsiooni käigus selgus, et puudub ülevaade tabelitest, mida aktiivselt enam ei täiendata. Dokumentatsiooni koostamiseks (andmebaasis olevate andmete tähendusest arusaamiseks) pidi autor võrdlema andmetabelite sisu 4sale rakenduses kuvatava infoga (milline andmebaasis olev väärtus on rakenduses mis väljas). Osad tabelid ja veerud jäidki tundmatuks ja nende tähenduse teada saamiseks tuleks suhelda 4sale arendajatega.4. Magistritöös "E-kaubandusettevõtte X andmekvaliteedi analüüs ja parendamine" oli eesmärgiks saavutada väikese e-kaubandusettevõtte andmekvaliteedi püsiv paranemine. Selleks võeti kasutusele Eesti riigi infosüsteemi andmekvaliteedi juhtimise raamistik, seda vastavalt vajadusele kohandades. Töö tulemusena viidi ettevõtte andmekvaliteet esimeselt (kõige madalamalt) küpsustasemelt (reaktiivselt tasemelt) kolmandale küpsustasemele (viietasemelisel skaalal) e standardiseeritud tasemele. Ettevõte peab e-poodi kasutades ülipopulaarset sisuhaldussüsteemi WordPress ja selle pistikprogrammi WooCommerce.  Ettevõtte andmebaas moodustus WordPressi ning selle pistikprogrammide tabelitest. W3techs andmete järgi oli 2023. aasta novembri seisuga sisuhaldussüsteemi WordPressi turuosa sisuhaldussüsteemide hulgas 62.2% (aastaga vähenes turuosa kaks protsendipunkti). 43% maailma veebisaitidest olid loodud WordPressi põhjal. WordPressil põhineva WooCommerce tarkvaral oli suurim – 29% suurune – turuosa e-poe tarkvarade hulgas. Ja ometigi tuli kohe töö tegemise algul välja, et WooCommerce ja WordPress andmebaasi dokumentatsioon on ebapiisav - laiali erinevates kohtades, erineval viisil esitatud ning tabelite ja veergude vabatekstilised kirjeldused olid nendes olevate andmete tähenduse mõistmiseks mõnikord ebapiisavad. Samas, kui tahta hakata parandama andmekvaliteeti, siis tuleb kõigepealt aru saada milliseid andmeid üldse kogutakse, mis on nende andmete tähendus ja millised võimalikud piirangud kehtivad andmeväärtustele. Seetõttu kulus märkimisväärne osa töö tegemise ajast tabelite ja veergude tähendusest arusaamisele ja selle vabatekstilise kirjeldusena kirja panemisele. Töö autor dokumenteeris need ettevõtte wikis, et ettevõtte töötajatel oleks tulevikus ühes kohas koos olev dokumentatsioon andmebaasi kohta. **Märksõnad:** kontseptuaalne andmemudel, Wordpress, WooCommerce ## Küsimus: Millised on erinevad tabelite võtmete tüübid ja kuidas need on omavahel seotud? **Vastus:** Supervõtmel peab olema: - unikaalsuse omadus.   Kandidaatvõtmel peab olema: - unikaalsuse omadus JA - mitteliiasuse omadus. Mitteliiasus tähendab, et sealt ei saa enam ühtegi veergu ilma unikaalsuse omadust kaotamata eemaldada.   Kõik kandidaatvõtmed on supervõtmed. Iga supervõti ei pruugi olla kandidaatvõti. Kandidaatvõtme kohta öeldakse mõnikord ka minimaalne supervõti.Andmebaasis tuleb jõustada (primaar- ja alternatiivvõtmetena) kandidaatvõtmed.Primaarvõti e esmasvõti on kandidaatvõti, mis on teiste kandidaatvõtmete hulgast esile tõstetud (võrdseim võrdsete seas).Nii nagu riigil on korraga maksimaalselt üks kuningas või president on ka tabelis korraga maksimaalselt üks primaarvõti.Alternatiivvõtmed on kõik need kandidaatvõtmed, mis ei saanud primaarvõtmeks. **Märksõnad:** kandidaatvõti, võtmekandidaat, supervõti, primaarvõti, esmasvõti, alternatiivvõti, võti ## Küsimus: Milliseid probleeme tekitab andmete liiasus operatiivandmete andmebaasides? **Vastus:** Andmete liiasus tähendab, et sama fakti on võimalik andmebaasist tuletada kahel või rohkemal erineval viisil. Andmete liiasus tähendab, et andmemaht suureneb, andmete muutmiseks tuleb teha rohkem tööd ja andmebaasi võivad tekkida mittekooskõlalised väited. Toon näite Tallinna Tehnikaülikooli õppeinfosüsteemi (ÕIS) põhjal. ÕISis tuleb aine deklareerimise (õpingukavasse valimise) võimaldamiseks defineerida aine-õppejõu paar. Kui selline paar on loodud, siis vastavat õppejõudu näidatakse ÕISis ainekaardil ainet õpetava õppejõuna. Samal ajal on süsteemis tunniplaanid, kus näidatakse milliseid õppeained õppejõud semestris õpetab. See pole aine-õppejõu paaridega seotud. Seega info, milline õppejõud õpetab semestris millist ainet, on dubleeritud - aine-õppejõud paaris ja tunniplaanis. Kui aine-õppejõu paar on süsteemis veel loomata, siis tekib olukord, kus tunniplaanis on õppejõud ainega seotud, kuid ainekaardil ei ole. See tekitab süsteemi kasutajates (üliõpilastes) segadust, sest nad ei saa aru, kas õppejõud õpetab järgmisel semestril mingit ainet või mitte. ## Küsimus: Milliseid täiendusi tuleb arenduse tulemites (mudelid, andmebaas+rakendus) teha, kui tekivad uued nõuded, mida rakendus peab realiseerima? **Vastus:** Süsteemiarenduse tulemid (artefaktid) on omavahel läbipõimunud. Muutes ühte, on vaja muuta ka paljusid teisi. Toon näite. Vastuvõtuaegade süsteemis lisandus nõue, et vastuvõtt võib toimuda Interneti vahendusel, st mitte enam kindlas ruumis füüsiliselt kohtudes. Lahenduseks on, et info virtuaalse kohtumise kohta pannakse kirja vastuvõtu kommentaari ning kui vastuvõtul puudub ruum, siis peab sellel olema kommentaar.Tegin süsteemiarenduse tulemites järgmised muudatused.Muutused mudelites. Lisandus ärireegel: "Kui vastuvõtt toimub Internetis, siis tuleb see kirjutada vastuvõtu kommentaari. Igal vastuvõtul peab olema registreeritud vähemalt üks kahest – ruum võikommentaar." Olemi suhte diagrammil muutus võimsustik: [Vastuvõtt]-0..*-------------------1-[Ruum] => [Vastuvõtt]-0..*-------------------0..1-[Ruum] Muutus ja dokumendis tuli asendada nii kontseptuaalse andmemudeli eskiismudeli diagramm kui ka vastuvõtuaegade registri detailanalüüsi täpsusega olemi-suhte diagramm. Kontseptuaalse andmemudeli atribuutide definitsioonis lisandus Vastuvõtt atribuudile kommentaar kitsendus: {Vähemalt üks kahest – ruum võikommentaar peab olema registreeritud.} Muutusid detailanalüüsi täpsusega kasutusjuhtude kirjeldused - vastuvõttude nimekirjas tuleb nii õppejõule kui üliõpilasele lisaks vastuvõtu hoonele/ruumile näidata ka vastuvõtu kommentaari. Andmebaasi disaini mudelis muutus tabeli Vastuvott veerg ruum_id mittekohustuslikuks. Andmebaasi disaini mudelis tuli kirjeldada CHECK kitsendus, mille kohaselt igas tabeli Vastuvott reas peab olema määratud vähemalt üks kahest - kommentaar või ruum_id. Vastuvõtuaegade registri muutunud disaini diagramm tuli dokumendis asendada. Muutused realisatsioonis. Tabeli Vastuvott veerult ruum_id tuli kustutada NOT NULL kitsendus. Tabelile Vastuvott tuli luua valideerimisreegel, mille kohaselt igas tabeli Vastuvott reas peab olema määratud vähemalt üks kahest - kommentaar või ruum_id. Vastuvõttude nimekirjavormidele tuli lisada ka vastuvõtja kommentaari väli, et nimekirja vaataja näeks kohe, et vastuvõtt toimub Internetis. Vastuvõtu lisamise/muutmise vormile tuli lisada abitekst selle kohta, et kui vastuvõtt toimub Internetis, siis peab selle kirjutama kommentaari. Muutused testides. Kui need oleksid loodud peaks muutma ka neid. ## Küsimus: Mis andmeid võiks registreerida tanklate kohta? Millised võiksid olla tanklaga seotud klassifikaatorid? Kas tanklat pidav organisatsioon võiks olla üks tanklaga seotud klassifikaator? **Vastus:** Näited andmetest, mida üks register kogub erinevate ettevõtete peetavate tanklate kohta: https://kytus.envir.ee/source-of-pollution/view/146241Olemitüübi Tankla tekstiliste atribuutide näiteid: Aadress Lahtiolekuajad Olemitüübi Tankla arvuliste atribuutide näiteid: X-koordinaat Y-koordinaat Olemitüübiga Tankla seotud klassifikaatorite näiteid: Tankla tüüp (automaatne, operaatoriga) Müügi tüüp (jaemüük, hulgimüük) Vald/Linn Selle registreerimiseks kasutatakse Eesti haldus- ja asustusjaotuse klassifikaatorit https://et.wikipedia.org/wiki/Eesti_haldus-_ja_asustusjaotuse_klassifikaator Tankla võiks olla seotud valla või linnaga ja see omakorda maakonnaga Tanklat pidava ettevõtte andmed tuleks andmebaasis siduda tankla andmetega kui tegemist oleks tanklate registriga, kus on andmed erinevate tanklapidajate tanklate kohta (võivad kuuluda erinevatele ettevõtetele). Sellisel juhul oleks selle registreerimiseks valida, et 1) registreerida ettevõtted kui klassifikaatorid või 2) kui organisatsioonid (olemitüüp Organisatsioon, mis on seotud olemitüübiga Tankla). Variant 1:[Klassifikaator]<|----------[Tanklaoperaator]-1--------0..*-[Tankla]Variant 2:[Organisatsioon]-1-+tanklaoperaator--------0..*-[Tankla]Valik sõltub sellest, kas tanklapidajatel on süsteemis teistsugused võimalikud seisundid (st andmete haldamise protsess) kui muudel klassifikaatoritel. Kui ei ole, siis sobib variant 1, kui on, siis tuleks valida variant 2. Kui teete ühe konkreetse tanklaoperaatori infosüsteemi, siis pole Tanklaoperaator eraldi olemitüüp/klassifikaator. Vastuse alguses viidatud süsteemis on Organisatsioon eraldi olemitüüp (st tanklapidaja ei ole klassifikaator). Organisatsioonil on antud juhul seisund e staatus "aktiivne". Selle registreerimiseks on kasutatud seisundiklassifikaatorit Organisatsiooni_seisundi_liik. ## Küsimus: Mis asi on register? **Vastus:** Andmebaas on nagu päikesesüsteem. Päikese rollis on organisatsiooni eesmärgid. Kõik mis organisatsioonis IT vallas (sh andmebaasidega) tehakse, peab olema nende eesmärkide teenistuses, mitte vastupidi. Seega planeedid (andmebaasi osad) tiirlevad ümber päikese (organisatsiooni eesmärkide), mitte vastupidi. Päikese ümber tiirlevad planeedid vastavad põhiobjektidele e põhiolemitüüpidele. Planeetide ümber tiirlevad omakorda kaaslased e kuud, mis vastavad mitte-põhiobjektidele. Iga planeet-planeedi kaaslased süsteem vastab andmebaasi äriarhitektuuris ühele registrile. Nii nagu iga kuu tiirutab ümber kindla planeedi on ka iga mitte-põhiobjekt kindla registri tiiva all. Igal planeedil on null või rohkem kuud; igal põhiobjektil on null-või rohkem samasse registrisse kuuluvat mitte-põhiobjekti. Lisaks planeetidele tiirutavad ümber päikese ka asteroidid. Neist võib andmebaaside analoogias mõelda, kui andmestruktuuridest, mis on vajalikud ühe või teise rakenduse töö hõlbustamiseks, kuid mis ei kuulu ühtegi registrisse (nt disainitaseme abitabelid). Ümber planeetide (hetkel teadaolevalt ainul Maa, aga hiljem miks mitte ka mõni teine planeet) tiirutavad kunstlikud tehiskaaslased, mis on sinna planeedi asukate poolt saadetud, kuid mingil hetkel planeedile tagasi langevad ja selle käigus ära põlevad. Need on nagu registris olevad ajutiste andmetega andmestruktuurid, mida läheb vaja mingi konkreetse ülesande (nt konkreetse päringu) täitmiseks, kuid mis millalgi oma otstarbe kaotavad ja seega võib eemaldada. Nii nagu andmebaas või meie arusaam selle ülesehitusest ajas muutub, muutub ka päikesesüsteem (nt planeet püüab gravitatsiooni mõjul kinni mõne pisitaevakeha, mis muutub selle planeedi kuuks) või meie arusaam sellest (nt muutub arusaam sellest, millised taevakehad kuuluvad planeetide hulka). Nii nagu kunagi kustub päike, nii saab kunagi otsa ka organisatsiooni ja selle IT-süsteemide (sh andmebaasisüsteemi toega andmebaasi) elukaar. ## Küsimus: Mis erinevus on primaarvõtme ja kandidaatvõtme vahel? **Vastus:** See on nagu organisatsioonile juhi valimised. Oletame, et on kolm kandidaati. Üks valitakse peadirektoriks. Tema saab ametiauto ja eraldi kabineti. Ülejäänud kaks ei saa peadirektoriks, kuid saavad asedirektori tiitli ning samuti ametiauto ja eraldi kabineti.Igas tabelis on üks või rohkem kandidaatvõtit e võtmekandidaati (candidate key). Üks nendest kuulutatakse primaarseks e esmaseks võtmeks e primaarvõtmeks. Ülejäänud on alternatiivsed võtmed e alternatiivvõtmed.Primaarvõti deklareeritakse kasutades PRIMARY KEY kitsendust.Alternatiivvõtmed deklareeritakse, kasutades UNIQUE + NOT NULL kitsendusi.Näiteks oletame, et tabelis Amet on kaks kandidaatvõtit: (amet_kood) ja (nimetus)(amet_kood) valitakse primaarseks.Tabeli loomise lauses: CONSTRAINT pk_amet_kood PRIMARY KEY (amet_kood)(nimetus) jääb alternatiivseks.Tabeli loomise lauses: CONSTRAINT ak_amet_nimetus UNIQUE(nimetus)Lisaks on veerul nimetus NOT NULL kitsendus. Miks NOT NULL kitsendus? Primaarvõtme veerud on automaatselt kohustuslikud - primaarvõtme väärtus ei tohi üheski reas puududa. Kuna võti on võti, siis pole alternatiivvõtmed halvemad ja ka nende väärtus ei tohiks üheski tabeli reas puududa.Seos teiste tabelitega luuakse tavaliselt primaarvõtme alusel - selleks, et tabelis Töötaja registreerida töötaja hetke amet, registreeritakse seal ameti kood, mitte ameti nimetus. **Märksõnad:** primaarvõti, kandidaatvõti, esmasvõti, võtmekandidaat ## Küsimus: Mis on intelligentne võti ja millal seda kasutada? **Vastus:** Üheks SQL tabelite võtmete liigiks on intelligentsed võtmed. Selliste võtmete väärtused omavad inimkasutajale sisulist tähendust ning võtme väärtusesse on kodeeritud informatsiooni. Sellise võtme näiteks on isikukood. Näiteks nii Eestis kui Soomes sisaldab see infot sünniaja ja soo kohta. Intelligentse võtme kasutamise väljakutseks on, et kui kodeering muutub, tuleb kõik sellest kodeeringust sõltuvad programmid ümber teha. Sellise võtme probleeme illustreerib hästi juhtum Rootsist, kus isikukoodid said suure pagulaste tulva tõttu otsa. Kuna ka Eesti isikukoodi osaks on järjekorranumber samal päeval sündinute eristamiseks, siis samasugune probleem võib tabada ka Eestit. Seda näiteks siis, kui e-residentsuse programm osutub ootamatult edukaks, sest ka e-residendid saavad isikukoodi. Viimaste uudiste kohaselt on Soomes arutusele tulnud kodeeringu muutmine. Põhjus on nii koodide otsalõppemine (vana skeem ei võimalda kõigile isikukoodi vajajatele unikaalset koodi genereerida) kui ka soov sooneutraalsuse järele. Moraal - koode, mis on "kõrgemalt poolt" (riik, standardiseerimisega tegelev organisatsioon, ettevõtte peakontor jne) ette kirjutatud tuleb kasutada, kuid ise ei peaks selliseid koode leiutama hakata. ## Küsimus: Mis on (lihtsalt selgitades) normaliseerimine ja normaalkujud? **Vastus:** Normaliseerimine on nagu mäetipp, mille otsas on auhind. Auhinnaks on see, et andmete liiasust (mis aeglustab ja muudab keerukamaks andmete muutmist) on andmebaasis vähem kui mäe jalamil (aga seda ikkagi on - see pole midagi, millest ühe tipu vallutamisega pääseb). Tipule vastab (SQL-andmebaaside näitel) viies normaalkuju ning mäe nõlval on peatuskohad, mis vastavad erinevatele madalamatele normaalkujudele (sealhulgas ka Boyce/Coddi normaalkuju). Praktikule, keda tulemus huvitab rohkem kui protsess, on lõpuks oluline jõuda tippu. Sinna saab erinevatel viisidel - kas mööda mäekülge üles ronides ja peatuskohtades peatudes (viies tabeleid järk-järgult üha kõrgematele normaalkujudele) või ka lennukist/kopterist langevarjuga hüpates, tipule või selle lähedale maandudes ja GPSiga kontrollides, kas sai tipule pihta või mitte (kas kõik tabelid on viiendal normaalkujul). Hüppamine on nagu mustrite põhjal loodud kvaliteetsest kontseptuaalsest andmemudelist andmebaasi disaini kirjelduse genereerimine.  Lihtsalt öeldes tähendab viies normaalkuju, et tabelit ei saa enam tükeldada väiksemateks ja algse tabeli täpset taastamist võimaldavateks osadeks nii, et tükkides on andmete liiasust vähem. Andmete liiasuse vähendamise mõttes on viies normaalkuju maksimum ja kõige olulisem. On ka kõrgemaid normaalkujusid (nagu kuues), kuid nendeni jõudmisel on juba teised auhinnad (näiteks lihtsam toimetulek puuduvate andmete ja skeemi evolutsiooniga). Enamik tabeleid, mis on kolmandal või Boyce/Coddi normaalkujul (populaarsed peatuskohad mäetipule ronides), on ka viiendal. Selle kohta on sõnastatud ja matemaatilised reeglid. ## Küsimus: Mis on olemitüüp, atribuut ja olem? **Vastus:** Kogu selle temaatika juures on suureks probleemiks terminoloogiline segadus. Näiteks erinevate autorite tekstides tähistavad järgnevad sõnad (terminid) sisuliselt sama mõistet. Klass Objektitüüp Olemitüüp Olem Põhiobjekt Näiteks erinevate autorite tekstides tähistavad järgnevad sõnad (terminid) sisuliselt sama mõistet. Objekt Objekti eksemplar Olem Eksemplar Olemi eksemplar Eriti halb on, kui neid sõnu kasutatakse läbisegi. Näiteks üks räägib olemitest ja olemi eksemplaridest, teine olemitüüpidest ja olemitest, kolmas objektidest ja objekti eksemplaridest, neljas klassidest ja objektidest, kuigi tegelikult mõtlevad nad sama asja. Samasugune probleem on seostega. Üks räägib seosetüüpidest ja seostest, teine seostest ja seoste eksemplaridest ning kolmas seosetüüpidest ja seoste eksemplaridest, kuigi tegelikult mõtlevad nad sama asja. Selline terminoloogiline segadus on paraku reaalsus. Näide, kus üritan seda terminoloogiat järjekindlalt kasutada. Reaalses maailmas on isik (omaduste e atribuutidega) (meiliaadress, mis ühtlasi eristab seda isikut kõigist teistest isikutest e on tema unikaalne identifikaator=)mari.maasikas2@hot.ee (eesnimi=)Mari (perenimi=)Maasikas. Reaalses maailmas on isik (omaduste e atribuutidega) (meiliaadress, mis ühtlasi eristab seda isikut kõigist teistest isikutest e on tema unikaalne identifikaator=)juhan.juurikas@hot.ee (eesnimi=)Juhan (perenimi=)Juurikas. Reaalses maailmas on Mari Maasikas Juhan Juurika ülemuseks. Nende tähelepanekute alusel sõnastab andmebaasi kavandaja kontseptuaalses andmemudelis vajaduse hoida andmebaasis isikute andmeid (meiliaadress, eesnimi, perenimi ning kes on kelle ülemus). Selleks kirjeldab ta seal olemitüübi Isik, millel on atribuudid e_meil, eesnimi ja perenimi. See vajadus joonistatakse UML keele klassidiagrammi abil loodud olemi-suhte diagrammile üles luues seal klassi Isik ja määrates sellele atribuudid e_meil, eesnimi ja perenimi. Kontseptuaalses andmemudelis ei modelleerita olemeid (Juhan Juurikas või Mari Maasikas), vaid nende üldistust (Isik). Samuti modelleeritakse olemi-suhte diagrammil seosetüüp on ülemus, mille mõlemad otsad on seotud klassiga Isik. Kontseptuaalses andmemudelis ei modelleerita seoseid (Mari Maasikas on Juhan Juurika ülemus), vaid nende üldistust (on ülemus). Kontseptuaalses andmemudelis sõnastatud nõude rahuldamiseks luuakse SQL-andmebaasis tabel Isik, kus on veerud e_meil, eesnimi ja perenimi + välisvõtme veerg ylemuse_id. Iga rida, mis sellesse tabelisse lisatakse, peab vastama selle tabeli päisele (mis määrab isiku kohta andmebaasis kogutavad andmed). Iga rida on kujutus/peegeldus reaalse maailma olemist (nt reaalsest lihast ja luust Juhan Juurikast). Reaalse maailma olem (nt kindel füüsiline isik) ja tema kujutis süsteemis (nt rida tabelis, JSON dokument või XML dokument) on tegelikult ju kaks ise asja, aga kõnekeeles ollakse sageli lühiduse huvides ebatäpsed ja räägitakse lihtsalt olemitest ja nende andmetest. ## Küsimus: Mis vahe on identifitseerival ja mitteidentifitseerival seosel tabelite vahel? **Vastus:** Identifitseeriv seos tähendab, et vanemtabeli reas olev võtmeväärtus aitab identifitseerida lapstabelis olevat rida. Seetõttu on vanemtabeli võti, mis on lapstabelis välisvõtmeks, osaks lapstabeli võtmest. Teiste sõnadega, lapsel pole oma identiteeti, vaid ta on identifitseeritav vanema kaudu, laps ei saa eksisteerida ilma vanemata ja koos vanemaga tuleks kustutada ka laps. Eelnevast nähtub, et selliste seoste puhul tuleks määrata kompenseeriv tegevus ON DELETE CASCADE.Näiteks oletame, et igal isikul on null või rohkem meiliaadressi ja null või üks kasutajakonto. Need on andmed isiku kohta, kuid on pandud eraldi tabelitesse (Meiliaadress ja Kasutajakonto), mis on välisvõtme kaudu seotud tabeliga Isik. Seosed tabelite Isik ja Meiliaadress ning Isik ja Kasutajakonto vahel on identifitseerivad seosed.Isik(isik_id, perenimi)Primaarvõti (isik_id)Meiliaadress(isik_id, e_meil)Primaarvõti (isik_id)Alternatiivvõti (e_meil)Välisvõti (isik_id) Viitab Isik (isik_id)Kasutajakonto(isik_id, parool, on_aktiivne)Primaarvõti (isik_id)Välisvõti (isik_id) Viitab Isik (isik_id)Kontseptuaalses andmemudelis öeldakse olemitüüpide Meiliaadress ja Kasutajakonto kohta, et need on nõrgad olemitüübid (weak entity types).   Mitteidentifitseeriv seos tähendab, et last ei identifitseerita vanema kaudu, lapsel on oma identiteet ja nende vahel ei ole eksistentsiaalset sõltuvust. Vanemtabeli võti ei ole osa lapstabeli võtmest ja vastava välisvõtme puhul ei kasutata ON DELETE CASCADE.Isik(isik_id, perenimi)Primaarvõti (isik_id)Tellimus (tellimuse_kood, tellija, summa)Primaarvõti (tellimuse_kood)Välisvõti (tellija) Viitab Isik (isik_id) ## Küsimus: Märkasin et te kirjutate SQL muutujaid eesti keeles, näiteks "nimi VARCHAR(10)". Arvestades et kõik ettevõtted ning arendajad kirjutavad tänapäeval muutujaid ja koodi inglisekeelselt, kas ma võin ka praktikaülesannetes ning iseseisvas töös kasutada inglise keelt? **Vastus:** Kui Te mõtlete iseseisvat tööd, siis loomulikult võite koodis kasutada ingliskeelseid nimesid. Töö tegemisel tuleb juurde lisasamm, kus kontseptuaalsest andmemudelist genereeritud tabelite kirjelduses tuleb nimed tõlkida. Mis puudutab praktikaülesannetes andmete otsimise või muutmise lausete kirjutamist, siis seal on kirjutaja piiratud nimedega, mis on andmebaasis kasutusel. Mis puudutab praktikaülesandeid muuta olemasoleva andmebaasi struktuuri (lisada tabeleid, veerge, kitsendusi), siis kasutada ühes andmebaasis läbisegi erinevaid keeli ei ole ilus ega ka kooskõlas puhta koodi põhimõtetega. Tahan rõhutada et kõik puhta koodi (sh nimetamise) üldpõhimõtted kehtivad sõltumata kasutatavast inimkeelest. Eesti keel on keel nagu iga teinegi ja sobib asjade nimetamiseks täpselt sama hästi. Seega minu arvates ei ole õigustatud arvamus, et andes asjadele nimesid eesti keeles õpime või teeme midagi valesti. Olulisemad on põhimõtted (ainsus vs. mitmus, snake_case vs. PascalCase vs. camelCase, regulaarne vs. piiritletud identifikaator), kui see, mis inimkeeles on see nimi kirjutatud. Aga veelkord - oma iseseisva töö projektis kasutage nimetamise stiili, mida ise paremaks peate. Peaasi, olge järjekindel.Kontseptuaalne andmemudel kirjeldab nõudeid. Nõuded tulevad süsteemi tellijatelt ja kasutajatelt. On täiesti loomulik, et nõuded esitatakse keeles, mis on tellijatele ja kasutajatele hästi arusaadav. Kui kasutate tabelite/veergude/kitsenduste nimetamisel inglise keelt, kuid kontseptuaalses andmemudelis eesti keelt, siis võiks kontseptuaalse andmemudeli olemitüüpide ja atribuutides definnitsioonide juures olemitüüpide ja atribuutide nimed olla nii eesti keeles kui ka sulgudes inglise keeles. **Märksõnad:** identifikaator, nimi, nimetamine ## Küsimus: Otsin omale põnevat lugemist andmebaaside (pigem relatsiooniliste, aga miks mitte ka teiste) antimustrite kohta. Mäletan Teiega andmebaaside kursust läbides, et erinevate materjalide nimed käisid läbi, aga mõtlesin küsida soovitust otse allikast. Mida võiks lugeda? Soovitatavalt võiks materjal olla inglise keeles (saaks jagada ka mitte-eestlastega), aga endale huvi pärast lugemiseks oleks eestikeelne materjal ka väga kasulik. Soovitused on teretulnud nii veebilinkide, dokumentide kui raamatusoovituste kujul. **Vastus:** Antimuster klassikalises mõttes on struktuurse kirjutamise viis, kus lisaks probleemile ja selle halvale lahendusele tuuakse välja ka see, kuidas seda probleemi paremal viisil lahendada ning ka see, millisel juhul võib halb lahendus osutuda väljakannatatavaks. SQL-andmebaaside disaini sagedased probleemid on antimustritena raamatusse kirja pannud Bill Karwin. Tema raamatut saab laenutada ülikooli raamatukogust (https://www.ester.ee/record=b2888667*est), seda saab lugeda O'Reilly digitaalselt platvormilt (https://learning.oreilly.com/library/view/sql-antipatterns/9781680500073/?ar; sellele on Tehnikaülikooli üliõpilastel juurdepääs).   Siis on olemas tasuta raamat kus kirjeldatakse 150-t võimalikku disainiprobleemi MS SQL Server andmebaasides: https://assets.red-gate.com/community/books/sql-code-smells.pdf Mõned nendest probleemidest on spetsiifilised MS SQL Serveri jaoks, kuid enamik võib esineda mistahes SQL-andmebaasides. Probleemide kirjeldamisel ei kasutata mustri formaati.Siia on kirja pandud viis viga, mida SQL-andmebaasi disainimisel tuleks üritada vältida: https://www.red-gate.com/simple-talk/databases/sql-server/database-administration-sql-server/five-simple-database-design-errors-you-should-avoid/   Mis puudutab NoSQL süsteeme, siis neid iseloomustab standardite puudus (kuid see on näiteks graafiandmebaaside puhul muutumas: https://www.gqlstandards.org/) ja lugemise skeemi eelistamine kirjutamise skeemile (andmete struktuuri ei kirjeldata andmebaasi tasemel ja andmebaasisüsteem ei kontrolli andmete struktuurile vastavust andmete salvestamisel) (kuid ka see on muutumas). Tulemuseks on, et turule jõudnud kümnetes, et mitte öelda sadadest NoSQL süsteemidest tehakse igaühes asju omamoodi ja paljusid süsteeme läbivaid disaini probleeme ei saa / on raske välja tuua. Probleemid ja nende kirjeldused on süsteemi-spetsiifilised. Raamatus "Seven NoSQL Databases in a Week" (Seitse NoSQL süsteemi nädalaga), mida saab O'Reilly keskkonna kaudu lugeda, kirjeldatakse seitset NoSQL andmebaasisüsteemi (https://learning.oreilly.com/library/view/seven-nosql-databases/9781787288867/?ar). Osade süsteemide peatükkides on antimustrite alapeatükk, kus kirjeldatakse lühidalt võimalikke probleeme. Need kirjeldused ei ole mustri formaadis.   Sellest raamatust hakkas valusalt silma tekstilõik: "Neo4j involves appropriately modeling the required queries. Relational modeling requires you to focus on how your data is stored, and not as much on how it is queried or returned." See esitab valeväiteid. Relatsiooniline mudel ei kirjuta ette, kuidas andmebaasisüsteemi tarkvara peab sisemiselt andmeid salvestama. See on andmebaasisüsteemide (mudeli realisatsiooni) küsimus. Mudel ja realisatsioon on kaks ise asja nii nagu projekt või tarkvara või plaan ning plaani täitmine on kaks ise asja. Ühes või teises relatsioonilist mudelit realiseerivas süsteemis võib andmete salvestamine olla tehtud nii, et andmete struktuur ja selle muutmine mõjutab ka andmete käitlemise operatsioonide jõudlust. Kuid see on konkreetse süsteemi realisatsiooni, mitte relatsioonilise mudeli probleem. Konkreetseid süsteeme tutvustavate, mitte üldistest põhimõtetest kirjutavate, allikate häda on selles, et need vananevad väga kiiresti ja saadud teadmine kehtib ühes konkreetses kohas - üks süsteem (sageli ainult mõnes selle kindlas versioonis).   Leidub päris mitmeid teadusartikleid, kus on uuritud SQL-andmebaaside disainiprobleeme. Need artiklid nimetavad probleeme ja uurivad nende esinemist erinevates andmebaasides, kuid probleeme ei esitata mustri formaadis. Nimetan järgnevalt mõningaid artikleid. Google Scholar (https://scholar.google.com/) kaudu otsides leiab nende artiklite avalikud täistekstid.   Blaha, M.: A retrospective on industrial database reverse engineering projects - part 2. In:  Eighth Working Conference on Reverse Engineering, pp. 147–153. IEEE, (2001). https://doi.org/10.1109/WCRE.2001.957818 Vana artikkel 35 SQL-andmebaasi pöördprojekteerimise tulemuste kohta. Nendes oli masendavalt palju puuduvaid kitsendusi. Minu kogemus näitab, et 20 aastat hiljem  pole taolised probleemid andmebaasidest kuhugi kadunud.   Blaha, M.R., Premerlani, W.J.: Observed idiosyncracies of relational database designs. In: 2nd Working Conference on Reverse Engineering, pp. 116–125. IEEE, (1995). https://doi.org/10.1109/WCRE.1995.514700 Jällegi vana artikkel, kuid siin nimetatud artiklitest üks kõige suurem hulk erinevaid SQL-andmebaasi disainiprobleeme. Paraku, kuna vigadest õppimine pole kombeks, siis see, et artikkel on vana ei tähenda, et neid vigu uutes andmebaasides ei tehta. Weber, J.H., Cleve, A., Meurice, L., Ruiz, F.J.B.: Managing technical debt in database schemas of critical software. In: Sixth International Workshop on Managing Technical Debt, pp. 43–46. IEEE (2014). https://doi.org/10.1109/MTD.2014.17 Puuduvatest välisvõtme kitsendustest ja sellest tulenevast tehnilisest võlast.   Al-Barak, M., Bahsoon, R.: Database design debts through examining schema evolution. In: 8th International Workshop on Managing Technical Debt, pp. 17–23. IEEE, (2016). https://doi.org/10.1109/MTD.2016.9 Esitatakse üks võimalik SQL-andmebaaside disainiprobleemide liigitus ja nimetatakse neid probleeme. Delplanque, J., Etien, A., Auverlot, O., Mens, T., Anquetil, N., Ducasse, S.: CodeCritics applied to database schema: Challenges and first results. In: 24th International Conference on Software Analysis, Evolution and Reengineering, pp. 432–436. IEEE, (2017). https://doi.org/10.1109/SANER.2017.7884648 Muuhulgas tutvustatakse SQL-andmebaaside disainiprobleemide otsimiseks mõeldud tarkvara ning nimetatakse 11 probleemi, mida see tarkvara suudab tuvastada.   Sharma, T., Fragkoulis, M., Rizou, S., Bruntink, M. and Spinellis, D.: Smelly relations: measuring and understanding database schema quality. In: 40th International Conference on Software Engineering: Software Engineering in Practice, pp. 55–64. ACM, (2018). https://doi.org/10.1145/3183519.3183529 Tutvustatakse SQL-andmebaaside disainiprobleemide otsimiseks mõeldud tarkvara. Nimetatakse 13 probleemi, mida see tarkvara suudab tuvastada. Uuritakse nende probleemide esinemist suures hulgas avatud lähtekoodiga süsteemide andmebaasides ja ka nende probleemide koosesinemist (kui esineb üks probleem, siis millised teised sellega sagedasti koos esinevad).   Dintyala, P., Narechania, A., Arulraj, J.: SQLCheck: automated detection and diagnosis of SQL anti-patterns. In: 2020 ACM SIGMOD International Conference on Management of Data, pp. 2331–2345. (2020). https://doi.org/10.1145/3318464.3389754 Muuhulgas tutvustatakse SQL-andmebaaside disainiprobleemide otsimiseks mõeldud tarkvara ning nimetatakse 26 probleemi, mida see tarkvara suudab tuvastada. Foidl, H., Felderer, M., Biffl, S.: Technical Debt in Data-Intensive Software Systems. In: 45th Euromicro Conference on Software Engineering and Advanced Applications, pp. 338 –341. IEEE, (2019). https://doi.org/10.1109/SEAA.2019.00058 Üks oluline mõte on, et viga ühes süsteemi osas võib tekitada probleeme teistes süsteemi osades. Näiteks puuduvad andmebaasi kitsendused vähendavad andmete kvaliteeti ja muudavad keerukamaks ning veaohtlikumaks andmebaasirakenduste realiseerimise. Eessaar, E.: Automating detection of occurrences of PostgreSQL database design problems. In: Robal, T., Haav, H.M., Penjam, J., Matulevičius, R. (eds) Databases and Information Systems. DB&IS 2020. Communications in Computer and Information Science, vol 1243. Springer, Cham. (2020) https://doi.org/10.1007/978-3-030-57672-1_14 Tutvustatakse PostgreSQL andmebaasi disaini kontrollimiseks mõeldud päringute kataloogi (https://github.com/erki77/database-design-queries). Suur osa nendest päringutest (problem detection queries) otsivad andmebaasi disaini probleemide esinemisi ja enamik nendest probleemidest ei ole PostgreSQL-spetsiifilised. Seega on ühtlasi tegemist ka disaini vigade kataloogiga ja selles esitatud päringud on nagu käivitatavad vigade spetsifikatsioonid. Võrreldes eelnevate artiklitega on selles kataloogis palju rohkem disaini probleeme. Balogh, G., Gergely, T., Beszédes, Á., Szarka, A., Fábián, Z.: Capturing expert knowledge to guide data flow and structure analysis of large corporate databases. Acta Polytechnica Hungarica 16(4), 7–26 (2019). Suurte süsteemide, sh andmebaaside analüüsimine tehniliste puuduste osas on keeruline ettevõtmine. Selleks on vaja toetavat tarkvara. Artikkel kirjutab esimestest sammudest, mis on tehtud reeglipõhise analüüsisüsteemi loomise suunas. Brass, S., Goldberg, C.: Semantic errors in SQL queries: A quite complete list. Journal of Systems and Software, 79(5), 630-644. (2006). https://doi.org/10.1016/j.jss.2005.06.028 SQL päringute vigade kataloog. **Märksõnad:** antimuster, anti pattern, muster, pattern ## Küsimus: Teeme projekti töövihiku järgi. Meil on andmebaasis järgmise kontseptuaalse andmemudeli järgi loodud tabelid: [Treening]-1----------0..*-[Treeningu_kategooria_omamine]-0..*---------1-[Treeningu_kategooria] [Treening]-1----------0..*-[Treeningu_põhimõttelise_toimumise_asukoht ]-0..*---------1-[Ruum] Milliste välisvõtmete puhul tuleks kasutada ON DELETE CASCADE ja milliste puhul mitte? **Vastus:** Teie andmebaasis on kaks sarnast (mitu-mitmele seost realiseerivat) tabelit. Treeningu_kategooria_omamine Treeningu_põhimõttelise_toimumise_asukoht Nendes on kokku neli välisvõtit. ON DELETE CASCADE kasutamise üle otsustamisel tuleks mõelda, milline oleks primaartabelist ühe rea kustutamise mõju sõltuvale tabelile. Analüüsin ükshaaval kõiki välisvõtmeid mõttega, et nende puhul oleks määratud "ON DELETE CASCADE". 1. Primaartabel: Treening Sõltuv tabel: Treeningu_kategooria_omamine Kui kustutan rea tabelist Treening, siis kustuvad ainult selle konkreetse treeningu kategooria omamised. Muudatus mõjutab ainult neid, kes kasutavad selle ühe treeningu andmeid. Kustutamine ei sega ega takista teistele treeningutele kategooriate määramist. Võib öelda, et muudatuse mõju on lokaalne. ON DELETE CASCADE toetaks kasutusjuhu Unusta treening läbiviimist. 2. Primaartabel: Treening Sõltuv tabel: Treeningu_põhimõttelise_toimumise_asukoht Sama, mis esimene. 3. Primaartabel: Ruum Sõltuv tabel: Treeningu_põhimõttelise_toimumise_asukoht Kui kustutan rea tabelist Ruum, siis mõjutab see kõiki treeninguid, millele see ruum on asukohaks märgitud (võib olla kümneid või isegi sadu). Võibolla mõni treening jääks üldse ilma ruumita. Kui treeningute haldur on treeningule märkinud ruumi ja siis selgub, et seda ruumi polegi tegelikult olemas või see kaob kasutusest, siis korrektne asjaajamine dikteerib, et treeningute haldurit tuleb sellest informeerida ning temaga koos leida lahendus, millist ruumi ikkagi treeningute jaoks kasutada. Äkki tuleb välja, et mõne treeningu läbiviimiseks ei olegi ühtegi sobivat ruumi ja seda treeningut ei saagi läbi viia (treening tuleb lõpetada või unustada). Võib öelda, et muudatuse mõju on globaalne. ON DELETE CASCADE ei peaks kasutama. Selle asemel sobib ON DELETE NO ACTION. Kui süsteemis on kasutusjuht Unusta ruum, siis ON DELETE NO ACTION aitab jõustada reegli, et kasutuses ruume ei saa unustada (andmeid kustutada), vaid need tuleb lõpetada ja vajadusel lõpetatavale ruumile sobiv asendus leida. 4. Primaartabel: Treeningu_kategooria Sõltuv tabel: Treeningu_kategooria_omamine Kui kustutan rea tabelist Treeningu_kategooria, siis mõjutab see kõiki treeninguid, mis on sellesse kategooriasse määratud (võib olla kümneid või isegi sadu). Võibolla peale seda ei kuulugi enam mõni aktiivne treening ühtegi kategooriasse. See läheb aga vastuollu analüüsi dokumendis seisundidiagrammis väljendatud reegliga, et iga aktiivne treening peab olema seotud vähemalt ühe kategooriaga. Kategooriaid kasutatakse treeningute otsimiseks. Kui treening pole üheski kategoorias, siis ei saa kliendid selle andmeid vaadata (vt kasutusjuhtu Vaata aktiivseid treeninguid). Võib öelda, et muudatuse mõju on globaalne.ON DELETE CASCADE ei peaks kasutama. Selle asemel sobib ON DELETE NO ACTION. Kui süsteemis on kasutusjuht Unusta klassifikaator, siis ON DELETE NO ACTION aitab jõustada reegli, et kasutuses klassifikaatori väärtuseid ei saa unustada (kustutada), vaid need tuleb lõpetada ja vajadusel lõpetatavale väärtusele sobiv asendus leida. ## Küsimus: Teeme töövihiku järgi ning põhiolemiks on hoiuruum. Küsimus: Kas olekudiagrammile oleks loogiline lisada ka "renditud" olek? Mõtlesime selle üle ning tundus, et see viib vastuoluni, et hoiuruum peab olema korraga nii aktiivne kui ka renditud/vaba. (See oleks justkui nagu aktiivse oleku alam-olek). Samas informatsioon selle oleku kohta, kas hoiuruum on välja renditud või vaba on väga vajalik. Kas seda olekut peaks kajastama hoiuruumi seisundi diagrammil või kuskil mujal? **Vastus:** Ei ole vaja kajastada. Jah, kontseptuaalselt on "Renditud" oleku "Aktiivne" alamolek. Andmebaasi mõttes saab kindlaks teha, kas hoiuruum on parajasti renditud või mitte selle kaudu, kui teha päring rentimiste registrisse ja veenduda, kas leidub selle hoiuruumi kehtiv rentimine, mille puhul hetke aeg jääb selle rentimise alguse aja ja lõpu aja vahele. Hoiuruum võib olla täna vaba, järgmine kuu renditud, ülejärgmine kuu jälle vaba. Küsimus - mis seisundis ta siis on - vaba või hõivatud. Praktikas muidugi võiks tahta hoiuruumi lõpetamisel kontrollida, kas sellel on mõni lõpetamata rentimine või mitte. Aga sellisel juhul tuleks projektis ka projekteerida ja realiseerida rentimiste register. Selle tegemine poole keelatud, kuid ei ole ka nõutud.Kokkuvõte:  Seda ei pea seisundidiagrammis kajastama, selle pärast ei pea kasutsjuhtude mudelit muutma ja see jääb käesoleva töö skoobist välja. **Märksõnad:** seisundidiagramm, olekumasin ## Küsimus: Töövihiku järgi on juba olemas klassifikaator Riik, mis on siis seotud kliendiga seoses isikukoodiga. Kui me soovime lisada klassifikaatori Riik ka Pakettreisile, kas sobib kasutada sama klassifikaatorit või peaksime tegema lisaks Pakettreisi_Riik. Pakettreisi_Riigis ilmselt on vähem võimalikke väärtusi. **Vastus:** Mitte ainult ei sobi, vaid see on ainuõige lahendus.   Näiteks avaliku teabe seadus ütleb (põhjusega)"§ 43-3.  Andmekogu asutamine(2) Keelatud on asutada ühtede ja samade andmete kogumiseks eraldi andmekogusid."   Andmete dubleerimine võib küll mõnikord parandada töökiirust, kuid samas tekitab see andmete muutmise anomaaliaid. Klassifikaatorite dubleerimine samas andmebaasis ei paranda töökiirust, aga andmete muutmise anomaaliad tekivad ikka. **Märksõnad:** dubleerimine, klassifikaator ## Küsimus: Töövihiku projekti muutes tekkis küsimus, kui suurt rõhku tuleks panna ainsuse/mitmuse kasutamisele X-i asendamisel? Nt. allsüsteemide juures on isikute, töötajate jne allsüsteemid, loogiliselt võttes tuleks seal asendada X mitmuse vormiga, aga kas see oleks korrektne? Läbivalt on kasutusel muidugi (meie projekti puhul) kaup kui ainsuse vorm, kuid mõned kohad tekitavad segadust, kas panna mitmusesse või ainsusesse. Kuidas sellises olukorras tegutseda? **Vastus:** Öeldakse, et arvutiteaduses on kaks keerulist asja ja nendest üks on nimede andmine. X ainsuse ja mitmuse vormi valikul on oluline järjekindlus – sama tüüpi elemente (nt allsüsteemid, kasutusjuhud, olemitüübid, tabelid) tuleb nimetada ühes stiilis. Minu soovitus on kasutada funktsionaalsete allsüsteemide ja registrite nimetamisel mitmuse vormi (nt kaupade funktsionaalne allsüsteem ja kaupade register) ning olemitüüpide ja tabelite nimetamisel ainsuse vormi (nt Kaup). Kasutusjuhtude korral, kui protsess tegeleb korraga ühe eksemplariga (nt ühe kauba lõpetamine), siis kasutage ainsuse vormi (nt kasutusjuht Lõpeta kaup). Kui protsess tegeleb korraga mitme eksemplariga, siis kasutage mitmuse vormi (nt kasutusjuht Vaata kõiki kaupu). --- # Teema: Korraldus - iseseisev töö ## Küsimus: Kas CASE vahendis tehtud mudelitesse tuleb lisada kõik põhiobjektid, mida oleme töövihikusse kirjutanud, või ainult need, millest räägitakse juhendis? Näiteks, meil on põhiobjektide hulgas "Partner" ja "Tätoveerija", kuid juhendis keskendutakse "Klient" ja "Töötaja" täiendamisele. **Vastus:** Ei. Kontseptuaalses andmemudelis tuleb kajastada ainult seda andmebaasi alamosa, mida on vaja kasutusjuhtude mudelis kirjeldatud funktsionaalsuste pakkumiseks.Tätoveerija ei peaks ilmselt olema põhiobjekt, sest selle elutsüklid ning neid kirjeldav seisundidiagramm pole erinev töötaja seisundidiagrammist. Põhiobjekt on Töötaja ja "tätoveerija" on üks töötaja roll.Põhiobjekti Partner peaks kontseptuaalses andmemudelis kajastama ainult siis, kui Teie töös leidub mõni kasutusjuht, mille täitmiseks peab lugema partnerite andmeid. Minu arvates töövihiku järgi projekti tehes sellist kasutusjuhtu ei leidu. ## Küsimus: Kas iseseisva töö ülevaatamisel peavad olema kohal kõik projekti tegijad? **Vastus:** Ei pea, kuid teadmiste saamise eesmärgil oleks mõistlik. See ei ole kaitsmine. Õppejõud vaatab koos vähemalt ühe autoriga töö üle ning teeb talle suuliselt teatavaks puudused mis tuleb arvestuse saamiseks kõrvaldada. Need tuleb üles kirjutada. Kui õppejõuga suhtleb ning märkmeid teeb mitu inimest, siis on väiksem võimalus, et midagi jääb kahe silma vahele. Kui kõik on kohal, siis jõuab kõigi osalisteni info vigade kohta kiiremini ja see võimaldab ka kiiremini ja paremini vigu parandada. ## Küsimus: Kas ma peaksin enne iseseisva töö prototüübi tegema hakkamist näitama õppejõule dokumentatsiooni ette? **Vastus:** See ei ole kohustuslik, kuid on mõistlik juhul kui olete otsustanud teha töö nullist ja omal teemal, mitte kasutada etteantud malli. Seda saab teha vastuvõtuajal. Kirja teel projekte üle ei vaadata. ## Küsimus: Kas ma võin minna üle ühest iseseisva töö tegijate rühmast teise üle? **Vastus:** Liitumine olemasoleva rühmaga (kaks üliõpilast), et nende projekti edasi teha on lubatud kuni kaheksanda õppenädala lõpuni. Peale seda on lubatud projektist eraldumine ja projekti üksinda tegemine, projekti liikme projektist väljaarvamine teiste liikmete poolt ning samuti kahe või kolme üksinda projekti tegija üheks tegijate rühmaks liitumine. Projekti liikmete muutmisel tuleb arvestada piiranguga, et projektis võib olla kuni kolm liiget. Projekti liikmete hulga muutusest õppejõu teavitamiseks on ainus viis muuta teema registreerimise ülesande vastust Mauruses. Kui seda pole tehtud, siis järelikult pole rühm muutunud. ## Küsimus: Kas ma võin muuta iseseisva töö registreeritud teemat? **Vastus:** Jah võib. Sellest mulle teada andmiseks muutke palun Mauruse keskkonnas iseseisva töö teema registreerimise ülesande vastust. Õppejõud näeb kui vastust on muudetud ja saab selle kaudu muudatusest teada. ## Küsimus: Kas ma võin vaadata teiste üliõpilaste projektide kaitsmisi? **Vastus:** Jah võite ja see on isegi väga soovitav. Ülevaatused toimuvad MS Teamsis ja need kohtumised on kõigile huvilistele avalikud. Kui projekt pole veel valmis ja arvestust saanud, siis osalege vähemasti oma tunniplaani järgses praktikumis (loomulikult võite tulla ka mõnda teise tundi!) ja vaadake palun teiste üliõpilaste tehtud tööd. Enamik võimalikest probleemidest on ühised paljudele projektidele. Nii nagu haiguste ennetamine on kasulikum haiguste ravimisest on ka projekteerimise korral palju odavam ja mugavam vigu ennetada, mitte neid tagantjärgi parandada. Hindan, et vähemalt 80% vigadest kordub paljudes projektides. ## Küsimus: Kas me saame töövihiku projekti korral ära kustuta diagrammidelt mentor ja juhendatav seose? **Vastus:** Töövihiku valmistehtud osi projektist eemaldada ei tohi. Diagrammilt (nt X registri olemi-suhte diagramm) võite selle kustutada, kuid seda ei tohi kustutada mudelist. Räägin praegu seosetüüpi tähistava joone pildilt eemaldamisest. See seosetüüp peab olema kindlasti nähtav töötajate registri olemi-suhte diagrammil. Andmebaasis tuleb see seosetüüp realiseerida. ## Küsimus: Kas töövihiku tüüpi projekti korral võib mitu rühma teha projekti samal teemal? **Vastus:** Jah võib. ## Küsimus: Kas ühes "Andmebaasid I" aine projekti meeskonnas võivad olla inimesed erinevatest gruppidest? **Vastus:** Projekti rühmas võivad olla üliõpilased erinevatest gruppidest, kes käivad erinevatel aegadel praktikumis ja kes võivad ka õppida erinevate õppekavade järgi. Kõikidele üliõpilastele on nõuded projekti osas ühesugused. Kui praktikumis toimub projektiga tegelemine, siis on oluline, et kõik kohalkäinud annaksid oma tunni töö järgmisele tundi tulijale üle. **Märksõnad:** meeskond, rühm, tiim ## Küsimus: Kuidas esitada iseseisev töö? **Vastus:** Iseseisva töö esitamiseks (sõltumata sellest, kas tegemist on lõplikult valmis versiooniga või vaheversiooniga, millele soovite konsultatsiooni käigus tagasisidet) valige õppekeskkonna vasakpoolsest menüüst "Kiirvalik=>Vastamine" ning avanenud leheküljelt ülesanne "Iseseiseva töö failide saatmine". Ülesande vastusena saab saata ka faile. Ülesandele esmakordselt vastamine.Vajutage ülesande juures lingile "saada faile". Avanenud aknas on iga küsimuse juures link "Saada fail". Sellele vajutades tekib lehe ülaosas võimalus faili valimiseks. Faili serverile saatmiseks tuleb vajutada nupule "Saada ära".Ülesande vastuse parandamine.Vajutage ülesande juures lingile "paranda/muuda". Avanenud lehel saab kustutada küsimustega seotud faile ja lisada uusi faile.NB! Proovige kontrolli eesmärgil enda üleslaetud faile alla laadida! Kui faili suurus on 0 KB (üleslaadimine ilmselt ebaõnnestus), siis on faili suurus punasega tähistatud.NB! Nupule "Salvesta muutused vastuse tekstis" tuleb vajutada vaid siis, kui lisaks failidele kirjutasite midagi ka küsimuste vastuste lahtritesse. NB! Iseseisva töö lõpliku versiooni esitamisel peab vastuse saatma üks projekti liige. ## Küsimus: Kuidas registreerida iseseisva töö projekti teema? **Vastus:** Tähtajaga 9. veebruar 2024 (kaasa arvatud) tuleb vastata iseseisva töö valikuga seotud küsimustele (st saada selgeks ülesande püstitus, valida teema ja panna kokku tegijate rühm). Seda tuleb nii varakult teha, et saaks alates kolmandast nädalast praktikumides sisukalt ja efektiivselt kaasa töötada. Iseseisva töö registreerimiseks valige õppekeskkonna vasakpoolsest menüüst "Kiirvalik=>Vastamine" ning avanenud leheküljelt ülesanne "Iseseiseva töö teema registreerimine". Kui teete iseseisvat tööd rühmatööna, siis peab teema registreerima üks rühma liige (iseseisvat tööd võib teha 1-3 liikmelistes rühmades). Enne vastamist on kindlasti vaja tutvuda ülesande püstitusega. Kui teete projekti üksinda, kuid otsite kaaslast, siis on võimalik seda soovi iseseisva töö teema registreerimisel väljendada. ## Küsimus: Kuidas toimub iseseisva töö projektide ülevaatamine? **Vastus:** Kõik projektide ülevaatamised toimuvad MS Teams vahendusel.Kõik ettenäitamised on avalikud. See tähendab, et õppejõud vaatab töid oma arvutis ning jagab ekraanipilti MS Teamsis kohtumisel osalejatele. Soovitan tulle vaatama ja kuulama (link kohtumisel osalemiseks tekib MS Teamsis grupi ITI0206-K-2024 kanalisse). Vestluste käigus tulevad kiiresti välja tüüpilised vead ja saate neid oma projekti juures kasvõi kohe parandada, et tulla oma projekti ettenäitamisele parema projektiga.Iseseisva töö ülevaatamise protsessi visuaalset kirjeldust saate vaadata SIIT. **Märksõnad:** iseseisev töö, projekt, ülevaatus, ülevaatamine, ettenäitamine, kaitsmine, kaug, kaugtöö ## Küsimus: Kui meie projekti teemaks on "Spordiklubi infosüsteemi treeningu funktsionaalne allsüsteem", kas meie tohime panna nii, et treener ja treeningu haldur on üks ja sama inimene ehkki tegutsejate alla paneme ainult "Treener"? Ja edaspidi, kus mallis on kirjas X haldur asendame siis ainult "Treener"-iga. **Vastus:** Treener ja Treeningute haldur on rollid, mitte füüsilised isikud. Ühel ja samal füüsilisel isikul võib olla mitu erinevat rolli. Selle jaoks on töövihiku järgi valmivas andmebaasis andmed töötajate rollide ja nende rollide omamiste kohta. Mida vähem on rolle, seda vähempaindlikum on infosüsteemile juurdepääsu andmine ning see hakkab pärssima ettevõtte äriliste eesmärkide täitmist. Näiteks meie ülikooli õppeinfosüsteemis ei ole õppeained mitte õppejõudude registreeritud, vaid seda on teinud õppeainete halduri rollis isik, kelleks on mõni töötaja õppeosakonnast. Kui õppejõud saaks hallata õppeaineid, siis saaks ta seda teha erinevatel õppeainetel (ka nendes, mis temasse kuidagi ei puutu) ning saaks teha kooskõlastamata muudatusi. Samuti peaks teda siis tasustama tööülesannete eest, mis tema pädevusse ei kuulu.Seega Teie pakutud muudatus töövihikusse ei sobi. Küll aga peaks vastavalt töövihiku sammule lisama kasutusjuhtude mudelisse tegutseja e rolli Treener ning tema tööülesannete läbiviimise võimaldamiseks siduma kasutusjuhtudega "Tuvasta kasutaja" ning "Vaata kõiki treeninguid" (nii diagrammil e skeemil kui ka kõrgtaseme ja laiendatud formaadis tekstikirjeldustes). ## Küsimus: Kui palju andmebaasioperatsioonide lepinguid peab olema iseseisvas töös laialt kirjeldatud? Näidisprojekti kasutujuhtude kirjelduses (punkt 2.1.1) on neid üsna palju, kuid operatsioonide lepingute kirjelduses (punkt 2.2.2) neid leidub neid vähem. Millised on nõuded selle projekti osa kohta? **Vastus:** Operatsioonide lepingud tuleb kirjutada kõigi nende operatsioonide kohta, mis täidavad mõlemat järgnevat tingimust. a) neid vajavad projektis käsitletavad kasutusjuhud, b) nende käigus lisatakse/muudetakse/kustutatakse andmebaasis olevaid andmeid. Operatsioonide lepinguid ei tule kirjutada operatsioonide kohta, mille käigus ainult ainult loetakse andmebaasis olevaid andmeid. ## Küsimus: Kus on kirjas, millised projekti osad tuleb iseseisvas töös täita? **Vastus:** Kevadise iseseiseva töö dokument hõlmab näiteprojektist peatükke 1, 2 ja 5 ning lisaks punkti 3.1. Lisaks tuleb teha projekteeritud süsteemi andmebaasi prototüüp (kogu projekti mahus) ja rakenduse funktsionaalne prototüüp ühe töökoha ulatuses. See info on ka kirjas kursuse tutvustuses kataloogis "Aine korraldus". Samuti näeb seda kui vaatate iseseisva töö dokumendi malli - kõik pealkirjad, mille alla peab aine projektis midagi kirjutama, on tähistatud punasega. ## Küsimus: Ma ei registreerinud õigel ajal iseseisva töö teemat. Mis nüüd saab? **Vastus:** Miinuseid selle eest ei saa. Kuid registreerige esimesel võimalusel oma vastused. Mida hiljem Te hakkate iseseisvat tööd tegema, seda raskem on seda õigeks ajaks valmis saada ja seda väiksema on võimalus saada lisapunkte eksamile. ## Küsimus: Ma ei tunne hästi ühtegi valdkonda, milles tegutseva ettevõtte/organisatsiooni kohta saab teha projekti töövihiku järgi? Mida teha? **Vastus:** Tarkvara kirjutamine vajab nõudeid ning nõuded tulenevad valdkonnast, millele tarkvara luuakse. Seega, ega valdkonna hästi tundmine loomulikult kahjuks ei tule. Samas ma kahtlustan, et enamik töövihiku järgi projekti tegijatest (keda on valdav enamik kuulajaskonnast) ei tunne oma projekti valdkonda (restoran, juuksurisalong, spordiklubi, tootmisettevõte, jne) süvitsi. Teisalt pole see minu arvates eriline takistus, sest: täiendused töövihikusse tegelikult ei nõua valdkonna süvitsi tundmist, piisavat taustainfot saab koguda ka lihtsalt selle valdkonna ettevõtete kodulehti vaadates. Valdkonna mingil määral tundmist on vaja näiteprojektis/töövihikus alajaotise 1.1 täitmiseks ning samuti veidi kontseptuaalse andmemudeli juures. Muudes kohtades asendate X-e (nt X=>Teenus) ja saategi kas täiesti valmis või peaaegu valmis tulemuse. See ongi eesmärk, sest aine on ikkagi andmebaaside aine ja ei tahaks kulutada suure osa semestrist näiteks funktsionaalsete nõuete kogumisele ja kirjapanekule. Selline X-i asendamine annab need nõuded sisuliselt tasuta kätte. ## Küsimus: Miks tasub iseseisva töö projekti teha rühmatööna? **Vastus:** Selleks, et harjutada koostööd ja suhtemist. Artikkel Postimehes (15.02.2018) kirjutab, et IT ettevõtted tunnevad puudust spetsialistidest, kes on koostööaltid ja head suhtlejad. ## Küsimus: Mul on küsimus andmebaaside I projekti kohta. Kas me põhiobjektid, mis alguses töövihikus olid võime muuta ja mõned kustutada, või me peame ainult enda oma põhiobjektid juurde lisada originaalseid puudutamata? **Vastus:** Kustutada ei või: Isik, Töötaja, Klient, Klassifikaator, X. Nende olemasoluga arvestatakse järgnevates dokumendi osades. Ülejäänusid võib kustutada, kuid tuleb pidada silmas, et siis tuleb muuta ka teisi punkte alajaotises 1.1​Soovitan kustutamise asemel keskenduda sellele, mida ise lisate. Töövihikusse on kirja pandud asjad, millega üldiselt tuleb peaaegu igas organisatsioonis/infosüsteemis tegeleda. **Märksõnad:** töövihik ## Küsimus: Projekti juhend on liiga pikk. Mida teha? **Vastus:** Tagasisides kirjutati: "Küll aga leian, et andmebaasi projektiga seotud materjalid (nt "Projekti juhend" või "Kommentaarid iseseisvate tööde kohta" ja projekti töövihik) laskusid liigsõnalisusesse ja liigsesse detailsusesse, mis raskendab konkreetse info saamist. Täpseid näiteid selle kohta on keeruline tuua, kuna tegemist on pigem teksti kui terviku probleem, aga parema arusaamise nimel, toon arbitraarselt välja ühe lõigu failist "Projekti juhend" (lk 7):  "Kui seisate kunagi ülesande ees automatiseerida tööd ja võtta selleks kasutusele (uus) tarkvara  /---/  Väidan, et enamike selle aine teemade jaoks on selline tarkvara olemas, seega päriselus sellise uue tarkvara tegemiseks peab olema väga hea põhjus (innovatsioon)."  Saan aru, et see lõik (koos eelneva ja järgneva tekstiga) selgitab projekti tegemise tagamaid, aga küsimus on selles, kas taoline essee-laadne kõrvalepõige on õigustatud niigi mahukas dokumendis (33 lehekülge), mis peaks justkui olema praktilise töö juhend."Minu mõtted. Kõige lihtsam projekti juhend on vaadata näiteprojekti ja teha midagi samasugust. Ei pea ennast muude juhendite lugemisega vaevama. PDF failis on pealkirjade struktuur. Neid saab vaadata ka veebilehitsejas ja need võimaldavad dokumendis navigeerida. Viidatud lõik on sissejuhatavas osas samas kui projekti tegemise samm-sammuline juhend on peatükis 6. Juba õige pea peate tegema lõputöö. Võite seal esitada huvitava ja ägeda programmi või infosüsteemi, kuid kui Teie lõputöö dokumenti põhiosa moodustavad lakoonilised mudelid, programmi lähtekood, või kasutusjuhend ilma täiendavate selgitusteta, siis ei tasu oodata suurepärast, ega isegi mitte väga head hinnet. Lõputöös (igasuguses töös) tuleb aru saada ja osata teistele selgitada, mida teed, miks teed ning miks teed just nii ja mitte teisiti. Õppijana peaks olema eesmärk saada aru, milleks mingeid tegevusi tehakse ja mis olukorras neid sobib või ei sobi teha. Tuleviku tööturul on inimeste eelis tehisintellekti vahendite ees (mille esimene pääsuke on ChatGPT) see, et inimene saab asjadest rohkem ja paremini aru ning oskab oma teadmisi loominguliselt rakendada. Juhiste järgi korduvate tegevuste tegemisega saab arvutisüsteem kindlasti paremini hakkama kui inimene. ## Küsimus: Soovin leida kaaslast või kaaslaseid, kellega koos projekti teha. Mida teha? **Vastus:** Variandid (võib kasutada kõiki): Suhelge oma kaaslastega väljapool tunde. Registreerige Kiirvalik=>Vastamine all vastuse selleteemalisele küsimusele. Seal saab oma soovi panna kirja nii siis, kui teete üksinda ja otsite kaaslast/kaaslaseid või kui teete projekti kahekesi ja otsite kolmandat projektirühma liiget. Annate loengu või praktikumi alguses või lõpus oma soovist teistele osalejatele teada. Annate oma soovist teada õppeaine MS Teamsi rühmas. NB! Kui leiate hiljem projekti tegemiseks kaaslase(d), siis tuleb sellest muudatusest mulle teada anda, muutes iseseisva töö teema registreerimise ülesande vastust. NB! Üksik üliõpilane ei saa liituda kahese projekti rühmaga peale kaheksanda õppenädala lõppu. Kõik muud liikumised rühmade sees ja vahel on lubatud kuni semestri lõpuni. ## Küsimus: Tahan teha projekti PostgreSQL või Oracle andmebaasisüsteemis. Mida tuleb selleks teha? **Vastus:** Saamaks juurdepääsu apex2.taltech.ee/apex.ttu.ee serveritele, kus on PostgreSQL/Oracle, täitke palun esimene punkt "Andmebaasid II" kodulehel (kasutajanimi: SIS2, parool: SIS2) olevast ülesandest 1. Loodavad kontod on individuaalsed, st kui teete iseseisvat tööd rühmatööna, siis iga rühma liige peab küsima eraldi juurdepääsu. Oma kasutajanime ja parooli kellelegi edasi anda ei ole lubatud. Kas ja kuidas pääseb väljastpoolt ülikooli ligi õppeserveris olevale PostgreSQL andmebaasisüsteemile kirjutatakse SIIN.PostgreSQL/Oracle kasutamise juhiseid leiate (kasutajanimi: SIS2, parool: SIS2) SIIT ja SIIT.Ülikooli serverite kasutamise lisandväärtus projekti tegemiseks on, et seal saab kasutada andmebaasi disaini automaatkontrolli vahendeid (need leiavad ka tõsist kasutust "Andmebaasid II" õppeaines).NB! Praktikumides PostgreSQLi põhjal SQL lisapunkti ülesannete lahendamiseks saab kasutada ka keskkondi DBFiddle (toetab uuemaid PostgreSQL versioone) ja SQLFiddle. Seal on võimalik käivitada SQL tabelite loomise lauseid ning nende tabelite põhjal käivitada andmete otsimise ja muutmise lauseid. Niimoodi saate testida, kas Teie lause läheb tööle ja annab õige tulemuse. **Märksõnad:** Postgres, apex, apex2 ## Küsimus: Töövihiku järgi tehtava projekti teema on "Ürituste korraldamise ettevõtte peoruumide funktsionaalne allsüsteem"? Kas peame kõigepealt kavandama ja siis ka realiseerima broneeringute registri ja lisateenuste registri? **Vastus:** Kui ei taha, siis ei pea!Töö dokumendi osa võib tinglikult jagada kaheks. Süsteemi üldvaade - jaotis 1.1 - kus kirjeldatakse organisatsiooni (antud juhul peoruumide pakkuja)  infosüsteemi kui tervikut, sh seda, et vaja on hallata infot broneeringute, lisateenuste, lisateenuse tellimuste jne kohta. Detailne projekt - alates jaotisest 1.2 kuni dokumendi lõpuni - kus keskendutakse selle suure süsteemi ühele alamosale. Selleks alamosaks on antud juhul peoruumide funktsionaalne allsüsteem ning andmebaasi poole pealt registrid e andmebaasi alamosad, mis sisaldavad andmeid, mida on vaja peoruumide haldusega seotud funktsionaalsuse toetamiseks. Teiste sõnadega, sellistest registritest on vaja kas andmeid lugeda või on seal vaja andmeid muuta.    Teil oleks vaja teha andmebaasis tabelid nagu "Lisateenus", "Lisateenuse_tellimus", "Broneering" jne ainult sellisel juhul, kui jaotises "1.2.4 Allsüsteemi funktsionaalsed nõuded" sisalduks mõni kasutusjuht e kasutusmall, mille täitmiseks peab neid andmeid lugema. Rõhutan, et sellesse alajaotusesse pole töövihiku projekti korral vaja ühtegi kasutusjuhtu lisada. Näiteks kasutusjuht "Esita broneering" oleks "Broneeringute funktsionaalse allsüsteemi" kasutusjuht ning kasutusjuht "Telli lisateenus" oleks lisateenuste tellimuste funktsionaalse allsüsteemi kasutusjuht.    See on Teie enda otsustada, kas tahaksite näiteks, et kasutusjuhu "Vaata kõiki peoruume" läbija peaks nägema ka peoruumiga seotud detailseid broneeringuid või peoruumiga seotud aktiivsete broneeringute arvu.   Kui otsustate, et selliseid andmeid peaks selle kasutusjuhu kontekstis nägema, siis: tuleks täiendada vastava kasutusjuhu kirjeldust, funktsionaalne allsüsteem loeks broneeringute registrit, st tuleks täiendada ka jaotist "1.2.2 Seosed pädevusalade ja registritega", kontseptuaalne andmemudel ning selle alusel loodud andmebaasi disaini mudel ja realiseeritud andmebaas peaksid hõlmama ka broneeringute registrit.   Kui otsustate, et selliseid andmeid ei peaks nägema, siis eelnevalt kirjeldatud tegevusi ei ole vaja teha. See, kas peaks või ei peaks selliseid andmeid nägema, on projekti tegijate otsus, st seda pole ette kirjeldatud. --- # Teema: Korraldus - SQL kontrolltöö ## Küsimus: Kas ka siis peab SQL kontrolltööle registreeruma, kui lisapunktidega on saavutatud lävend, mis annab kontrolltöö hindeks 5? **Vastus:** Siis palun ärge registreeruge! Kui olete juba registreerunud, siis palun kustutage oma registreerimine. **Märksõnad:** kontrolltöö, lisapunktid ## Küsimus: Kas oleks võimalik saada iseseisvaks harjutamiseks mõeldud SQL ülesandeid? **Vastus:** Ülesanded on lisamaterjalide lehe (kasutajanimi: SIS2, parool: SIS2) kataloogis AB 1 SQL praktika. Seal on neid palju ning igale maitsele. Selle kataloogi alamkataloogis SQLi nuputamine on keerukamad ülesanded. Selle kataloogi alamkataloogis Lahendused on ülesannete (sageli kommenteeritud) vastused. **Märksõnad:** lisaülesanne, lisaülesanded, ülesanne, harjutusülesanne, harjutusülesanded ## Küsimus: Kui kirjutan kontrolltööd 16 nädalal ja ei õnnestu see mul, kas tohib peale seda teha järel tööd sessiooniajal? **Vastus:** Jah, tohite küll. Sessiooni ajal on veel kaks kontrolltöö kirjutamise võimalust (üks sessiooni alguse- ja teine lõpuosas). Nendel aegadel ei lähe lisapunktid enam arvesse. ## Küsimus: Kui kirjutan SQL kontrolltööd esimest korda mingil muul ajal kui aprillis, siis kas on lubatud kasutada A4 lehte abimaterjalina. **Vastus:** Üldiselt ei ole lubatud. Abimaterjale saab SQL kontrolltöö kirjutamisel kasutada üks kord aastas - aprillis - kui üliõpilastel on esimene kontrolltööde kirjutamise voor. Ainus erand on, et kui annate enne 13nda õppenädala kontrolltööd teada, et ei saa sellel osaleda, siis see annab võimaluse kasutada A4 abimaterjalide lehte 16nda nädala järeltööl. Sellest teadaandmise tähtaja leiate kursuse kodulehelt. Teadaandmiseks tuleb ennast registreerida Mauruses õppeaine kodulehel spetsiaalsele teadmiste kontrollile. ## Küsimus: Tahaksin küsida. Kui sel semestril projekt ei jõua teha aga SQL kontrolltöö on tehtud, nagu mina sain aru, et projekt on vaja järgmisel kevadel uuesti teha aga mis saab siis kontroltöö hinnest? Kas kontrolltöö on vaja ka uuesti teha? **Vastus:** Kontrolltöö hinne kehtib kuni deklaratsiooni kehtivuse lõpuni. Uuesti deklareerimisel tuleb kontrolltöö uuesti teha. Projekti arvestus kehtib ka uuesti deklareerides. Hindamisel kasutatav projekti kordaja määratakse kindlaks vastavalt jooksval semestril kehtivatele reeglitele. SQL kontrolltöö ja eksami lisapunktid kehtivad ainult saamise semestril. Deklaratsioon kehtib ühe semestri. ## Küsimus: Tahan kirjutada kontrolltööd 16. nädalal. Kas selle saad kirjutada mitte oma grupi praktikumi ajal? **Vastus:** Jah. 16. nädalal toimuvadki kontrolltöö järeltööd ainult osade praktikumide ajal. Ülejäänud praktikumides toimub iseseisva töö ettenäitamine. --- # Teema: Korraldus - üldine ## Küsimus: Kas eksamit saab teha enne eksamisessiooni algust? **Vastus:** Kui väga vaja, siis kokkuleppel õppejõuga saab. Eksamieeldused peavad olema eelnevalt täidetud. Kui mõtlete, et see on vajalik selleks, et eksamisessiooni ajal oma lõputööd kaitsta, siis ärge muretsege - lõputööde kaitsmine toimub eksamisessiooni teises pooles ning tehes eduka eksami eksamisessiooni esimesel nädalal jõuate ilusti kaitsmisele. **Märksõnad:** eksam, eksamisessioon ## Küsimus: Kas eksamit saab teha enne kui kõik eksamieeldused on täidetud? **Vastus:** Ei saa. Eksami tegemiseks peavad olema täidetud kõik eksamieeldused: SQL kontrolltöö tehtud jooksval semestril vähemalt hindele 1, projekt on arvestatud. ## Küsimus: Kas erinevatel nädalatel võib käia erinevates praktikumides? **Vastus:** Jah, erandkorras ning kokkuleppel õppejõuga saab. Sisu poolest on kõik praktikumid ühesugused. Palun Teid väga osaleda võimalusel Teie tunniplaanijärgses tunnis, et üliõpilased oleksid praktikumide vahel ühtlaselt jaotatud ja et ei tekiks olukorda, kus mõnes tunnis on palju rahvast ja teises vähe. Mida rohkem on tunnis osalejaid, seda vähem jääb õppejõul iga osaleja jaoks aega. Mis puudutab üliõpilasi, kellel ei ole seda ainet tunniplaanis (nt Avatud Ülikooli õppurid), siis elu näitab, et lõpptulemusena võib olla mõnes praktikumis hästi palju osalejaid ja õppejõul jagub sedavõrra osalistele vähem aega aga mõnes teises praktikumis (eriti reedeti) on aga väga vähe osalejaid ja samavõrra on õppejõul igale osaleja jaoks rohkem aega. Seega tasub alates teises õppenädalast õppejõult uurida, millised on ajad, kus tunnis käijaid on vähe ning käia selles tunnis - et õppimine läheks võimalikult libedalt ja ainest oleks võimalikult palju kasu. ## Küsimus: Kas praktikume on võimalik teha ka arvutiklassi arvutites? **Vastus:** Jah, on küll võimalik. Arvutiklassid on nüüd tehtud sellisteks, et pooltel töökohtadel on arvuti täiskomplekt, pooltel kohtadel aga ainult kuvar ja võrgukaabel (et soovi korral ühendada oma sülearvuti). Arvutiklassi arvutites on kogu vajalik tarkvara olemas. Muide, arvutiklass ICT-405 on vabakasutuses ja peaks olema koolipäevadel kasutamiseks avatud (kui seal just tundi ei ole). ## Küsimus: Kas tehes eksamit eksamisessiooni viimasel eksami tegemise ajal on veel võimalik seda parandada? **Vastus:** Kui teete eksamit eksamisessiooni viimasel päeval, siis saate vajadusel ikkagi teha eksamit 2+1 korda (kui teete põhieksamit) või 1+1 korda (kui teete lisaeksamit). Kuid kõik need eksami tegemised toimuvad samal päeval ja samas kohas, üksteise järgi (olen selleks aeg varunud). ## Küsimus: Kuidas arvestatakse lisapunkte? **Vastus:** SQL lisapunktid lähevad arvesse SQL kontrolltöös (13. õppenädalal) ja esimeses järeltöös (16. õppenädalal). Näiteks ilma lisapunktideta on SQL töö 65 punkti ja 2, kuid koos 7 lisapunktiga 72 punkti ja 3. Lisaks sellele määran üheteistkümnenda õppenädala lõpus lisapunktide lävendi, mille ületamisel saab üliõpilane SQL kontrolltöö hinde automaatselt 5. Kõik üle lävendi olevad punktid lähevad eksami lisapunktideks. Seega, kui üliõpilasel on näiteks 5 punkti üle lävendi, siis ta saab eksamile 5 punkti juurde. Kahe vahetesti tulemused lähevad samuti eksamile lisapunktideks. Näiteks ilma lisapunktideta on eksam 68 punkti ja 2 (17 õiget vastust 25-st), kuid koos 10 lisapunktiga on eksam 78 punkti ja 3. Eksami lisapunktid lähevad arvesse kõigil semestri jooksul tehtud eksami sooritustel. **Märksõnad:** punktid, lisapunkt, SQL kontrolltöö, test, eksam, hinne, lävend ## Küsimus: Kuidas kujuneb hinne? Milline mõju on lisapunktidel ja projektil? **Vastus:** Üks koht, kust seda kiiresti vaadata on aine korralduse kirjelduses. Hindamise põhimõtted on rasvase ja suure fondiga esile tõstetud. ## Küsimus: Kuidas peaks üliõpilane toimima, kui ta on haige? **Vastus:** Kui olete haige või haiguskahtlusega, siis ärge palun füüsiliselt klassi kohale tulge - õppetööd saab suures osas teha ka distantsilt. Kui toimumas on teadmiste kontroll, kus füüsiline kohalolu klassis on vajalik, siis võtke palun õppejõuga ühendust. **Märksõnad:** covid, haige, haigus, gripp, covid-19, nakkus ## Küsimus: Kuidas saada juurdepääs O'Reilly digitaalsele platvormile? **Vastus:** Juhend on SIIN. **Märksõnad:** oreilly ## Küsimus: Kuidas toimub SQL lisapunkti ülesannete lahendamine? **Vastus:** Kontrolltööl saab punkte ka osaliselt õigete vastuste eest. Lisapunkti ülesannete hindamine seevastu on binaarne - kui kõik on õige, siis 1 punkt, muidu 0 punkti. SQLis on ühe ülesande lahendamiseks (peaaegu) alati võimalik mitu erinevat lahendust. Kui ülesandes pole nõutud lahendusviis ette antud, siis võite lahendusviisi ise valida. Ootan lausetelt vähemalt minimaalsel tasemel loetavust - erinevad klauslid erinevatel ridadel; võtmesõnad suurtähtedega; nimed ei ole läbivalt suurtähtedega (nimede osas on erandiks LibreOffice Base). Põhiülesande punkte saab nädalas üks kord - ühe praktikumi eest. Kui osalete põhiülesannete lahendamisel, aga ei saa mitte ühtegi punkti, siis võite tulla uuesti põhiülesandeid lahendama. Nuputamisülesandeid võib tulla lahendama rohkem kui ühte praktikumi. Enne nuputamisülesannete lahendamist peavad olema lahendatud nädala põhiülesanded (st saadud nende eest vähemalt üks punkt). Ülesannete lahendamise ajal tuleb olla Teamsi tunnis kohal. Kes on klassis füüsiliselt kohal, see peab istuma nii, et nii talle kui ümberringi istuvatele kaaslastele jääb piisavalt isiklikku ruumi. Kui klassis on ruumi, siis tuleb istuda üle ühe inimese! Enamiku tagasisidest annan mikrofoni kasutades - olge kogu aeg kuuldel. Palun ette vabandust nende käest, kellele selline korraldus tundub häiriv. See oleks ka üks põhjus, miks tulla praktikumi, kus käib vähem inimesi. Vastuste esitamine käib ainult Teamsi kaudu (st mitte meiliteel, kohapeal näitamisega vms). Kui saate midagi valmis või tahate küsida, siis tuleb SQL kood (mitte näiteks MS Accessi fail või ekraanipilt) saata õppejõule MS Teamsi privaatses vestluses (chat), mitte tunni vestluses. Teise nädala ülesannete 3-7 vastuste ettenäitamiseks tuleb MS Accessi kasutamise korral üliõpilasel jagada ekraani. Nuputamisülesannete vastuste esitamise kohta on allpool eraldi punkt. Mugavama ülevaatamise huvides: palun kasutage lausetes reavahetusi (iga klausel eraldi real, iga alamtingimus eraldi real), palun ärge kasutage lausetes treppimist (õppejõuni jõudes on lausetesse tekkinud mitteprinditavad märgid, mis segavad käivitamist). Iga ülesande kohta tuleb saata eraldi teade. Kui lahendate ülesande mitme lausega, siis tuleb kõik need laused samasse teatesse üksteise järel kirja panna. Siin on erand teise nädala ülesande juures, mis on kirjas ülesande tutvustuses. Iga teate alguses peab olema öeldud, millise numbriga ülesannet selles teates olevad laused lahendavad. Kui lahendate ülesannet LibreOffice Base või PostgreSQL andmebaasisüsteemis, siis tuleb öelda ka seda. Kui ülesande vastuse juures on minu poolt pandud pöial püsti 👍, siis järelikult on vastus õige ja saab ühe punkti. Kui ülesande vastuse juures on minu poolt pandud üllatunud nägu 😲, siis on vastus vale või olematu loetavuse tõttu ebasobiv. Õppejõud võib vastust kommenteerida vestluses või ka läbi mikrofoni nii, et kõik kuulevad. Kui on üllatunud nägu, kuid Te pole saanud/kuulnud tagasisidet, siis küsige üle. Kui pole saanud 10 minuti jooksul tagasisidet, siis küsige üle. Võimalik, et mul on jäänud midagi kahe silma vahele. Ma palun selle eest juba ette vabandust! Punktide saamisel lähevad arvesse ainult vastused, mis on saabunud Teamsi tunni lõpuks (nt kell 14:00 algava tunni puhul hiljemalt 15:30). Kui esitate vastuse hiljem või muudate saadetud vastust hiljem, siis tagasisidet saate, aga punkte ei saa. Annan jooksvat tagasisidet kuni punktide saamise tähtajani. Kui mõni vastus jäi ülevaatamata, siis teen seda hiljem. Kui parandate vastust, siis ALATI tuleb vestlusesse kopeerida parandatud lause uuesti. Juba saadetud lause teate parandamine ei lähe punktide saamiseks arvesse. Kui lahendus koosnes mitmest lausest, siis tuleb need kõik uuesti saata (ühes teates nagu oli eelpool juttu). Kui kasutate MS Accessi, siis nuputamisülesande vastus tuleb esitada Accessi failina, kuhu on lahenduseks olevad SQL laused Query objektidena salvestatud. LibreOffice Base või PostgreSQL kasutamise korral tuleb saata vastuse tekst. Nuputamisülesannete vastuseid vaatan peale tunni lõppu ja saadan siis Teamsi kaudu tagasiside. Teie poolne esmane kontroll on see, et päringu tulemuses olevad read on täpselt samad kui on ülesande tekstis esitatud illustratsioonis. Kui ei ole, siis on lahendus kindlasti vale. Kui on, siis see ei garanteeri veel vastuse õigsust. Üldised reeglid Pidage palun protsessi sujuvuse ja maksimaalselt kiiresti tagasiside saamise huvides eelnimetatud reeglitest kinni. Enne tunni algust saadan laiali viited materjalidele (videod, slaidid), mida Te võiksite ENNE tunni algust ise üle vaadata.Tunni alguses teen peale paari avasõna õppeaine kodulehel nähtavaks tunni ülesande. See ilmub nähtavale vastava nädala materjalide algusesse. Moodles alajaotuse SQL alguses. Kõiki materjale võib kasutada. Teiste inimeste ja tehisintellekti vahendite (nagu nt ChatGPT) abi ei või kasutada - ülesannete lahendamine on individuaalne. Palun käige tunniplaanijärgses tunnis ja jaotuge selle kaudu tundide vahel ühtlaselt. Kui ühte tundi tuleb kokku liiga palju inimesi, siis kõikidel selles tunnis osalejatel on halvemad võimalused saada punkte ja tagasisidet. **Märksõnad:** MS Teams, kaug, kaugtöö ## Küsimus: Kuidas toimub valikvastustega lisapunktide testide tegemine? **Vastus:** Selliseid teste toimub kolm tükki. Viiendal õppenädalal test, mis annab juurde kuni 10 lisapunkti eksamile. Kaheksandal õppenädalal test, mis annab juurde kuni 10 lisapunkti eksamile. 10.-11. õppenädalal test, mis annab juurde kuni 6 lisapunkti SQL kontrolltööle. Testi tegemine ei toimu praktikumis, vaid etteantud perioodi jooksul veebipõhiselt iseseisvalt. Lisapunktide saamiseks tuleb etteantud ajaperioodi jooksul teha testi vähemalt etteantud arv kordi. Info täpse perioodi kohta saadetakse õppeaine kodulehe kaudu. Testi tegemine tähendab vastuste salvestamist. Teste võib teha ka ettenähtud miinimumarvust rohkem kordi. Tulemus arvutatakse tehtud testide keskmisena. Teste tuleb teha iseseisvalt, ilma abimaterjalid ning kõrvalise abi (sh teised inimesed või tehisintellekti vahendid) kasutamiseta.Testi tegemise perioodil on test tegemiseks avaldatud SIIN.Enne kõiki neid perioode on võimalik sellisel viisil tehtavateks testideks harjutada SIIN.Testi tegemisel peate väga täpselt jälgima, et Te ei ületataks testi tegemiseks ettenähtud aega, sest aja ületamisel vastuse salvestamine ebaõnnestub. Kuigi testi tegemise aknas on näha kell, siis see võib olla ebatäpne. Seega on ülioluline, et võtaksite testi tegemisel ise stopperiga aega. Kui kuritarvitate süsteemi, et selle abil küsimusi välja pumbata või saada meelepärasemaid küsimusi või ületate vastamiseks ettenähtud aega, siis automaatselt ja ilma eelhoiatuseta suletakse jäädavalt Teie juurdepääs sellele testile (sellisel viisil punktide/hinde saamine pole kohustus, vaid võimalus). Kuritarvituste näiteid: skripti kasutamine vastamiseks, küsimustiku genereerimine ilma vastuste salvestamiseta, küsimustiku genereerimine ja vastusteta salvestamine, vastamiseks ettenähtud aja ületamine, läbiklõpsutades liiga kiiresti vastamine. Teilt oodatakse, et need küsimused, mille süsteemilt saate, nendele ka vastate ja mõtlete sealjuures, mitte lihtsalt ei klõpsi. Panen Teile väga südamele, et Te kõigi nende nõuetega arvestaksite! **Märksõnad:** valikvastustega test, lisapunktid, vahetest, vahetestid ## Küsimus: Kuidas valmistuda õppeaines toimuvateks testideks (vahetestid ja lõpptest)? **Vastus:** Kordamisküsimused leiab SELLEST DOKUMENDIST (kataloog Teooria). Testide tegemine toimub veebipõhise keskkonna kaudu, kuhu Teie konto luuakse õppejõu poolt peale seda, kui olete Mauruses õppeaine kodulehel registreerinud. NB! Süsteemis on olemas testideks harjutamise funktsionaalsus. Harjutamiseks minge lehele https://maurus.ttu.ee/testimine/valik_harjuta.php. Õppeaines toimub auditoorse õppetöö perioodil kaks vabatahtliku teooria vahetesti, mis annavad lisapunkte eksamile ning kohustuslik lõpptest (eksam) eksamisessiooni ajal. Samuti toimub SQL kontrolltööle lisapunktide kogumise test. Kõikide nende jaoks saab selles keskkonnas harjutada. Kõikides vahetestides esitatavad küsimused võivad tulla ka lõpptesti. Millal on mingi test harjutamiseks avatud on kirjas õppeaine kodulehe ajakavas ning perioodi algusest teavitatakse ka eraldi meili teel. Järgnevalt loetlen harjutuskeskkonna mõned olulised põhimõtted. Sisselogimiseks on Mauruse kasutajanimi ja parool. Harjutamiseks võib olla avatud rohkem kui üks test - pöörake palun tähelepanu, mida valite. Testi omadused (vastamiseks ettenähtud aeg; küsimuste arv; küsimuste hulk, millest testiküsimused valitakse; küsimuste valiku põhimõtted) on samasugused nagu vastaval hinnataval testil. Iga testi tegemisel genereerib süsteem uue küsimustiku. Tehtavate testide arv ei ole piiratud. Süsteemi kuritarvitamisel, et selle abil küsimusi välja pumbata (skripti kasutamine vastamiseks; küsimustiku korduv genereerimine ilma vastamiseta), blokeeritakse vastaja juurdepääs sellele testile ilma eelhoiatuseta ning jäädavalt. Iga valitava testi juures on näha ajahetk, milleni on test harjutamiseks valitud. Tulemused salvestatakse ja õppejõud näeb tulemusi. Salvestamise järel näeb vastaja õigete vastuste arvu, hinnangut vastustele ja iga küsimuse korral ka seda, kas küsimusele vastati õigesti või valesti. Iga testi puhul on määratud, kui mitmel korral päevas näeb vastaja, juhul kui ta vastas küsimusele valesti (kuid ei jätnud vastamata), ka õiget vastust. Teste võib muidugi päevas teha rohkem kui on kordi, millal näeb õigeid vastuseid. Õigeid/valesid vastuseid näeb ainult salvestamise järel, kuid mitte hiljem. Harjutamise testide tulemusi näeb hiljem ka siit. Tulemusi ei võeta õppeaine hindamisel MITTE MINGIL VIISIL arvesse (st võite julgelt harjutada ja ka eksida). ## Küsimus: Kui praktikumis ei jõudnud kõiki või ühtegi lisapunktide ülesannet ära lahendada, kas on võimalik samal nädalal ka mõnes teises praktikumis veel lisapunktide ülesandeid lahendada? **Vastus:** Põhiülesannete eest võib nädala jooksul punkte saada maksimaalselt üks kord. Nuputamisülesannete (praktikumi ülesannete failides joone all) eest võib punkte saada nädalas rohkem kui ühel korral. Seega: kui käisite tunnis ja ühegi põhiülesande eest punkti ei saanud, siis võite tulla mõnda teise sama nädala praktikumi, et veelkord proovida põhiülesandeid lahendada (eeldusel, et seal ruumi jagub), kui käisite tunnis ja saite vähemalt ühe põhiülesande eest punkti, siis samal nädalal uuesti tundi tulles saate lahendada nuputamisülesandeid. ## Küsimus: Milline on vääritu käitumine antud aine kontekstis? **Vastus:** Infotehnoloogia teaduskonnas kehtib õppuri akadeemiliste tavade rikkumise ja vääritu käitumise menetlemise kord (dokument 09). Selles dokumendis määratakse ära, milliseid õppuri poolseid tegevusi loetakse akadeemiliselt väärituks käitumiseks ning millised on tegevused ja võimalikud ametlikud tagajärjed õppuri jaoks (noomitus, eksmatrikuleerimine) kui ta millegi sellisega hakkama saab. Palun Teilt järgnevat. Palun ärge jagage enda tehtud projekte teiste üliõpilastega. Palun ärge tehke kellegi teise eest tema tööd ära. Palun ärge taluge projekti rühmas liikmeid, kes teistega võrdselt töösse ei panusta. Sellega teete tegelikult neile palju halba, sest nad ei õpi midagi!!! Veel enam, Te teete kahju endale, sest teadmisteta/oskusteta lõpetajad kahjustavad tööandjate silmis kõigi diplomisaajate mainet. Kui mõni projekti kaaslane ei panusta piisavalt, siis arvake ta palun oma projektist välja ja teavitage sellest (nt õppekeskkonna kaudu) õppejõudu.Kindlasti olete praeguseks kuulunud ka tehisintellekti vahenditest ChatGPT ja muud sarnased, mis suudavad vahelduva eduga vastata ka tehnilistele küsimustele ja genereerida programmikoodi. Nende vahendite kasutamine teadmiste kontrollides ei ole lubatud. "Teeseldud meetodite ja valeandmetega või ebaeetiliselt/ebaausalt kogutud andmetega opereerimine on akadeemiline petturlus. Akadeemiline petturlus on ka igasuguse eelisolukorra loomine, mis ei ole kehtestatud reeglitega põhistatud, samuti valeandmete esitamine – tulemuste hindamise protsessis, rahastuse või positsiooni taotlemisel nii enda kui teiste suhtes. Siia alla kuulub ka hindajale teadmata abivahendite või keelatud andmete kasutamine;" (Birgi Lorenz) **Märksõnad:** OpenAI ## Küsimus: Millised oleksid põhilised soovitused selle aine edukaks sooritamiseks? **Vastus:** Tehke ainega iga nädal iseseisvat tööd Määrake näiteks kindel nädalapäev ja kellaaeg millal uurite materjale ja tegelete projektiga Alustage projekti varakult ja lõpetage varakult Kui jääte projektiga jänni, siis küsige kohe õppejõult Kõige operatiivsem on Teamsi vestlus Kasutage kõiki pakutud võimalusi lisapunktide kogumiseks - siin aines on neid palju See sunnib iganädalaselt ainega tegelema ja ka premeerib iganädalast ainega tegelemist Jälgige aine kohta e-posti aadressile tulevaid teateid Kasutage Mauruses seda aadressi, mida järjepidevalt jälgite Tehke kirjakastis reegel, mis suunab kõik Mauruselt tulevad kirjad eraldi kataloogi Võtke veidi aega, et vaadelda erinevaid kodulehe versioone ja valida sealt endale sobivaim Viite sellele saab järjehoidjasse panna ning ülejäänud soovi korral unustada Erinevad versioonid: Moodle Materjalid nädalate kaupa Algne koduleht Kohustuslikud materjalid (pole küll eraldi koduleht, aga võibolla mõni ei tahagi rohkem materjale näha) Logige oma tööaega. Kui ainega tegelemine jääb unarusse, siis tuleb see aruande jooksvast seisust kohe välja ja võiks motiveerida aine uuesti käsile võtta Annab lisapunkte Aina rohkem üliõpilasi teeb lõputöö rühmatööna ja seal on iga rühma liikme individuaalselt kulutatud aja aruanne lausa nõutud ## Küsimus: Millises järjekorras ja millisel viisil soovitate aine õppimist alustada? Millele kõigepealt tähelepanu pöörata? **Vastus:** Soovitan alustada sellest, et jälgite pealehele ilmuvaid kuupäevi ja üritate täita nendega seotud ülesanded. Pealehel näidatakse lähenevaid tähtaegu. Kõiki kuupäevi saab vaadata aine tutvustuse alt. Kuluva aja ja üliõpilaste tagasisiside järgi vaadates on õppeaine kõige raskem osa iseseisava töö projekt. On väga oluline, et teeksite selle tegemiseks head valikud (üksi või kaaslastega; kui kaaslastega, siis kellega; mis viisil teha (töövihik vs. omalooming), mis teemal teha, mis vahendeid kasutada) ja kui tuleb välja, et need ei olnud ikkagi head valikud, siis korrigeeriksite neid kiiresti. See on nagu süsteemiarendusega - mida hiljem viga avastada, seda kulukam on seda parandada. Leidke palun aega, et ülesande püstitus korralikult läbi lugeda ja valida meeldiv ja jõukohane teema. Selle arvelt kokku hoitud viis minutit võib hiljem valusalt kätte maksta. Töö tegemist nõuab iseseisev töö igal juhul, aga mõni teema/tegemise viisi korral kindlasti rohkem kui mõne teise korral. Soovitan iseseisva töö kiireks ja edukaks sooritamiseks sellega iga nädal kasvõi natukenegi tegeleda. Praktikumide ajakavas on kirjas, mis võiks olla iseseisva töö osas tehtud viienda õppenädala lõpuks. Kui teete projekti rühmas, siis kasutage palun maksimaalselt paralleeltöö võimalust, et sama ajaga rohkem tehtud saada. Selles mõttes pole üldse paha mõte (pole muidugi kohustuslik), et 3-5 õppenädalal osaleksid sama projekti tegijad erinevates praktikumides 3*3*1.5 tundi projekti tegemist on kindlasti parem kui 3*1.5 tundi projekti tegemist. Siis tuleb muidugi oma tunnitöö järgmisena tundi tulijale edasi anda. ## Küsimus: Millistel teemadel toimuvad valikvastustega lisapunktide testid? **Vastus:** Esimene eksami lisapunktide vahetest (viiendal õppenädalal).Ettevalmistumiseks vaadake palun: Slaidikomplekti SQL‑andmebaaside projekteerimise põhimõisteid esimene osa (alajaotised "Sissejuhatus" ja "SQL"). Vaadake siit selle kohta tehtud videoid: Sissejuhatus, SQL (1), SQL (2), SQL (3). Teise õppenädala praktikumi ülesanne + selle ettevalmistuseks tehtud videod. Eksami kordamisküsimusi teemade 3–5 (SQL) kohta, sest nende hulgas on testi küsimuste valikusse kuuluvaid küsimusi. Lisaks tehke SIIN harjutamise teste. Teine eksami lisapunktide vahetest (kaheksandal õppenädalal).Ettevalmistumiseks vaadake palun: Slaidikomplekti SQL‑andmebaaside projekteerimise põhimõisteid teine osa (alates alajaotisest "Süsteemiarenduse üldpõhimõtteid" kuni lõpuni). Vaadake siit selle kohta tehtud videoid: Süsteemiarenduse üldpõhimõtteid (1), SQL-andmebaasi projekteerimine (1), SQL-andmebaasi projekteerimine (2). Slaidikomplekti Kontseptuaalne andmemudel. Kõik loengutes ja praktikumides iseseisva töö projektist räägitu + iseseisva töö juhendid. Eksami kordamisküsimusi teemade 3–5 (SQL), 7 ja 10 kohta, sest nende hulgas on testi küsimuste valikusse kuuluvaid küsimusi. Lisaks tehke SIIN harjutamise teste. SQL kontrolltöö lisapunktide test (10.-11. õppenädalal).Ettevalmistumiseks vaadake palun: Kõik SQLi puudutavad materjalid. Eksami kordamisküsimusi teemade 3–5 (SQL) kohta, sest nende hulgas on testi küsimuste valikusse kuuluvaid küsimusi. Lisaks tehke SIIN harjutamise teste. **Märksõnad:** valikvastustega test, lisapunktid, vahetest, vahetestid ## Küsimus: Millist tarkvara läheb õppeaines vaja ja võiks seega võimalusel oma Windows arvutisse installeerida? **Vastus:** Kui kasutate SQL ülesannete lahendamiseks andmebaasisüsteemi MS Access või LibreOffice Base, siis võiks see olla installeeritud hiljemalt teise õppenädala alguseks Kui kasutate SQL ülesannete lahendamiseks PostgreSQLi, siis saate kasutada veebikeskkonda DB Fiddle, mida ise installeerima ei pea Kui kasutate projekti tegemiseks andmebaasisüsteemina PostgreSQLi, siis graafilist kasutajaliidest pakkuv andmebaasiga töötamiseks mõeldud programm PgAdmin Programmeerijatele (sh SQL lausete kirjutajatele) mõeldud tekstiredaktor: Notepad++ või SciTe Võiks olla installeeritud hiljemalt teise õppenädala alguseks Notepad++ puhul on võimalus kasutada meie ülikooli üliõpilaste välja töötatud pistikprogrammi, mis võimaldab käivitada sinna kirjutatud SQL lauseid MS Access või PostgreSQL andmebaasis ning neid lauseid ka vigade suhtes kontrollida. Erinevalt DBeaverist või DBbSchemast saab selle kaudu MS Accessi andmebaasis käivitada ka CREATE, ALTER ja DROP lauseid. CASE vahend: Enterprise Architect või Rational Rose Võiks olla installeeritud hiljemalt kolmanda õppenädala alguseks Enterprise Architecti korral võiksite lisaks installeerida meie ülikooli üliõpilase poolt välja töötatud täiendatud mudeliteisenduse kontseptuaalsest andmemudelist esialgse SQL-andmebaasi disaini mudeli genereerimiseks Enterprise Architecti korral võiksite lisaks installeerida meie ülikooli üliõpilase poolt välja töötatud programmi, mis suudab klassidiagrammi tõlkida inimkeelseteks lauseteks Soovi korral universaalne (erinevate andmebaasisüsteemide jaoks mõeldud) graafilise kasutajaliidesega programm SQL lausete käivitamiseks ja andmebaasi struktuuri visualiseerimiseks: DBeaver (versioon 22.3.2 või hilisem) Võiks olla installeeritud hiljemalt kuuenda õppenädala alguseks Alternatiivina sobib ka DbSchema Saab kasutada alternatiivse graafilise kasutajaliidesena MS Accessi andmebaasis andmete otsimise ja muutmise lausete koostamiseks ja käivitamiseks. Probleem on selles, et käivitada saab ka lauseid, mida MS Accessis otse käivitada ei saa - programm ise tõlgib neid MS Accessile arusaadavaks. Sellised laused SQL ülesannete lahenduseks ei sobi. Paraku ei saa ei DBeaveri ega DbSchema kaudu käivitada MS Accessi andmebaasis CREATE, ALTER ja DROP lauseid Kui kasutate MS Accessi, siis soovi korral MS Accessi andmebaasi kasutamiseks alternatiivset kasutajaliidest pakkuvad programmid nagu MDB Admin või MDB Viewe Plus. ## Küsimus: Mis andmebaasisüsteeme antud kursuse kasutada saab? **Vastus:** Praktikumide lisapunkti ülesandeid ja iseseisvaid harjutusülesandeid lahendada ning SQL kontrolltööd teha on võimalik kasutades: PostgreSQLi, LibreOffice Base'i (kasutab HSQLDB v1.8) või MS Accessi. Iseseisva töö andmebaasi võib luua kasutades mistahes SQL-andmebaasisüsteemi (PostgreSQL, MySQL, MS SQL Server, MS Access, Oracle jne). --- # Teema: Küsimused seoses jätkuainega ("Andmebaasid II") ## Küsimus: Arvestades sellega, et "Andmebaasid II" aines tuleb seda projekti edasi teha, siis millised oleksid soovitused "Andmebaasid I" projekti jaoks andmebaasisüsteemi valimisel? **Vastus:** Jätkuaines "Andmebaasid II" peate Te valima ühe serveri andmebaasisüsteemi, mille põhjal oma projekti edasi teha. Süsteemid, mille hulgast valik teha, on rangelt ette antud - PostgreSQL ja Oracle (ei näe põhjust seda valikut lähitulevikus muuta, sest tegu on väga heade süsteemidega). Projektis tuleb valitud serveri andmebaasisüsteemi abil realiseerida andmebaas ning samuti realiseerida seda andmebaasi kasutav rakendus valitud allsüsteemi ühe töökoha piires. Rakenduse tegemise vahendi valik on vaba, kuid tulemust peab olema muidugi võimalik mulle demonstreerida. Eelnevast tulenevalt soovitan kevadise projekti tegemiseks kasutada kas: MS Access PostgreSQL Oracle Kui kasutate MS Accessi, siis on Teil võimalik sügisel töötada MS Accessis tehtud rakendus ümber nii, et see hakkab ODBC andmeühenduse tehnoloogia vahendusel kasutama PostgreSQL andmebaasi. Kui kasutate MS Accessi ja plaanite ka sügisel projekti rakenduse osa MS Accessis teha, siis valige kevadises projektis realiseerimiseks töökoht, mis võiks ka reaalses elus kasutada kahekihilist klient-server süsteemi, kus rakendus on kliendi arvutis. Seega ei sobi MS Accessis realiseerimiseks kõikvõimalikud "kliendi" töökohad, mis kindlasti peavad olema tehtud veebirakendusena. Kui teete oma kevadise projekti PostgreSQLis või Oracles, siis saate sügisel tehtud serveri andmebaasi edasi arendada. Kindlasti on sügisel disaini parandamisega omajagu tööd, kuid kevadel saadud kogemus võib tööd lihtsamaks muuta. Huvilistele saan juba kevadel anda juurdepääsu serveritele, kus on PostgreSQL (15) ja Oracle (12c Enterprise Edition, Release 1). Kuna seal serveris on andmebaaside disaini automaatkontrollimise vahendid, siis palun PostgreSQLis või Oracles tehtud "Andmebaasid I" projekti andmebaas sinna enne ettenäitamist üles panna. **Märksõnad:** Postgres, MSAccess ## Küsimus: Kas aines "Andmebaasid I" tehtava projekti rühm peab jääma samaks jätkuaine "Andmebaasid II" raames? **Vastus:** Ei pea. ## Küsimus: Kas sügisel saab teha "Andmebaasid II" õppeainet, kui "Andmebaasid I" jäi kevadel tegemata? **Vastus:** Võite sügisel deklareerida "Andmebaasid II", kui "Andmebaasid I" on tegemata. Muidugi hoiatan, et üks on teisele sisuline eeldus ja kui eeldusaine pole selgeks saanud, siis on jätkuaine kindlasti selle võrra raskem. "Andmebaasid II" õppeaines arendatakse edasi "Andmebaasid I" projekti. Pakun välja kolm "Andmebaasid I" projekti, mille hulgast saavad üliõpilased, kellel on eeldusaine tegemata, valida projekti, mida sügisel edasi arendada. Nii saavad üliõpilased "Andmebaasid II" projekti tegemisega kohe septembri alguses pihta hakata. Teine võimalus on, et liitute sügiseks mõne rühmaga, kus "Andmebaasid I" projekt on tehtud. Nii nagu kevadel on ka sügiseses projektis lubatud osalejate arv 1-3 üliõpilast. "Andmebaasid I" projekti sügisel kaitsta ei saa. Seda saab teha järgmisel kevadel. Siis saate ka teenida varase esitamisega seotud soodustuse (suur kordaja väärtus). Selles mõttes pole paha mõte sügisel "Andmebaasid I" projekt ikkagi ära teha, et siis kohe järgmise aasta veebruaris/märtsis see ette näidata. Te ei pea valima uut "Andmebaasid I" projekti teemat. Piirang millega tuleb arvestada "Andmebaasid II" projekti teema valimisel on, et eelnevalt kirjeldatud viisidel projekti tehes ei tohi "Andmebaasid I" ja "Andmebaasid II" projekti teemad kokku langeda. Sellel semestril kogutud lisapunktid "Andmebaasid I" uuesti deklareerides arvesse ei lähe, kuid saate neid koos ülejäänud üliõpilastega järgmisel kevadel uuesti koguda. SQL kontrolltöö tuleb õppeainet uuesti deklareerides uuesti teha ning lävend ületada. Kui saite projekti kevadel tehtud, siis saate sellega sügisel jätkata. Õppeaine uuesti deklareerimisel ei ole vaja projekti uuesti teha. Projekti kordaja leitakse uuesti deklareerimise semestril kehtivate reeglite kohaselt. ## Küsimus: Kui nt üks liige peab ajateenistuse tõttu aasta vahele jätma, kas siis seda projekti võivad erinevad rühma liikmed erinevatel aastatel edasi teha "Andmebaasid II" aine raames, st kaks liiget selle aasta sügisel ja kolmas liige eraldi üksi järgmise aasta sügisel? Kas selline olukord on üldse võimalik või tuleks siis "Andmebaasid I" projekt üksi teha? **Vastus:** Kõigepealt tuleb muidugi öelda, et me keegi ei tea täpselt ette, mis juhtub mitme aasta pärast ning elu võib igasugustes nõuetes ja plaanides teha korrektiive. Järgnev on minu käesoleva hetke vaade ning praegu pole mul plaani selles vaates muudatusi teha. Jätkuaines "Andmebaasid II" peate Te valima ühe serveri andmebaasisüsteemi, mille põhjal oma ("Andmebaasid I") projekti edasi teha. Süsteemid, mille hulgast valik teha, on rangelt ette antud - PostgreSQL ja Oracle (ei näe põhjust seda valikut lähitulevikus muuta, sest tegu on väga heade süsteemidega). Eeldusel, et lähteprojektis kasutati teist andmebaasisüsteemi, on sisuliselt tegemist süsteemi migreerimise projektiga ühelt platvormilt teisele koos koodi puhastamisega ja selleks vajaliku refaktoreerimisega. Ainus lisaks realiseerimist vajav funktsionaalsus on kasutaja tuvastamine. Projektis tuleb valitud serveri andmebaasisüsteemi abil realiseerida andmebaas ning samuti realiseerida seda andmebaasi kasutav rakendus valitud allsüsteemi ühe töökoha piires. Rakenduse tegemise vahendi valik on vaba, kuid tulemust peab olema muidugi võimalik mulle demonstreerida. Ka sügisese aine projekti saab teha 1-3 üliõpilast. Nagu kevadel, ei sõltu ka sügisese aine projekti maht/nõuded/tähtajad tegijate arvust. Millised oleksid Teie kaaslase valikud järgmise aasta sügisel, eeldusel, et teete "Andmebaasid I" projekti mitmekesi? 1. Kaaslane teeb edasi kevadel alustatud ja arvestuse saanud projekti, kuid kasutab sügisese projekti tegemiseks teist andmebaasisüsteemi kui Teie sügisel kasutasite. Toon näite. Oletame, et töö teemaks on "e-poe infosüsteemi kaupade arvestus". Sellel sügisel realiseerib üks grupp selle kasutades Oracle andmebaasisüsteemi. Järgmisel sügisel realiseerib teine grupp selle kasutades PostgreSQL andmebaasisüsteemi. Vahendite valikus võiks muidugi omavahel aegsasti kokku leppida. 2. Kaaslane leiab järgmisel sügisel projekti, millesse ta läheb teiseks või kolmandaks liikmeks. 3. Kaaslane valib projekti tegemiseks ühe selleks otstarbeks "Andmebaasid II" kodulehele välja pandud (mõnede teiste üliõpilaste tehtud) "Andmebaasid I" projekti. --- # Teema: Loengud ## Küsimus: Millele oleks eriti oluline andmebaaside õppimisel tähelepanu pöörata? **Vastus:** Kui maailmas on üldse midagi kindlat, siis see, et kõik on pidevas muutumises. Kui loote infosüsteemi ja selle andmebaasi, siis tuleb neid ajaga kaasaskäimiseks pidevalt kohandada. Hoolduskulud võivad lõpuks moodustada kuni 80% süsteemi kogukuludest. Selles kontekstis on väga oluline andmebaasi hallatavus. Artiklis: Riaz, M., Tempero, E., Sulayman, M., & Mendes, E. (2013). Maintainability Predictors For Relational Database-Driven Software Applications: Extended Results From A Survey. International Journal of Software Engineering and Knowledge Engineering, 23(04), 507-522. esitatakse 40 tarkvaraarenduse spetsialisti hulgas läbiviidud küsitluse tulemused. Selle küsitlusega sooviti teada saada, millised tegevused aitavad parandada SQL-andmebaasil põhinevate andmebaasirakenduste hallatavust. Vastusele lisatud failis tuuakse välja kõik sellised aspektid, millel on küsitlusele vastanute arvates mõõdukas või suur positiivne mõju hallatavusele. See fail esitab artiklis esitatud diagrammi. ## Küsimus: Mul ei õnnestu vaadata loengute lindistusi, sest saan videote vaatamisel veateate. ERROR:Unable to process language file located at: language/ru.xml The file is either missing or corrupt. **Vastus:** Ilmselt on probleem selles, et veebilehitseja on vene keelne. Lahendus oleks kasutada inglise keelset veebilehitseja. Ehk siis peaksite ära muutma keele sätted. GoogleChromes saaks korda kui võtta Настройка и управление Google Chrome Настройки ->Показать дополнительные настройки -> Языки ->Настройка языков и способов ввода ja võtate kasutusse inglise keele (англиский (США)). ## Küsimus: Mul on veidi vaba aega ja tahaks kuulata audio- või videoloenguid. Kas oskate soovitada midagi andmebaaside kohta? **Vastus:** Kursus andmebaasisüsteemide kohta Carnegie Mellon ülikoolis. "Andmebaasid I" kursuse temaatika alla lähevad esimesed viis loengut. https://www.youtube.com/playlist?list=PLSE8ODhjZXjYutVzTeAds8xUt1rcmyT7x 01 Course introduction & Relational Data Model (Fall 2017) - täiendus teemale 2 02 Relational Algebra (Fall 2017) - täiendus teemale 3 03 Advanced SQL (Fall 2017) - täiendus teemadele 4, 5 04 Functional Dependencies (Fall 2017) - täiendus teemale 9 05 Normal Forms (Fall 2017) - täiendus teemale 9 Carnegie Mellon ülikoolis on andmebaaside teadusgrupp. Nende Youtube lehel leidub päris palju loenguid tehnilisemate (edasijõudnute) teemade kohta. Osasid nendest teemadest käsitleb ka sügisene "Andmebaasid II" õppeaine. https://www.youtube.com/channel/UCHnBsf2rH-K7pn09rb3qvkA Relatsioonilised andmebaasid: https://www.youtube.com/watch?v=qx0F7TfA8CI https://www.youtube.com/watch?v=kSZX3fBgg1A&index=5&list=PLWIxuiyTh_yY3w26sJMbdTDXuEYJp-GxT (puuduvate andmetega toimetulek. SQLis on selleks üks väga veider omamoodi elukas NULL - sellest ka loengu nimi) Esimene on küll väga lühike video, kuid lektoriks mõlemal on C.J.Date, kellel minu arvates on väga hea selgitamisoskus. NoSQL süsteemid ja suurandmed: https://www.youtube.com/watch?v=qI_g07C_Q5I (hea kõrgtaseme ülevaade; lektorist) https://www.youtube.com/watch?v=S79-buNhdhI (lektorist) --- # Teema: SQL ## Küsimus: Kas CHECK kitsendustes saab kasutada mittedeterministlikke funktsioone? **Vastus:** Deterministlik funktsioon tagastab samade argumentidega  (sisendandmetega) alati samasuguse väärtuse. Mittedeterministlik funktsioon võib tagastada samade argumentidega erinevatel ajahetkedel erineva tulemuse. Mittedeterministlikud funktsioonid on näiteks CURRENT_DATE (tagastab hetke kuupäeva), CURRENT_TIMESTAMP (tagastab hetke kuupäeva ja kellaaja koos ajavööndiga) ja LOCALTIMESTAMP (tagastab hetke kuupäeva ja kellaaja ilma ajavööndita).CHECK kitsendus on kujul CHECK(loogikaavaldis). Iga tabelisse lisatava rea korral peab selle loogikaavaldise väärtuse arvutamise tulemus olema TRUE või UNKNOWN (kui reas mõnes väljas väärtus puudub e on NULL). SQL:2011 standardi kohaselt:   "Certain <boolean value expression>s are identified as “retrospectively deterministic”. A retrospectively deterministic <boolean value expression> has the property that if it is True at one point time, then it is True for all later points in time if re-evaluated for the identical SQL-data by an arbitrary user with the identical set of privileges.   No integrity constraint shall be defined using a <search condition> that is not retrospectively deterministic.   Without Feature F672, “Retrospective check constraints”, conforming SQL language shall not contain a <check constraint definition> that generally contains CURRENT_DATE, CURRENT_TIMESTAMP, or LOCALTIMESTAMP."Järgnevas tabeli loomise lauses: kitsendus chk_pakkumine_alguse_aeg on retrospektiivselt deterministlik Kui lisada tabelisse rida, mis lisamise hetkel vastas sellele kitsendusele, siis see rida vastab sellele kitsendusele ka tulevikus. kitsendus chk_pakkumine_lopu_aeg ei ole retrospektiivselt deterministlik Kui lisada tabelisse rida, mis lisamise hetkel vastas sellele kitsendusele, siis mingil hetkel tulevikus see rida enam sellele kitsendusele ei vasta. Nii tekib kahetsusväärne olukord, kus tabelis on andmed, mis ei ole kooskõlas tabelile defineeritud kitsendusega. CREATE TABLE Pakkumine ( pakkumine_id INTEGER NOT NULL, alguse_aeg DATE NOT NULL, lopu_aeg DATE NOT NULL, CONSTRAINT pk_pakkumine PRIMARY KEY (pakkumine_id), CONSTRAINT chk_pakkumine_alguse_aeg CHECK (alguse_aeg<=CURRENT_DATE), CONSTRAINT chk_pakkumine_lopu_aeg CHECK (lopu_aeg>=CURRENT_DATE));Eelnevalt viidatud SQL standardi lõik ütleb, et kitsendusi, mis pole retrospektiivselt deterministlikud, ei tohiks saada defineerida. Kui andmebaasisüsteem ei toeta omadust  F672, “Retrospective check constraints”, siis ei peaks CHECK kitsendustes saama üldse CURRENT_DATE, CURRENT_TIMESTAMP ja LOCALTIMESTAMP kitsendusi kasutada.Milline on tegelik olukord andmebaasisüsteemides? Kasutasin katsetamiseks keskkondi DB Fiddle, SQL Fiddle ja db<>fiddle.Andmebaasisüsteemid jagunesid kaheks: CHECK kitsendustes ei saa üldse CURRENT_DATE, CURRENT_TIMESTAMP ja LOCALTIMESTAMP funktsioone kasutada (sulgudes veateade eelneva CREATE TABLE lause käivitamisel). MySQL 9 (Query Error: An expression of a check constraint 'chk_pakkumine_alguse_aeg' contains disallowed function: curdate.) MariaDB 10.7 (ERROR 1901 (HY000) at line 1: Function or expression 'curdate()' cannot be used in the CHECK clause of `chk_pakkumine_alguse_aeg`) Oracle 23ai (ORA-02436: date or system variable wrongly specified in CHECK constraint) IBM DB2 Developer-C 11.1 (SQL0546N  The check constraint "CHK_PAKKUMINE_ALGUSE_AEG" is invalid.) CHECK kitsendustes saab kasutada CURRENT_DATE, CURRENT_TIMESTAMP ja LOCALTIMESTAMP funktsioone piiranguteta, st saab luua ka kitsendusi, mis ei ole retrospektiivselt deterministlikud. PostgreSQL 17 SQLite 3.46 MS SQL Server 2022 (CURRENT_DATE tuli asendada GETDATE()) MS Access 2019 (CURRENT_DATE tuli asendada DATE()) Firebird 4 HSQLDB 1.8 (LibreOffice Base) Süsteemides, mis lubavad kitsendusi, mis pole retrospektiivselt deterministlikud, tuleb olla kitsenduste defineerimisel ise tähelepanelik! ## Küsimus: Kas Count(1) ridade arvu loendamiseks on kiirem kui Count(*)? **Vastus:** Oletame, et SQL-andmebaasis on tabel:Isik(isikukood, perenimi)Primaarvõti (isikukood)LauseSELECT Count(*) AS arvFROM Isik;leiab tabelis Isik olevate ridade arvu. Kui Count funktsiooni poole pöörduda nii: Count(<avaldis>), siis leitakse selliste ridade arv, mille korral avaldise väärtus ei ole NULL.SELECT Count(1) AS arvFROM Isik;Ühegi rea korral tabelis Isik ei ole sulgudes oleva avaldise väärtuse arvutamise tulemus NULL - seega tulemus on sama nagu eelmisel päringul. Need kaks lauset on seega loogiliselt samaväärsed. Võiks arvata, et nende lausete täitmise protseduur (täitmisplaan) ja seega täitmise kiirus on ühesugused. Enamikes andmebaasisüsteemides see ongi nii. Kuid nagu kirjutatakse SIIN, siis PostgreSQLis on Count(*) kasutava päringu täitmine kiirem kui Count(1) kasutava päringu täitmine.Katsetasin seda PostgreSQL (16) andmebaasis tabeli (hcv) põhjal, kus on üks miljon rida. Kasutasin töökiiruse leidmiseks EXPLAIN ANALYZE lauset, mille käivitamise korral näeb kasutaja lause täitmise plaani ja ka lause täitmiseks kulunud aega. Käivitasin neid lauseid vaheldumisi viis korda ja leidsin kummagi lause korral täitmisaegade geomeetrilise keskmise.Lause 1: EXPLAIN ANALYZE SELECT Count(*) AS arv FROM Hcv;Lause 2: EXPLAIN ANALYZE SELECT Count(1) AS arv FROM Hcv;Count(*): geomeetriline keskmine 69.1 msCount(1): geomeetriline keskmine 76.1 msMinu katsetus seega kinnitas seda väidet, kuid töökiiruse erinevused on kasutajale vähemärgatavad. **Märksõnad:** kokkuvõttefunktsioon, jõudlus, töökiirus, PostgreSQL ## Küsimus: Kas erinevates andmebaasisüsteemides on tekstiotsing vaikimisi tõstutundlik või tõstutundetu? **Vastus:** SELECT * FROM Isik WHERE perenimi='Mets';Tõstutundetu (case insensitive) otsingu korral leitakse nii isik perenimega Mets kui ka isik perenimega mets.Tõstutundliku (case sensitive) otsingu korral leitakse isik perenimega Mets, kuid ei leita isikut perenimega mets.Kuidas käituvad erinevad andmebaasisüsteemid? Oracle Database 23ai Free - tõstutundlikMicrosoft SQL Server 2022 - tõstutundetuMySQL 8 - tõstutundetuPostgreSQL 16 - tõstutundlik SQL Lite 3.27.2 - tõstutundetuMariaDB 10.7.8 - tõstutundetuMS Access 2019 - tõstutundetu ## Küsimus: Kas korduste eemaldamine IN/NOT IN alampäringus muudab lause täitmise kiiremaks või mitte? **Vastus:** Sõltub andmebaasisüsteemist. Näiteks PostgreSQLis on sellel suur mõju, MySQLis ei ole mõju. PostgreSQLis aeglustab korduste eemaldamine alampäringus IN päringu täitmist kolm korda kuid muudab NOT IN päringu täitmise absurdselt palju kiiremaks.Toon näite. Olgu meil PostgreSQL andmebaas, millel on järgmine kontseptuaalne struktuur[Facility]-1-------------0..*-[Health_care_visit]Tabelis Facility on 50_000 rida.Tabelis Health_care_visit on 1_000_000 rida.Järgnevad katsetused on tehtud PostgreSQL (16) põhjal. Täitmisplaanide ja täitmise kiiruse vaatamiseks kasutasin EXPLAIN ANALYZE lauset. Rõhutan, et nende ülesannete juures pakutud lahendusvariandid on loogiliselt samaväärsed e annavad alati sama tulemuse. Kõik need on kokku näide "abstraktsioonide lekkimise" kohta e selle kohta, kuidas andmete füüsilise ("süsteemi kaane all") salvestamise ja töötlemise küsimused "lekivad" andmete kasutaja maailma ja kokkuvõttes peab ta teadma, kuidas oleks konkreetses süsteemis kõige otstarbekam oma küsimusi formuleerida.Ülesanne: Leia tervishoiuasutused, kuhu on tehtud vähemalt üks visiit.Lahendus 1: Lause täitmiseks kasutatakse tabeli Facility primaarvõtmele ja tabeli Health_care_visit välisvõtmele loodud indekseid. Lause täitmine võtab umbes 100ms. SELECT * FROM Facility  WHERE facility_id IN (SELECT facility_id FROM Health_Care_visit);Lahendus 2: Lause täitmiseks loetakse ainult tabelite andmeid (st indekseid ei kasutata). Lause täitmine võtab umbes 300 ms. SELECT * FROM Facility  WHERE facility_id IN (SELECT DISTINCT facility_id FROM Health_Care_visit);Lahendus 3: Sama, mis lahendus 2. SELECT * FROM Facility  WHERE facility_id IN (SELECT facility_id FROM Health_Care_visit GROUP BY facility_id);Ülesanne: Leia tervishoiuasutused, kuhu pole tehtud ühtegi visiiti.Lahendus 1: Iga rea kohta tabelist Facility materialiseeritakse e arvutatakse välja ja salvestatakse mällu indeksi põhjal täidetud alampäringu tulemus. Lause täitmine võtab umbes 31 minutit. SELECT *  FROM Facility  WHERE facility_id NOT IN (SELECT facility_id  FROM Health_care_visit  WHERE facility_id IS NOT NULL); Lahendus 2: Peaaegu sama plaan kui esimese lahenduse korral, ainult et alampäringu tulemust ei materialiseerita. Lause täitmine võtab umbes 125 ms. SELECT *  FROM Facility  WHERE facility_id NOT IN (SELECT DISTINCT facility_id  FROM Health_care_visit  WHERE facility_id IS NOT NULL); Lahendus 3: Sama, mis lahendus 2. SELECT *  FROM Facility  WHERE facility_id NOT IN (SELECT facility_id  FROM Health_care_visit  WHERE facility_id IS NOT NULL GROUP BY facility_id);Proovisin alampäringus korduste eemaldamise mõju ka MySQL (8) andmebaasis ja seal ei paistnud sellel lause täitmisplaani koostamisele ja lause täitmise kiirusele mõju olevat. ## Küsimus: Kas olemasse tabelisse T ridade lisamiseks võib MS Accessis kasutada SELECT ... INTO T FROM ... lauset? **Vastus:** Ei! See oleks ränk viga. SELECT ... INTO T … põhjustab MS Accessis tabeli T kustutamise ja uuesti loomise. Uues tabelis T on: kaotsi läinud kõik seal varem olnud andmed, tabeliga seotud kitsendused, tabeliga seotud indeksid. Loodud tabelis on andmetüübid ja maksimaalsed lubatud andmete suurused valitud vastavalt päringus viidatud tabelite andmetüüpidele ja väljapikkustele.Andmete lisamiseks tabelisse (olgu selles andmeid või mitte) tuleb kasutada INSERT lauset.NB! SQL standardis ja paljudes teistes SQL-andmebaasisüsteemides on sarnaseks koopia loomiseks kasutusel CREATE TABLE ... AS ... lause. Kui üritate sellega luua tabelit T ja tabel T on juba andmebaasis vastavas skeemis olemas, siis lause täitmine ebaõnnestub (mitte ei kirjutata tabelit üle nagu MS Access seda teeb). Sama juhtub ka siis kui kasutada SELECT ... INTO lauset MS SQL Server andmebaasisüsteemis. **Märksõnad:** MS Access, MSAccess ## Küsimus: Kas otsingutingimus x10 saab olla täidetud, st kas sellise otsingutingimusega päringu tulemuses saab olla ridu? **Vastus:** Ei saa.AND tähendab, et mõlemad alamtingimused peavad olema täidetud - vaadake AND operatsiooni tõeväärtustabelit. Oletame, et tabelis T on veerg x, mis on täisarvu tüüpi.Kui käivitada päring: SELECT * FROM TWHERE x<1 AND x>10; , siis päringu täitmisel toimuvad kontseptuaalselt järgmised toimingud. Iga rea korral tabelist T leitakse x väärtus, pannakse see tingimuses oleva x asemele, saadakse väide ja kontrollitakse selle väite täidetust e kehtivust. Kui kontrolli tulemus on TRUE e rida vastab tingimusele, siis see rida on päringu tulemuses. Kui kontrolli tulemus on FALSE või UNKNOWN, siis rida ei ole tulemuses. Neli näidet: x=5 - väide: 5<1 AND 5>10 - kumbki alamtingimus pole täidetud - vale väide e kontrolli tulemus on FALSE - rida pole tulemuses. x=0 - väide: 0<1 AND 0>10 - esimene alamtingimus on täidetud ja teine ei ole - vale väide e kontrolli tulemus on FALSE - rida pole tulemuses. x=20 - väide 20<1 AND 20>10 - teine alamtingimus on täidetud ja esimene ei ole - vale väide e kontrolli tulemus on FALSE - rida pole tulemuses. x on NULL - väide NULL<1 AND NULL>10 - kummagi alamtingimuse täidetust ei saa kontrollida, sest NULL on nagu kinnine karp, mille sisse ei näe - väide, mille täidetus ei saa kontrollida e kontrolli tulemus UNKNOWN - rida pole tulemuses. Selle päringu tulemuses ei ole ühtegi rida. ## Küsimus: Kas saate tuua näite sellest, kuidas ebaotstarbekas SQL ülesande lahendus mõjutab vastuse saamise kiirust? **Vastus:** Olgu meil PostgreSQL andmebaas järgmise kontseptuaalse struktuuriga:[Facility]-1---------------0...*-[Health_care_visit] Facility - 50_000 ridaHealth_care_visit - 1_000_000 rida.Järgnevad katsetused on tehtud PostgreSQL (16) põhjal. Täitmisplaanide ja täitmise kiiruse vaatamiseks kasutasin EXPLAIN ANALYZE lauset. Rõhutan, et nende ülesannete juures pakutud lahendusvariandid on loogiliselt samaväärsed e annavad alati sama tulemuse. Ülesanne - leia iga patsiendi kohta, kui mitmes protsendis erinevates tervishoiuasutustest on ta teinud vähemalt ühe külastuse. Ümarda tulemus ühe kohani peale koma. Kirjutasin kaks lauset, et seda ülesannet lahendada. Lausetest on puudu nulliga jagamise vältimine, aga see ei muuda üldpilti. Lause 1 - Tekitatakse tabelite Health_care_visit ja ja Facility otsekorrutis (leitakse kõikvõimalikud ridade paarid). Kasutatakse Count(DISTINCT ...), et leida tulemuse põhjal erinevate tervishoiuasutuste arv ja erinevate tervishoiuasutuste arv, kus on tehtud vähemalt üks reserveerimine. SELECT hcv.patient_id, Round(Count(DISTINCT hcv.facility_id)::numeric/Count(DISTINCT facility.facility_id)*100,1) AS percentageFROM Health_care_visit AS hcv, FacilityGROUP BY hcv.patient_idORDER BY hcv.patient_id; Lause 2 - Kasutatakse Count(DISTINCT ...), et leida erinevate tervishoiuasutuste arv, kus on tehtud vähemalt üks reserveerimine. Tervishoiuasutuste arv leitakse eraldi alampäringuga. SELECT hcv.patient_id, Round(Count(DISTINCT hcv.facility_id)::numeric/(SELECT Count(*) AS cnt FROM Facility)*100,1) AS percentageFROM Health_care_visit AS hcvGROUP BY hcv.patient_idORDER BY hcv.patient_id; Lause 1 täitmiseks kulus 290 minutit ja lause 2 täitmiseks 370 millisekundit. Lause 1 täitmise plaanist (lisatud pildina siia küsimusele) on näha, et tsüklis moodustatakse tulemus, kus on 50_000_000_000 (50 miljardit) rida ja siis asutakse korduseid eemaldama. Tsükli käigus materialiseeritakse e salvestatakse eraldi koopiana miljon korda tabeli Facility läbikäimise tulemus. **Märksõnad:** otsekorrutis, Cartesiuse ristkorrutis, täitmisplaan, execution plan, protsent, protsendiarvutus ## Küsimus: Kas UPDATE lause võiks kirjutada nii, et WHERE klauslisse kirjutatud tingimuse asemel kirjutatakse SET klauslisse tingimus, mille täidetuse korral uuendatakse vastavat rida? **Vastus:** Süntaksi mõttes on see tehtav ja annaks soovituse tulemus, kuid PostgreSQL (16) näitel oleks see halva jõudlusega lahendus.Vaatame näidet.Andmebaasis on tabel Health_care_visit, kus on üks miljon rida.Ülesanne: Suurenda 2020. aastal alanud visiitide visiiditasu 10%. NB! 2020. aastal ei alanud ühtegi visiiti.Lahendus 1: Otsingu tingimus on WHERE klauslis. UPDATE Health_Care_visit SET visit_fee=visit_fee*1.1 WHERE Extract(YEAR FROM from_date)=2020;   Lahendus 2: Otsingutingimuse WHERE klauslisse kirjapaneku asemel kasutan SET klauslis CASE avaldist, mis leiab iga rea korral uue visiiditasu (võib jääda samaks või olla senisest 10% suurem).UPDATE Health_Care_visit SET visit_fee=CASE WHEN Extract(YEAR FROM from_date)=2020 THEN visit_fee*1.1 ELSE visit_fee END;Käivitan mõlemad laused ning vaatan EXPLAIN ANALYZE lause abil täitmisplaani ja täitmise aega. NB! Kuna EXPAIN ANALYZE korral lause täidetakse, siis panen andmemuudatused transaktsiooni plokki, mille lõpuks tagasi rulline, et andmebaasis andmed püsivalt ei muutuks.Lahendus 1: Süsteem loeb kõiki tabeli plokke ja filtreerib välja read, mis vastavad tingimusele ja mida tuleks uuendada. Lause täitmiseks kulus 254 ms.Lahendus 2: Süsteem loeb kõiki tabeli plokke ja uuendab kõiki tabeli ridu (arvutab iga rea korral välja CASE avaldise tulemuse ning kirjutab selle visit_fee välja). Lause täitmiseks kulus 24252 ms e 95 korda rohkem aega. ## Küsimus: Kas uuema ühendamise süntaksi korral võib WHERE klauslis olevad lisapiirangud kirjutada FROM klauslis ühendamise tingimusse? **Vastus:** Vaatlen näitena andmebaasi, millel on kontseptuaalne struktuur: [Dept]-0..1-----------0..*-[Emp]SIIN on PostgreSQL andmebaasi loomise laused ja järgnevat koodi saab katsetada näiteks DB Fiddle keskkonnas.INNER JOINNeed kaks lauset:SELECT *FROM Dept INNER JOIN Emp ON Dept.deptno=Emp.deptno AND Dept.dname LIKE 'A%';SELECT *FROM Dept INNER JOIN Emp ON Dept.deptno=Emp.deptno WHERE Dept.dname LIKE 'A%';ja need kaks lauset:SELECT *FROM Dept INNER JOIN Emp ON Dept.deptno=Emp.deptno AND Emp.sal>1000;SELECT *FROM Dept INNER JOIN Emp ON Dept.deptno=Emp.deptnoWHERE Emp.sal>1000;annavad samasuguse tulemuse.Lisakommentaarid: Mõni andmebaasisüsteem (nt MS Access) ei toeta lisapiirangute kirjutamist FROM klausli ühendamise tingimusse. PostgreSQL ja Oracle näiteks toetavad. Seega väheneb koodi porditavus. PostgreSQL ja Oracle näitel on lausete täitmisplaanid ja seega ka täitmise kiirus ühesugused. Pannes lisatingimused FROM klauslisse ei saa kasutada tabelite ühendamisel mugavat ja kompaktset USING (<ühised veerud>) süntaksi. Selline lause ei toimi: SELECT * FROM Dept INNER JOIN Emp USING (deptno) AND Emp.sal>1000; Vanema ühendamise süntaksi puhul toodi probleemina välja, et WHERE klausel on tingimustega ülekoormatud. Pannes kõik tingimused FROM klauslisse on tulemus samasugune. Olukorras, kus laused annavad ühesuguse tulemuse, ei ole kõigi tingimuste koondamine FROM klauslisse mõttekas. Veel üks näide - tabelite põhjal, kus on palju rohkem andmeid (tabelis Health_care_visit on 1_000_000 rida). Täitmisplaanid ja täitmise kiirus on ühesugune, kuid loetavuse poolest on minu arvates FROM ja WHERE klausli eristamine parem.SELECT Hcv.*FROM Health_care_visit AS Hcv INNER JOIN Facility AS F ON Hcv.facility_id=F.facility_idAND EXTRACT(year FROM Hcv.from_date) >2010 AND F.facility_name ILIKE 'A%'INNER JOIN Postal_address AS P ON Hcv.postal_address_id=P.postal_address_id AND P.city='Kaduna';SELECT Hcv.*FROM Health_care_visit AS Hcv INNER JOIN Facility AS F USING (facility_id)INNER JOIN Postal_address AS P USING (postal_address_id)WHERE EXTRACT(year FROM Hcv.from_date) >2010 AND F.facility_name ILIKE 'A%'AND P.city='Kaduna';OUTER JOINLaused annavad erineva tulemuse.SELECT *FROM Dept LEFT JOIN Emp ON Dept.deptno=Emp.deptno AND Dept.dname LIKE 'A%';Tulemuses on kõik osakonnad (töötajatega või mitte) - ka sellised, mille nimi ei alga A tähega.SELECT *FROM Dept LEFT JOIN Emp ON Dept.deptno=Emp.deptno WHERE Dept.dname LIKE 'A%';Tulemuses on ainult sellised osakonnad (töötajatega või mitte), mille nimi algab A tähega.SELECT *FROM Dept LEFT JOIN Emp ON Dept.deptno=Emp.deptno AND Emp.sal>1000;Tulemuses on töötajad, kelle palk on üle 1000 EUR + üks rida iga osakonna (Dept) kohta, milles pole ühtegi üle 1000 EUR palgaga töötajat. Seda saab kasutada, et lahendada ülesanne: Leia osakonnad, kus pole ühtegi üle 1000 EUR palgaga töötajat.SELECT Dept.*FROM Dept LEFT JOIN Emp ON Dept.deptno=Emp.deptnoAND Emp.sal>1000WHERE Emp.deptno IS NULL;Järgneva päringu tulemuses on töötajad, kelle palk on üle 1000 EUR.SELECT *FROM Dept LEFT JOIN Emp ON Dept.deptno=Emp.deptnoWHERE Emp.sal>1000; ## Küsimus: Kas ühes ja samas SQL päringus võib segamini kasutada vanemat ja uuemat ühendamise süntaksi? **Vastus:** Jah, see on tehniliselt võimalik. Kuid see ei ole soovitav, sest halvendab koodi loetavust.Halvem.SELECT Tudeng.tudkood, Tudeng.perenimi, Oppimine.oppim_algus, Oppimine.oppim_lopp, Aine.aine_kood, Aine.nimetusFROM Aine, Tudeng INNER JOIN Oppimine ON Tudeng.tudkood = Oppimine.tudengWHERE Aine.aine_kood = Oppimine.aine;Parem.SELECT Tudeng.tudkood, Tudeng.perenimi, Oppimine.oppim_algus, Oppimine.oppim_lopp, Aine.aine_kood, Aine.nimetusFROM (Tudeng INNER JOIN Oppimine ON Tudeng.tudkood = Oppimine.tudeng)INNER JOIN Aine ON Aine.aine_kood = Oppimine.aine;--läbivalt uuem süntaksSELECT Tudeng.tudkood, Tudeng.perenimi, Oppimine.oppim_algus, Oppimine.oppim_lopp, Aine.aine_kood, Aine.nimetusFROM Tudeng, Oppimine, AineWHERE Tudeng.tudkood = Oppimine.tudengAND Aine.aine_kood = Oppimine.aine;--läbivalt vanem süntaks **Märksõnad:** puhas kood, clean code, SQL, join, ühendamine ## Küsimus: Kuidas arvutada SQLis protsenti nii, et ei peaks sama tabelit mitmekordselt lugema? **Vastus:** PostgreSQLis on andmebaas järgmise kontseptuaalse struktuuriga.[Facility_type]-1-------0..*-[Facility]-1---------------0..*-[Health_care_visit]Tabelis Facility_type on 5 rida.Tabelis Facility on 5_000 rida.Tabelis Health_care_visit on 1_000_000 rida.Järgnevalt esitatakse kolm ülesannet ja nende lahendused PostgreSQLis (16). Lahendus 1 korral tehakse kaks päringut samadesse tabelitesse. Need päringud vormistatakse  parema loetavuse huvides ühiste tabeli avaldistena (common table expression) - need on lause alguses WITH klauslis. Lausete täitmisplaanid näitavad, et samu tabeleid ja nende indekseid loetakse mitmekordselt. Lahendus 2 korral tehakse samade tabelite põhjal üks päring. Protsendi arvutamiseks vajalike arvude leidmiseks kasutatakse Count kokkuvõttefunktsiooni koos FILTER predikaadiga.  Lausete täitmisplaanid näitavad, et samu tabeleid ja nende indekseid loetakse ühekordselt. PostgreSQLis peab jagamisoperatsioonide täpsuse huvides vähemalt ühe argumendi teisendama Decimal tüüpi (seda teeb ::decimal). Kõigi lausete puhul kasutatakse nulliga jagamise vältimiseks Nullif funktsiooni, mis tagastab NULL kui argumendid on võrdsed (Väärtus/NULL=> NULL). Kõigi lausete puhul kasutatakse ümardamiseks Round funktsiooni.  Kõigi lausete puhul vaadatakse täitmisplaani ja täitmise kiirust kasutades EXPLAIN ANALYZE lauset. Ülesanne 1: Leia, kui mitu protsenti moodustab tervishoiuasutuste külastuste arv, kus tasu on alla 9000, külastuste arvust, kus tasu on 9000 või rohkem. Väldi nulliga jagamist. Ümarda tulemus ühe kohani peale koma.Lahendus 1 WITH smaller_fee AS (SELECT Count(*) AS cnt FROM Health_care_visit WHERE visit_fee<9000), higher_fee AS (SELECT Count(*) AS cnt FROM Health_care_visit WHERE visit_fee>=9000) SELECT Round(smaller_fee.cnt::decimal*100/nullif(higher_fee.cnt::decimal,0),1) AS percent FROM smaller_fee, higher_fee; Täitmise aeg: 208 ms. Lahendus 2 SELECT Round(Count(*) FILTER (WHERE visit_fee<9000)::decimal/nullif(Count(*) FILTER (WHERE visit_fee>=9000)::decimal,0),1) AS percent FROM Health_care_visit; Täitmise aeg: 136 ms.Ülesanne 2: Leia, kui mitu protsenti moodustab kliinikute külastuste arv haiglate külastuste arvust. Väldi nulliga jagamist. Ümarda tulemus ühe kohani peale koma.Lahendus 1   WITH hospital_visits AS (SELECT Count(*) AS cnt FROM Facility AS F INNER JOIN Health_care_visit AS Hcv USING (facility_id) WHERE facility_type_code='HOS01'), clinic_visits AS (SELECT Count(*) AS cnt FROM Facility AS F INNER JOIN Health_care_visit AS Hcv USING (facility_id) WHERE facility_type_code='CLI06') SELECT Round(clinic_visits.cnt::decimal*100/nullif(hospital_visits.cnt::decimal,0),1) AS percent FROM hospital_visits, clinic_visits; Täitmise aeg: 113 ms.Lahendus 2 SELECT Round(Count(*) FILTER (WHERE facility_type_code='CLI06')::decimal*100/nullif(Count(*) FILTER (WHERE facility_type_code='HOS01')::decimal,0),1) AS hospital_visits_cnt FROM Facility AS F INNER JOIN Health_care_visit AS Hcv USING (facility_id); Täitmise aeg: 98 ms.Ülesanne 3: Leia, kui mitu protsenti moodustab tervishoiuasutuste arv, kus on vähemalt üks külastus, mille eest tasuti üle 9000 ühiku raha, kõigi asutuste arvust, kus on tehtud vähemalt üks külastus. Väldi nulliga jagamist. Ümarda tulemus ühe kohani peale koma.Lahendus 1   WITH total_facilities AS (SELECT Count(*) AS cnt FROM Facility), facilities_with_high_fees AS (SELECT Count(*) AS cnt FROM Facility AS F  WHERE EXISTS (SELECT * FROM Health_care_visit AS Hcv WHERE F.facility_id=Hcv.facility_id AND visit_fee>9000 )) SELECT Round(facilities_with_high_fees.cnt*100/nullif(total_facilities.cnt,0),1) AS percent FROM total_facilities, facilities_with_high_fees;Täitmise aeg: 122 ms. Lahendus 2 SELECT Round(Count(DISTINCT Hcv.facility_id) FILTER (WHERE visit_fee>9000)::decimal*100/nullif(Count(DISTINCT F.facility_id)::decimal,0),1) AS percent FROM Facility AS F INNER JOIN Health_care_visit AS Hcv USING (facility_id);Täitmise aeg: 462 ms.Järeldused. Sama ülesannet saab lahendada mitmel erineval viisil. Protsendi arvutamine nii, et sama tabelit ei pea mitu korda lugema on mõnikord kiirem kui protsendi arvutamine nii, et sama tabelit loetakse mitu korda (ülesanded 1 ja 2) kuid mõnikord ei ole (ülesanne 3). Ülesande 3 lahenduse 2 puhul tundub probleemiks olevat vajadus eemaldada korduseid. **Märksõnad:** protsent, protsendiarvutus, FILTER klausel, nulliga jagamine ## Küsimus: Kuidas kasutada õigesti TOP (MS Access) ja FETCH FIRST n ROWS WITH TIES (PostgreSQL) predikaate väärtuste jadas kohal x olevate väärtuste leidmiseks? **Vastus:** TOP n - saab kasutada MS Accessis (samaväärset TOP ... WITH TIES saab kasutada MS SQL Serveris). SQL standard ei kirjelda. LIMIT n - Saab kasutada nt PostgreSQLis (ja ka nt LibreOffice Baseis). SQL standard ei kirjelda. FETCH FIRST n ROWS ONLY - Samaväärne LIMITiga. Saab kasutada nt PostgreSQLis. Seda kirjeldab SQL standard. FETCH FIRST n ROWS WITH TIES - Samaväärne MS Accessi TOPiga. Saab kasutada nt PostgreSQLis. Seda kirjeldab SQL standard. Kõik need predikaadid põhinevad sellel, et read sorteeritakse ja valitakse esimesed read. LIMIT n ja FETCH FIRST n ROWS ONLY tagastavad maksimaalselt n rida. TOP n ja FETCH FIRST n ROWS WITH TIES võivad tagastada rohkem kui n rida. Kui sorteerimise aluseks olevas veerus on reas n mingi väärtus, mis on ka järgnevates ridades, siis on tulemuses ka need read. NB! PostgreSQLis saaks järgneva kahe ülesande lahendamiseks edukalt kasutada ka Dense_rank aknafunktsiooni. See leiab tiheda pingerea. Tihedas pingereas on asetused näiteks 1,1,2, mitte 1,1,3. Lahenduseks on leida suuruste või esinemiste arvu pingerida ja valida sealt kolmandal kohal olevad tulemused.Loon näitena tabeliCREATE TABLE Vaartus (suurus SMALLINT NOT NULL);INSERT INTO Vaartus(suurus) VALUES (10);INSERT INTO Vaartus(suurus) VALUES (10);INSERT INTO Vaartus(suurus) VALUES (10);INSERT INTO Vaartus(suurus) VALUES (9);INSERT INTO Vaartus(suurus) VALUES (9);INSERT INTO Vaartus(suurus) VALUES (9);INSERT INTO Vaartus(suurus) VALUES (8);INSERT INTO Vaartus(suurus) VALUES (8);INSERT INTO Vaartus(suurus) VALUES (7);Ülesanne 1: Leia tabelist Vaartus read, kus on suuruselt kolmas suurus. Antud andmete korral tuleks leida read, kus suurus on 8.Vale lahendus MS Accessis:SELECT suurusFROM VaartusWHERE suurus = (SELECT Min(suurus) AS mFROM (SELECT TOP 3 suurusFROM VaartusORDER BY suurus DESC) AS ap);Vale lahendus PostgreSQLis:SELECT suurusFROM VaartusWHERE suurus = (SELECT Min(suurus) AS mFROM (SELECT suurusFROM VaartusORDER BY suurus DESCFETCH FIRST 3 ROWS WITH TIES) AS ap);Tulemuseks on read, kus suurus on 10.Alampäring, kus on TOP/FETCH, ei leia mitte kolme erinevat suurimat suurust, vaid suuruse järgi kahanevalt sorteeritud tulemusest kolm esimest rida. Juhul kui on veel mõni rida, kus on esimeses kolmes reas olnud suurus, siis on ka see tulemuses. Antud juhul on tulemuses read, kus suurus on 10.Õige lahendus MS Accessis:SELECT suurusFROM VaartusWHERE suurus = (SELECT Min(suurus) AS mFROM (SELECT DISTINCT TOP 3 suurusFROM VaartusORDER BY suurus DESC) AS ap);Õige lahendus PostgreSQLis:SELECT suurusFROM VaartusWHERE suurus = (SELECT Min(suurus) AS mFROM (SELECT DISTINCT suurusFROM VaartusORDER BY suurus DESCFETCH FIRST 3 ROWS WITH TIES) AS ap);Sisemine alampäring leiab kolm erinevat kõige suuremat suurust. Välimine alampäring leiab nende hulgast kõige väiksema. Põhipäring leiab kõik read, kus on leitud suurus. Antud juhul võib alampäringus kasutada ka FETCH FIRST 3 ROWS ONLY või LIMIT, sest see ei muuda tulemust.Ülesanne 2: Leia tabelist Vaartus esinemiste arvult kolmandal kohal olevad suurused. Väljasta suurus ja selle esinemiste arv. Antud andmete korral tuleks leida suurus 7, mida esineb üks kord.Vale lahendus MS Accessis:SELECT suurus, Count(*) AS arvFROM VaartusWHERE suurus=(SELECT Min(suurus) AS mFROM (SELECT TOP 3 suurus, Count(*) AS arvFROM VaartusGROUP BY suurusORDER BY Count(*) DESC) AS ap)GROUP BY suurus;Vale lahendus PostgreSQLis:SELECT suurus, Count(*) AS arvFROM VaartusWHERE suurus=(SELECT Min(suurus) AS mFROM (SELECT suurus, Count(*) AS arvFROM VaartusGROUP BY suurusORDER BY Count(*) DESCFETCH FIRST 3 ROWS WITH TIES) AS ap)GROUP BY suurus;Tulemuseks on suurus 8, mida esineb kaks korda.Alampäring, kus on TOP/FETCH, ei leia mitte kolme erinevat suurimat suuruste esinemiste arvu, vaid arvu järgi kahanevalt sorteeritud tulemusest kolm esimest rida. Juhul kui on veel mõni rida, kus on esimeses kolmes reas olnud arv, siis on ka see tulemuses. Antud juhul on tulemuses kaks rida, kus arv on 3 ja üks rida, kus arv on kaks. Õige lahendus MS Accessis:SELECT suurus, Count(*) AS arvFROM VaartusGROUP BY suurusHAVING Count(*)=(SELECT Min(arv) AS mFROM (SELECT DISTINCT TOP 3 Count(*) AS arvFROM VaartusGROUP BY suurusORDER BY Count(*) DESC) AS ap);Õige lahendus PostgreSQLis:SELECT suurus, Count(*) AS arvFROM VaartusGROUP BY suurusHAVING Count(*)=(SELECT Min(arv) AS mFROM (SELECT DISTINCT Count(*) AS arvFROM VaartusGROUP BY suurusORDER BY Count(*) DESCFETCH FIRST 3 ROWS WITH TIES) AS ap);Sisemine alampäring leiab kolm erinevat kõige suuremat esinemiste arvu. Välimine alampäring leiab nende hulgast kõige väiksema. Põhipäring leiab erinevate suuruste esinemiste arvu ja jätab alles read, kus see arv on võrdne alampäringutega leitud arvuga. Antud juhul võib alampäringus kasutada ka FETCH FIRST 3 ROWS ONLY või LIMIT, sest see ei muuda tulemust. ## Küsimus: Kuidas konkateneerida MS Accessis, PostgreSQLis ja LibreOffice Baseis tekstilisi väärtuseid, kui üks väärtus puudub (on NULL)? **Vastus:** Oletame, et andmebaasis on tabel, kuhu on lisatud kaks rida andmeid. Ühel isikul perenimi puudub (on NULL).CREATE TABLE Isik(isik_id INTEGER,eesnimi VARCHAR(50) NOT NULL,perenimi VARCHAR(50),CONSTRAINT pk_isik PRIMARY KEY (isik_id));INSERT INTO Isik (isik_id, eesnimi) VALUES (1,'Mati');INSERT INTO Isik (isik_id, eesnimi, perenimi) VALUES (2,'Kati','Karu');Ülesanne: Leia kõik isikud. Väljasta iga isiku kohta isik_id ning ees- ja perenimi ühe stringina. Nime komponentide vahel peab olema tühik.PostgreSQLSELECT isik_id, eesnimi || ' ' || perenimi AS nimiFROM Isik;Isikul, kelle perenimi on NULL, on nime väljas samuti NULL, sest NULL || 'tekst'=>NULLKuidas saada tulemus, kus puuduva perenimega isikul on nime väljas eesnimi?Lahendus 1: Funktsioon Coalesce tagastab vasakult lugedes esimese argumendi, mis pole NULL. Selle abil asendatakse NULL tühja stringiga. Funktsiooni Trim abil eemaldatakse stringi lõpust tühik.SELECT isik_id, Trim(eesnimi || ' ' || Coalesce(perenimi,'')) AS nimiFROM Isik;Lahendus 2: SELECT isik_id, Trim(Concat(eesnimi,' ',perenimi)) AS nimiFROM Isik;Lahendus 3: Trim funktsiooni tühiku eemaldamiseks eesnime järelt ei ole vaja.SELECT isik_id, Concat_ws(' ', eesnimi, perenimi) AS nimiFROM Isik;Lahendus 4:SELECT isik_id, Trim(Format('%1$s %2$s', eesnimi, perenimi)) AS nimiFROM Isik;MS AccessSELECT isik_id, Trim(eesnimi & ' ' & perenimi) AS nimiFROM Isik;MS Accessis on kaks eraldi stringide konkatenatsiooni operaatorit, mille korral on erinevus tulemuses, kui argument on NULL.NULL & 'tekst'=>'tekst'NULL+tekst=>'tekst'LibreOffice Base (kasutab HSQLDB)SELECT ISIK_ID, Trim(BOTH FROM (EESNIMI || ' ' || Coalesce(PERENIMI,''))) AS NIMIFROM ISIK;Sarnaselt PostgreSQLile NULL || 'tekst'=>NULL. Seega kasutatakse Coalesce funktsiooni, et asendada NULL tühja stringiga. ## Küsimus: Kuidas kustutada korraga mitu tabeliga seotud kitsendust? **Vastus:** See on hea näide, kuidas SQLi dialekt e mägimurrak erineb erinevates andmebaasisüsteemides detailide poolest. Järgnev katsetus tehti keskkondades DB Fiddle, SQL Fiddle ja db<>fiddle. CREATE TABLE Riik (riik_kood CHAR(3) NOT NULL, CONSTRAINT pk_riik PRIMARY KEY (riik_kood));   CREATE TABLE Isik(isik_id INTEGER NOT NULL, pikkus SMALLINT NOT NULL, kaal SMALLINT NOT NULL, riik_kood CHAR(3) NOT NULL, CONSTRAINT pk_isik PRIMARY KEY (isik_id), CONSTRAINT chk_isik_pikkus CHECK (pikkus>0), CONSTRAINT chk_isik_kaal CHECK (kaal>0), CONSTRAINT fk_isik_riik FOREIGN KEY (riik_kood) REFERENCES Riik (riik_kood)); Kustuta tabelist Isik ühe lausega CHECK kitsendused ning välisvõtme kitsendus.PostgreSQL (17), MySQL (9),  Firebird (4), MariaDB (10.9): ALTER TABLE Isik DROP CONSTRAINT chk_isik_pikkus, DROP CONSTRAINT chk_isik_kaal, DROP CONSTRAINT fk_isik_riik;--komadegaOracle (23ai), IBM DB2 (11): ALTER TABLE Isik DROP CONSTRAINT chk_isik_pikkus DROP CONSTRAINT chk_isik_kaal DROP CONSTRAINT fk_isik_riik;--komadeta MS SQL Server (2022): ALTER TABLE Isik DROP CONSTRAINT chk_isik_pikkus, chk_isik_kaal, fk_isik_riik;MS Access (365): ALTER TABLE Isik DROP CONSTRAINT chk_isik_pikkus; ALTER TABLE Isik DROP CONSTRAINT chk_isik_kaal; ALTER TABLE Isik DROP CONSTRAINT fk_isik_riik;--eraldi lausedLibreOffice Base (HSQLDB), SQLite (3.39):Kitsendusi saab defineerida, kuid ALTER TABLE lausega kustutada ei saa. ## Küsimus: Kuidas leida andmebaasist andmeid, mida seal justkui ei ole? Näiteks on andmebaasis andmed külaliste ja nende hotellide reserveerimiste kohta ja pean leidma külalised, kes EI OLE, 2014. aastal ühegi reserveerimist alustanud. **Vastus:** Andmebaasi kontseptuaalne struktuur on antud juhul järgmine.[Külaline]-1----------------0..*-[Reserveerimine] Võimalik ülesande lahendus on selline. SELECT Külaline.külalise_nr, Külaline.perenimiFROM KülalineWHERE Külaline.külalise_nr NOT IN(SELECT Reserveerimine.külalise_nr FROM ReserveerimineWHERE Year(Reserveerimine.alguse_aeg) = 2014); SQLis me töötame hulkadega. Oletame näiteks, et teete fotosid ja peate valima, milliseid tahate säilitada. On kaks fotode hulka - need mida säilitada ja need mida mitte. Säilitatavaid fotosid võib hakata ükshaaval välja valima. Kuid mõnikord võib lihtsam olla vaadata kõik fotod üle ja visata ära need, mis ei tulnud kindlasti välja. Kõik allesjäänud fotod kuuluvad säilitamisele. Nii ka siin - alampäringuga leian kõik külalised, kellel on mõni reserveerimine 2014. aastal alanud. Põhipäringuga leian kõik ülejäänud külalised. Nende hulka kuuluvad nii külalised, kellel pole üldse reserveeringuid kui ka need, kelle kõik reserveeringud on alanud muul ajal kui 2014. aastal. Siit tuleb välja üks üldine probleemide lahendamise strateegia (SQLis ja mujal). Kui tahan leida mingitele tingimusele vastavad olemid või seosed, siis otsin kõigepealt kõiki neid, mis minu tingimustele ei vasta ja siis leian kõik ülejäänud seda tüüpi olemid või seosed - need ongi need, mida otsin.   ## Küsimus: Kuidas Mauruse otsing täpsemalt töötab? Millist tuge pakkus selle realiseerimiseks andmebaasisüsteem, mida Maurus kasutab? **Vastus:** Mauruse kasutajad soovisid sageli, et seal oleks otsingu funktsionaalsus. Lisasin Maurusesse selle funktsionaalsuse. Otsing on võimalik kodulehe piires. Leiate võimaluse seda teha iga aine kodulehe paremast ülaservast. Otsing toimub üle aine sisu kirjelduse, materjalide metaandmete, tegevuskava, teadete (v.a isiklikud teated), kasutajatoe küsimuste/vastuste, viidete, tähaegade, ülesannete (kuid mitte nende vastused) ja vastuvõtuaegade. Otsingu tulemused on ühel lehel nende kategooriate kaupa grupeerituna. Materjale, teateid ja kasutajatoe küsimusi/vastuseid on otsingu tulemuses igaühte kuni 10. Viiteid on tulemuses kuni 20. Materjalide puhul ei toimu otsing mitte failide sisu, vaid materjale kirjeldavate andmete (metaandmete) põhjal. Kuna Maurus kasutab PostgreSQL andmebaasisüsteemi, siis tegi PostgreSQLi pakutav täisteksti otsingu funktsionaalsus, mille kohta saab näiteks lugeda SIIT ja SIIT, selle funktsionaalsuse realiseerimise lihtsamaks. Järgnevalt esitan koodinäite. Näiteks oletame, et tahan lisada teadete otsimise võimaluse ning et andmebaasis on tabel Avalik_teade, üle mille veergude pealkiri ja sisu peaks otsing toimuma. CREATE TABLE Avalik_teade(avalik_teade_id SERIAL,pealkiri TEXT NOT NULL,sisu TEXT NOT NULL,CONSTRAINT pk_avalik_teade PRIMARY KEY (avalik_teade_id));INSERT INTO Avalik_teade (pealkiri, sisu) VALUES ('Otsinguvõimalus', 'Kodulehel saab nüüd teha otsingut'); Lisan tabelisse veeru tsv, mis hakkab iga teate korral sisaldama spetsiaalset pealkirja ning sisu kokkuvõtet ja on ühtlasi aluseks nende alusel otsingute tegemisele. See veerg on tüüpi tsvector. See on spetsiifiline PostgreSQLi andmetüüp. Kahjuks ei ole täistektiotsingutel eesti keele tuge, tänu millele oskaks andmebaasisüsteem otsingu tegemisel arvestada keele eripäradega. Seega kasutan inglise keele (english) reegleid. Tabelisse lisatud rea korral oleks veerus tsv väärtus: 'kodulehel':2 'nüüd':4 'otsingut':6 'otsinguvõimalus':1 'saab':3 'teha':5Andmete automaatseks uuendamiseks tekstiotsingu veerus on kaks võimalust.Võimalus 1. Lisan tabelisse kohustusliku arvutatava veeru, mille väärtus on salvestatud kettale (stored).ALTER TABLE Avalik_teadeADD COLUMN tsv tsvectorGENERATED ALWAYS AS (to_tsvector('english', coalesce(pealkiri, '') || ' ' || coalesce(sisu, ''))) STORED NOT NULL;coalesce funktsioon tagastab vasakult lugedes esimese argumendi, mis ei ole NULL. coalesce(pealkiri,'') avaldis tähendab, et kui pealkiri on olemas (pole NULL) tagastab funktsioon pealkirja, vastasel juhul teiseks argumendiks oleva tühja stringi. Tühi string ja NULL on kaks ise asja - tühi string on väärtus, kuid NULL on marker, mis tähistab väärtuse puudumist. coalesce läheb vaja, sest PostgreSQLi stringide ühendamise (konkatenatsiooni) operaator käitub juhul kui üks argument on NULL järgnevalt: 'tekst' || NULL => NULL. Juhuks kui teates pealkiri või sisu puudub tuleb enne nende ühendamist kontrollida kas üks nendest on NULL ja vajadusel asendada see tühja stringiga: 'tekst' || '' => 'tekst'Võimalus 2. Lisan tabelisse uue veeru ning lisan tabelile trigeri, mis tabelisse rea lisamisel või olemasolevas reas pealkirja või sisu uuendamisel, arvutab tsvector väärtuse ja salvestab sellesse veergu. ALTER TABLE Avalik_teade ADD COLUMN tsv tsvector; Loon tabeliga seotud trigeri, mis andmete tabelisse lisamisel või muutmisel värskendab veergudes pealkiri ja sisu olevate andmete põhjal veerus tsv olevaid andmeid. Määran, et ridade uuendamise (UPDATE) korral peaks triger käivituma ainult siis, kui andmeid uuendatakse (UPDATE) mingis kindlas veerus. CREATE TRIGGER teade_tsv_iu BEFORE INSERT OR UPDATE OF pealkiri, sisuON Avalik_teade FOR EACH ROW EXECUTE PROCEDURE tsvector_update_trigger(tsv, 'pg_catalog.english', pealkiri, sisu); Teen andmemuudatuse, mis tänu eelnevale trigerile tingib andmete lisamise veergu tsv. UPDATE Avalik_teade SET pealkiri=pealkiri; Muudan veeru tsv kohustuslikuks. ALTER TABLE Avalik_teade ALTER COLUMN tsv SET NOT NULL;   Loon veerule tsv otsingu kiirendamiseks indeksi, ükskõik kas kasutan võimalust 1 või 2. CREATE INDEX teade_tsv_idx ON Avalik_teade USING gin(tsv); Järgnev päring leiab tabelist Avalik_teade sellised teated, mis sisaldavad sõna "otsingut". Päring väljastab teate identifikaatori, pealkirja, sisu ning pealkirja ja sisu põhjal moodustatud kokkuvõtte, kus on otsisõna esile tõstetud. Päringu tulemus on sorteeritud tulemuse relevantsuse hinnangu alusel kahanevalt. Päringu tulemuses on maksimaalselt 10 rida.. SELECT avalik_teade_id, pealkiri, sisu, ts_headline(coalesce(pealkiri,'') || ' ' || coalesce(sisu,''), q) AS fragment FROM (SELECT avalik_teade_id, pealkiri, sisu, q, ts_rank_cd(tsv,q) AS rank FROM Avalik_teade, to_tsquery('otsingut') AS q WHERE tsv @@ q ORDER BY rank DESC FETCH FIRST 10 ROWS ONLY) AS foo; **Märksõnad:** tekstiotsing ## Küsimus: Kuidas oleks PostgreSQLis töökiiruse mõttes kõige efektiivsem leida andmed ühest tabelist ja väljastada tulemuses ka tõeväärtus, mis leitakse teises tabelis olevate andmete põhjal? **Vastus:** Järgnev katsetus on tehtud PostgreSQL (16) põhjal.Andmebaasis on tabelid järgmise kontseptuaalse struktuuriga:[Person]-1----------0..*-[Health_care_visit]Tabelis Person on 70_000 rida.Tabelis Health_care_visit on 1_000_000 rida.Tabelis Health_care_visit on liitindeks, mille esimene veerg on person_id, ja millesse kuulub ka veerg from_date.Ülesandeks on leida iga isiku kohta tema isiku id, eesnimi, perenimi, sünniaeg ja tõeväärtus, mis näitab, kas isikul on alanud viimase viie aasta jooksul vähemalt üks visiit (TRUE) või mitte (FALSE).Kolm võimalikku lahendust.Lahendus 1: SELECT klauslis on korreleeruv EXISTS alampäring SELECT party_id, first_name, last_name, birth_date, EXISTS (SELECT * FROM Health_care_visit AS hcv  WHERE hcv.patient_id=person.party_id AND EXTRACT (YEAR FROM from_date) BETWEEN EXTRACT(YEAR FROM CURRENT_DATE)-5 AND EXTRACT(YEAR FROM CURRENT_DATE)) AS has_recent_visits FROM Person; Lahendus 2: SELECT klauslis on korreleeruv alampäring, millega loendatakse isikuga seotud sobivate visiitide arv ja väljastatakse tõeväärtus TRUE, kui see arv on suurem kui 0. SELECT party_id, first_name, last_name, birth_date, (SELECT Count(*)>0 AS reslt FROM Health_care_visit AS hcv  WHERE hcv.patient_id=person.party_id AND EXTRACT (YEAR FROM from_date) BETWEEN EXTRACT(YEAR FROM CURRENT_DATE)-5 AND EXTRACT(YEAR FROM CURRENT_DATE)) AS has_recent_visits FROM Person;   Lahendus 3: Kasutatakse kokkuvõttefunktsiooni Bool_or, mis tagastab ridade rühma kohta tõeväärtuse TRUE, kui vähemalt ühe rühma kuuluva rea puhul arvutatud tõeväärtus on TRUE.SELECT party_id, first_name, last_name, birth_date, Bool_or(EXTRACT (YEAR FROM from_date) BETWEEN EXTRACT(YEAR FROM CURRENT_DATE)-5 AND EXTRACT(YEAR FROM CURRENT_DATE)) AS has_recent_visits FROM Person INNER JOIN Health_care_visit AS hcv  ON hcv.patient_id=person.party_idGROUP BY party_id, first_name, last_name, birth_date;Lahendus 4: Ühises tabeli avaldises (common table expression) leitakse hiljuti külastusi teinud patsientide identifikaatorid. Põhipäringus ühendatakse need andmed välisühendamist kasutades tabeliga Person - välisühendamist kasutatakse, et tulemuses oleks ka need isikud, kellel hiljutisi külastusi ei ole.  WITH recent_visitors AS (SELECT DISTINCT patient_id FROM Health_care_visit WHERE EXTRACT (YEAR FROM from_date) BETWEEN EXTRACT(YEAR FROM CURRENT_DATE)-5 AND EXTRACT(YEAR FROM CURRENT_DATE)) SELECT party_id, first_name, last_name, birth_date, CASE WHEN rv.patient_id IS NOT NULL THEN TRUE ELSE FALSE END AS  has_recent_visits FROM Person LEFT JOIN recent_visitors AS rv  ON rv.patient_id=person.party_id; Kasutasin lausete käivitamiseks EXPLAIN ANALYZE lauset. Sellisel juhul lause täidetakse, kasutajale tulemust ei näidata, kuid kasutaja näeb lause täitmisplaani (protseduuri, mille alusel andmebaasisüsteem lause täidab) ja täitmise aega.Kõigil kolmel lausel oli täitmisplaan erinev. Kõige kiiremini täideti lahendus 1 - 227 ms. Täitmiseks ei kasutatud indeksit. Andmebaasisüsteem vaatas järjest läbi kõik tabeli Person read ja iga rea korral vaatas ridu tabelist Health_care_visit, kuni leidis vaste.Täitmiskiiruselt järgmine oli lahendus 4 - 267 ms. Täitmiseks ei kasutatud indeksit. Alampäringu täitmiseks loeti paralleelprotsesside poolt tabeli Health_care visit ridu ja kordused eemaldati sorteerimist kasutades. Saadud tabel ühendati tabeliga Person kasutades räsiväärtuste arvutamisel põhinevat algoritmi (hash join).Täitmiskiiruselt järgmine oli lahendus 3 - 588 ms. Täitmiseks ei kasutatud indeksit. Andmebaasisüsteem ühendas tabelid Person ja Health_care visit kasutades räsiväärtuste arvutamisel põhinevat algoritmi (hash join).Kõige aeglasem oli lahendus 2 - 688 ms. Täitmiseks kasutati indeksit. Andmebaasisüsteem vaatas järjest läbi kõik tabeli Person read ja iga rea korral loendas indeksi alusel kokku tabelis Health_care_visit olevate seotud ridade arvu.Mõned üldised järeldused: SQL ülesandele on tüüpiliselt mitu erinevat vastust. Erinevate lahenduste täitmiskiirused võivad olla erinevad. Andmebaasisüsteem otsustab ise, millal andmebaasis loodud indekseid päringute täitmiseks kasutada ja indeksi kasutamine ei pruugi alati olla kõige kiirem viis andmete ülesleidmiseks. ## Küsimus: Kuidas teistes andmebaasisüsteemides realiseerida PostgreSQLi FILTER predikaati, mida saab kasutada koos kokkuvõttefunktsiooniga? **Vastus:** PostgreSQLis saab kokkuvõttefunktsioonidega (nt Count, Min, Max, Sum, Avg) koos kasutada FILTER klauslit, et piirata ridu, mis lähevad kokkuvõttefunktsiooni tulemuse arvutamisel sisendiks. See võimaldab ühe ja sama lausega küsida samast tabelist koondtulemusi erinevatele tingimustele vastavate ridade põhjal.Oletame, et SQL-andmebaasis on tabel Hotell:Hotell(hotelli_nr, nimi, linn)Primaarvõti(hotelli_nr)Ülesandeks oleks leida sama lausega Tallinnas olevate hotellide arv ja Tartus olevate hotellide arv.PostgreSQLSELECT Count(*) FILTER (WHERE linn='Tallinn') AS tallinna_hotellide_arv,Count(*) FILTER (WHERE linn='Tartu') AS tartu_hotellide_arvFROM Hotell;Alternatiivsed lahendused põhinevad Count funktsiooni omadusel, et Count(<avaldis>) loendab vaid ridu, kus avaldise arvutamise tulemus ei ole NULL.MS Access SELECT Count(iif(linn='Tallinn',linn,NULL)) AS tallinna_hotellide_arv, Count(iif(linn='Tartu',linn,NULL)) AS tartu_hotellide_arv FROM Hotell;iif funktsioonil on kolm parameetrit - esimese oodatav väärtus on kontrollitav tingimus, teise oodatav väärtus on funktsiooni tulemus, kui tingimuse kontrolli tulemus on TRUE, kolmanda oodatav väärtus on funktsiooni tulemus, kui tingimuse kontrolli tulemus on FALSE. PostgreSQL (ilma FILTER kasutuseta) SELECT Count(CASE WHEN linn='Tallinn' THEN linn ELSE NULL END) AS tallinna_hotellide_arv, Count(CASE WHEN linn='Tartu' THEN linn ELSE NULL END) AS tartu_hotellide_arv FROM Hotell;Kasutatakse CASE avaldist. ## Küsimus: Kuidas tuleb erinevates andmebaasisüsteemides esitada tekstilisi väärtuseid? **Vastus:** SQL standard näeb ette, et väärtus peab olema ühekordsete ülakomade e apostroofide vahel ('tekst'). Jutumärkidesse võib panna andmebaasiobjektide nimesid e identifikaatoreid ("tekst").Kuidas käituvad erinevad andmebaasisüsteemid? Oracle Database 23ai Free - apostroofid ('tekst')Microsoft SQL Server 2022 - apostroofid või jutumärgid ('tekst', "tekst")MySQL 8 (vaikimisi) - apostroofid või jutumärgid ('tekst', "tekst")MySQL 8 (režiimis ansi) - apostroofid ('tekst')  PostgreSQL 16 - apostroofid ('tekst') SQL Lite 3.27.2 - apostroofid või jutumärgid ('tekst', "tekst")MariaDB 10.7.8 - apostroofid või jutumärgid ('tekst', "tekst")MS Access 2019 - apostroofid või jutumärgid ('tekst', "tekst")MySQLis saab sessiooni piires SQL lausete täitmisse režiimi muuta lausega: SET SESSION sql_mode = 'ansi'; ## Küsimus: Kuidas töötavad SQLis tingimused IN ja NOT IN? **Vastus:** Oletame, et meil on sellise kontseptuaalse struktuuriga andmebaas:[Hotell]-1------------0..*-[Reserveerimine]Ülesanne: Leia reserveerimised, mis on tehtud Tallinna linnas olevas hotellis. SELECT *FROM ReserveerimineWHERE hotelli_nr IN (SELECT hotelli_nrFROM HotellWHERE linn = 'Tallinn' ); Sulgudes oleva alampäringuga leitakse hotellide numbrid, mille korral on täidetud tingimus linn = 'Tallinn'. Tulemuseks on hulk (1,2,8). Iga rea korral tabelist Reserveerimine leitakse sellest reast hotelli number ja kontrollitakse, kas see number sisaldub alampäringuga leitud hulgas. Näiteks reserveerimisel hotellis 3 kontrollitakse: Kas on tõsi, et väärtus 3 sisaldub hulgas (1,2,8). Vastus - ei ole tõsi. Järelikult sellise hotelli numbriga reserveerimine ei ole tulemuses. Näiteks reserveerimisel hotellis 2 kontrollitakse:Kas on tõsi, et väärtus 2 sisaldub hulgas (1,2,8). Vastus - jah, on tõsi. Järelikult sellise hotelli numbriga reserveerimine on tulemuses.Ülesanne: Leia reserveerimised, mis ei ole tehtud Tallinna linnas olevas hotellis. SELECT *FROM ReserveerimineWHERE hotelli_nr NOT IN (SELECT hotelli_nrFROM HotellWHERE linn = 'Tallinn'); Sulgudes oleva alampäringuga leitakse hotellide numbrid, mille korral on täidetud tingimus linn = 'Tallinn' . Tulemuseks on hulk (1,2,8). Iga rea korral tabelist Reserveerimine leitakse sellest reast hotelli number ja kontrollitakse, kas see number ei sisaldu alampäringuga leitud hulgas. Näiteks reserveerimisel hotellis 3 kontrollitakse:Kas on tõsi, et väärtus 3 ei sisaldu hulgas (1,2,8). Vastus - jah, on tõsi. Järelikult sellise hotelli numbriga reserveerimine on tulemuses. Näiteks reserveerimisel hotellis 2 kontrollitakse: Kas on tõsi, et väärtus 2 ei sisaldu hulgas (1,2,8). Vastus - ei ole tõsi. Järelikult sellise hotelli numbriga reserveerimine ei ole tulemuses.Juhul, kui alampäring võib tagastada NULLi, siis tuleks kirjutada: SELECT *FROM ReserveerimineWHERE hotelli_nr NOT IN (SELECT hotelli_nrFROM HotellWHERE linn = 'Tallinn' AND hotelli_nr IS NOT NULL);Ilma selleta juhtuks nii, et kui alampäring tagastaks NULLi, siis poleks põhipäringu tulemuses ühtegi rida. Miks see nii juhtub? Vaatame järgmist näidet. Sulgudes oleva alampäringuga leitakse hotellide numbrid, mille korral on täidetud tingimus linn = 'Tallinn' . Tulemuseks on hulk (1,2,8, NULL). Iga rea korral tabelist Reserveerimine leitakse sellest reast hotelli number ja kontrollitakse kas see number ei sisaldu alampäringuga leitud hulgas. Näiteks reserveerimisel hotellis 3 kontrollitakse: Kas on tõsi, et väärtus 3 ei sisaldu hulgas (1,2,8, NULL). Vastus - ei tea. NULL on nagu suletud karp, mille sisse ei näe. Võibolla on seal karbis 3 võibolla mitte. Järelikult sellise hotelli numbriga reserveerimine ei ole tulemuses. Näiteks reserveerimisel hotellis 2 kontrollitakse: Kas on tõsi, et väärtus 2 ei ole hulgas (1,2,8, NULL). Vastus - ei ole tõsi. Järelikult sellise hotelli numbriga reserveerimine ei ole tulemuses. Antud juhul polnud seda tingimust (hotelli_nr IS NOT NULL) tingimata vaja kirja panna (ehki kirjapanek poleks ka viga), sest hotelli_nr tabelis Hotell on primaarvõti ja seega ka kohustuslik veerg. ## Küsimus: Lispunktide/kontrolltöö ülesandeks on teha koopia tabelist X (SELECT ... INTO lausega) ning seejärel koopias ridu muuta või ridu kustutada. Kas võin selle asemel kirjutada lause, mis loob koopia ridadega kus kajastub muudatuste järgne seis? **Vastus:** Sellise ülesande eesmärgiks on teha kindlaks, kas lisaks andmetest koopia tegemisele oskate koostada UPDATE või DELETE lauseid. Seega, SQL lisapunktide või kontrolltöö lahendamisel oleks see vale lahendus. Peaksite kirjutama vähemalt kaks eraldi lauset - üks koopia tegemiseks ja teine nõutud muudatuste tegemiseks. Lisapunktide ülesannete lahendamisel ühe lausega lahenduse eest punkte ei saa. Kontrolltöös saab selle eest osa punkte - seega kui kahe lausega ei oska, siis tehke ühe lausega. ## Küsimus: Mida tähendab, et kirjutage INSERT lause nii, et see poleks tundlik veergude järjekorra muutmise suhtes? **Vastus:** Halb: INSERT INTO Isik VALUES ('39107070123', 'Mets'); Kui tabelis Isik muutub veergude järjekord, siis tuleb seda lauset muuta. Vastasel juhul võib lisamine ebaõnnestuda, või mis veel hullem, lisamine õnnestub, kuid väärtused lähevad valedesse väljadesse. Lause ei kirjelda esitatud väärtuste tähendust. Palju parem: INSERT INTO Isik (isikukood, perenimi) VALUES ('39107070123', 'Mets'); Kui tabelis Isik muutub veergude järjekord, siis ei tule seda lauset muuta. Halb: INSERT INTO Magamine_koopia SELECT * FROM Magamine; Lisaks eelnimetatud probleemidele ei näe koodi lugeja, millised veerud ja millises järjekorras alampäringu poolt tagastatakse. Palju parem: INSERT INTO Magamine_koopia (ase_id, algus, magaja_id, kestus, kommentaar)SELECT ase_id, algus, magaja_id, kestus, kommentaar FROM Magamine; ## Küsimus: Mida tähendab ülesandes lause "tabelite ühendamisel realiseerige joini tingimused WHERE klausli abil"? **Vastus:** Teatavasti saab tabelite ühendamiseks kasutada nii vanemat süntaksi: SELECT Oppimine.*, Aine.nimetus AS aine_nimetus FROM Oppimine, Aine WHERE Oppimine.aine=Aine.aine_kood; kui "uuemat" süntaksi: SELECT Oppimine.*, Aine.nimetus AS aine_nimetus FROM Oppimine INNER JOIN Aine ON Oppimine.aine=Aine.aine_kood; "Uuem" on jutumärkides, sest SQL standard näeb seda ette juba 1992. aasta redaktsioonist/versioonist. Mõlemaid kirjaviise peaks oskama. Näiteks võivad SQL lausete generaatorid genereerida just vanema süntaksiga lauseid. Siis peaks sellest aru saama. Kui ülesandes on öeldud, et "tabelite ühendamisel realiseerige joini tingimused WHERE klausli abil", siis see tähendab, et juhul kui kasutate ühendamisoperatsiooni, siis tuleb kasutada vanemat süntaksi. Kui lahendate ülesande ilma ühendamisoperatsioonideta (nt kasutades alampäringuid), siis ignoreerige seda juhist. ## Küsimus: Miks mõnikord peab koos kokkuvõttefunktsiooni kasutamisega kasutama GROUP BY klauslit ja mõnikord ei pea? **Vastus:** Järgnevad koodinäited põhinevad enamasti MS Accessil, kuid kirjeldatud põhimõtted kehtivad SQLis üldiselt.Oletame, et ülesandeks on leida iga aasta kohta, millal on alanud mõni reserveerimine, sellel aastal alanud reserveerimiste arv. SELECT Year(alguse_aeg) AS aasta, Count(*) AS arv FROM Reserveerimine;   See lause on vale, sest puudub eeskiri (GROUP BY klauslis), kuidas moodustada ridade rühmad, milles olevad read tuleb kokku loendada. Kuna SELECT klauslis on veerg, millele kokkuvõttefunktsiooni ei rakendata (aasta), siis ei saa eeldada, et kõik tabeli read on selleks paigutatud ühte rühma. Teiste sõnadega, kui SELECT klauslis on kokkuvõttefunktsioonide väljakutseid + üks või mitu veergu, millele ei rakendu kokkuvõttefunktsioon, siis peavad kõik need veerud olema ka nimetatud GROUP BY klauslis.Õige oleks SELECT Year(alguse_aeg) AS aasta, Count(*) AS arv FROM Reserveerimine GROUP BY Year(alguse_aeg); PostgreSQLis saab GROUP BY klasuslis kasutada ka veerule SELECT klauslis määratud aliast. SELECT Extract(year from alguse_aeg) AS aasta, Count(*) AS arv  FROM Reserveerimine  GROUP BY aasta;  Kurioosumina võib välja tuua, et populaarset andmebaasisüsteemi MySQL saab panna tööle erinevates režiimides, sh sellises, mis lubab käivitada algselt välja toodud lauset. Vaikimisi seda lauset MySQL 8-s ei täideta. SET SESSION sql_mode = 'traditional';   SELECT Year(alguse_aeg) AS aasta, Count(*) AS arv FROM Reserveerimine;Lause täidetakse. Tulemuseks on tabel, kus on üks rida ja kaks veergu. Väljas aasta on üks (esimene?) aasta , väljas arv on kõikide reserveerimiste koguarv.   SET SESSION sql_mode = 'ansi';   SELECT Year(alguse_aeg) AS aasta, Count(*) AS arv FROM Reserveerimine; Lauset ei täideta.Järgnevas lauses aga pole GROUP BY klauslit vaja, sest KÕIKIDESSE tulemusse kuuluvatesse veergudesse leitakse andmed kokkuvõttefunktsiooniga. Kuna SELECT klauslis pole ühtegi kokkuvõttefunktsiooniga katmata veergu, siis saab eeldada, et ridade rühma, mille järgi koondväärtused leitakse, moodustavad kõik tabeli read. SELECT Round(Avg(lopu_aeg - alguse_aeg),2) AS avg_pikkus, Min(lopu_aeg - alguse_aeg) AS min_pikkus, Max(lopu_aeg - alguse_aeg) AS max_pikkus FROM Reserveerimine AS R, Hotell AS H WHERE R.hotelli_nr = H.hotelli_nr AND linn = 'Tallinn' AND lopu_aeg - alguse_aeg > 2   Eelnev näide on samaväärne selle lausega - rühmitamine e grupeerimine tühjal veergude hulgal e kõik tabeli read kuuluvad ühte rühma. Sellist süntaksi SQL standard lubab, aga MS Access ei toeta.   SELECT Round(Avg(lopu_aeg - alguse_aeg),2) AS avg_pikkus, Min(lopu_aeg - alguse_aeg) AS min_pikkus, Max(lopu_aeg - alguse_aeg) AS max_pikkus FROM Reserveerimine AS R, Hotell AS H WHERE R.hotelli_nr = H.hotelli_nr AND linn = 'Tallinn' AND lopu_aeg - alguse_aeg > 2 GROUP BY (); ## Küsimus: Miks õppida SQLi? **Vastus:** SQLis kui keeles võiks kahtlemata olla palju asju teistmoodi ja paremini (vt "Andmebaasid I" teema 6 materjale). Arendajad kiristavad mõnikord SQLi peale hambaid ja kiruvad, kuid ikkagi kasutavad seda. Miks nad seda teevad? 2024. aasta märtsi seisuga on kümne kõige populaarsema andmebaasisüsteemi hulgas seitsmes kasutusel SQL. IEEE Spectrumi 2024. aasta programmeerimiskeelte populaarsuse indeksis oli SQL populaarsuselt kuuendal kohal ja tööandja poolt oodatud keelte hulgas esikohal!IEEE Spectrumi 2023. aasta programmeerimiskeelte populaarsuse indeksis oli SQL populaarsuselt seitsmendal kohal ja tööandja poolt oodatud keelte hulgas esikohal! IEEE Spectrumi 2022. aasta programmeerimiskeelte populaarsuse indeksis oli SQL populaarsuselt kuuendal kohal ja tööandja poolt oodatud keelte hulgas esikohal! SQL on oma positsiooni selles pingereas tublisti parandanud, sest 2021. aasta uuringu kohaselt oli SQL populaarsuselt 15-s ja tööandja oodatult keelte hulgas 6-s. Tööandjad tahavad töötajatelt lisaks muude keelte oskustele kindlasti ka SQLi oskust, sest programmid töötavad andmetega ja väga-väga sageli on andmed SQL-andmebaasides. Seega puutub mistahes valdkonnas ja keeles programmeerija kindlasti kokku ka SQLiga. SQLi leiab kasutust suurandmetega töötamisel, andmeteaduses, masinõppes. SQL on pika ajalooga, küps keel, mille kasutamiseks mõeldud programmide hulk on tohutu ning mis on suutnud uute IT-trendidega alati väga hästi kohanduda. SIIN on artikkel, mis kirjutab SQL populaarsuse tõusust. Artikkel lõpeb tõdemusega: "Igal dekaadil tekib mõni uus ülehaibitud andmebaasi tehnoloogia, mille pooldajad väidavad, et SQL on kohutav, aeglane või ebapraktiline. Aja jooksul võidab terve mõistus ja saadakse aru, et SQL on hea idee ning kõik jätkavad selle kasutamist."Sellest tulenevalt on lisaks arendajatele SQL hädavajalik keel andmeteadlastele. Nad peavad kuidagi enda uurimismaterjalile e andmetele ligi pääsema ja sageli on selleks vaja kasutada SQLi. Näiteks üleeuroopalisel suurandmete töötlemise maratonil 2017. aastal kolmanda koha saanud meeskonna liige kommenteeris, et sisendandmed olid SQL-andmebaasis, hierarhiatena, Adjacency List (külgnevusnimistu) mudeli alusel. Ta ütles SQLi kasutamise kohta: "asi kisub vist hoopis sql hackathoniks. /.../ eeltöötlus ja andmebaasides ringirändamine ja avastamine on 80-90% ajast." Osalejatele anti vahendite valik vabaks. Eesti meeskond otsustas esmajoones kasutada PostgreSQLi (populaarne ja väga võimalusterohke avatud lähtekoodiga serveri andmebaasisüsteem, kus saab kasutada SQLi). See tähendab, et andmed laaditi PostgreSQLi tabelitesse ja otsiti vastuseid küsimustele kasutades SQL päringuid. Ainult siis, kui PostgreSQL jäi töökiiruse mõttes hätta ("5+ JOINiga päringutel kulus tulemusteni üle 15 minuti (võtmeveergude indekseerimised jm. "hügieenilised" tegevused olid eelnevalt tehtud)"), laaditi andmed päringu tegemiseks Hadoop klastrisse. Ka seal läks vaja SQLi oskust, sest läbi Hive pakutava liidese saab klastris olevate andmete poole pöörduda kasutades SQL-laadset keelt HiveQL. PostgreSQL päringuid polnud vaja palju muuta, kuid töökiiru paranes kuni kümme korda. Samas kommenteeris üks meeskonna liikmetest, et "Kui Hackathlonil poleks ajapiirangut olnud, siis selle andmestiku puhul oleks saanud ka ilma Hiveta." Samuti kasutati hajusarvutuste platvormi Spark, kuid ka selle kasutamiseks on kasulik SQLi tunda. Arvatavasti olete kuulnud NoSQL (kes interpreteerib seda kui "No to SQL", kes aga "Not only SQL") süsteemidest. Need süsteemid sõitsid 2010ndatel suure hurraaga turule, kui järjekordsed printsid valgel hobusel, mis pidid andmebaaside maailma kõigist hädadest päästma. Eriti alguses vastandusid need (nagu nimigi viitab) täielikult SQLile. Nüüdseks aga on üha rohkemates sellistes süsteemides kasutusele võetud kõrgtaseme (deklaratiivne) päringukeel, mis kangesti meenutab SQLi. Irvhambad on hakanud NoSQLi kutsuma tänu sellele kui "Not yet SQL". Nii et kui "päris" SQLi oskate, siis pole keeruline ka neid uusi keeli suhu saada. Näited: CQL (Cassandra Query Language, andmebaasikeel veergude perekondade põhises andmebaasisüsteemis Cassandra). N1QL (päringukeel dokumendipõhises andmebaasisüsteemis Couchbase). SPARQL (standardiseeritud päringukeel andmebaasisüsteemidele, mis põhinevad RDF (Resource Description Framework, ressursside kirjeldamise karkass) andmemudelil). PGQL (katse pakkuda graafipõhistele süsteemidele välja ühtlustatud SQLi-laadset päringukeelt). Rahvusvaheline standardimisorganisatsioon ISO (International Organization for Standardization) alustas graafipõhise andmebaasikeele standardi väljatöötamisega. Uus keel hakkab põhinema SQLil ja selle edul ning andmete otsimise lause peaks meenutama SQL SELECT lauset. Cypher (päringukeel graafipõhises andmebaasisüsteemis Neo4J). Carnegie Melloni ülikooli andmebaaside professor Andy Pavlo ütles 2021. aastal, et SQLi puudus hoiab Redise (ühe tuntud NoSQL süsteemi) kasutajaid tagasi, sest iga suurem ja kasutatavam NoSQL süsteem, v.a MongoDB ja FaunaDB, toetab mingit SQLi varianti. "SQL oli maailmas enne teie sündi ja on siin ka siis, kui te surete". (artikkel) (video) ## Küsimus: Millal kasutada SQLis tabelite ühendamist ja millal alampäringut? **Vastus:** SQL on keeleliselt liiane, mis tähendab, et aastate jooksul on SQL keelt täiendatud aina uute keelekonstruktsioonidega ja ühte ning sama ülesannet saab seetõttu lahendada paljudel erinevatel viisidel. Mingis mõttes on see nagu inimkeeles, kus on ka palju sünonüüme ning ühte ja sama mõtet saab avaldada erinevatel viisidel. Mõni väljendusviis võib olla sobivam ühes kontekstis ja mõni teises.Oletame, et meil on sellise kontseptuaalse struktuuriga andmebaas:[Hotell]-1------------0..*-[Reserveerimine]Ülesanne: Leia reserveerimised, mis on tehtud Tallinna hotellides.Lahendus 1: SELECT *FROM ReserveerimineWHERE hotelli_nr IN (SELECT hotelli_nrFROM HotellWHERE linn='Tallinn');Lahendus 2;SELECT Reserveerimine.*FROM Reserveerimine INNER JOIN Hotell ON Reserveerimine.hotelli_nr=Hotell.hotelli_nrWHERE Hotell.linn='Tallinn';Millal kindlasti kasutada lahendust 2? Päringu tulemuses on vaja väljastada andmeid tabelist Hotell. Väljastatavad andmed määratakse ära lause SELECT klauslis. Päringu tulemuses on vaja väljastada andmeid mõnest muust tabelist kui Hotell, kuid selle tabelini jõudmiseks tuleb see ühendada tabeliga Hotell. Päringu tulemust on vaja sorteerida andmete järgi, mis on tabelis Hotell või mõnes sellises tabelis milleni pääseb tabelit Hotell ühendades. Sorteerimiseeskiri oleks lause ORDER BY klauslis. Päringu tulemusse on vaja arvutada koondandmeid andmete põhjal, mis on tabelis Hotell või mõnes sellises tabelis milleni pääseb tabelit Hotell ühendades. Koondandmete arvutamiseks vajaliku grupeerimise eeskiri oleks lause GROUP BY klauslis. Ülesanne: Kustuta selliste reserveerimiste kommentaarid, mis on tehtud Tallinna hotellidesLahendus 1:UPDATEReserveerimine SET kommentaar=NULLWHERE hotelli_nr IN (SELECT hotelli_nrFROM HotellWHERE linn='Tallinn');Miks mitte kasutada ühendamist?Tõepoolest, see oleks võimalik, kuid erinevate andmebaasisüsteemide SQL dialektides e mägimurrakutes oleks see lause erinev. Seega kood on vähem porditav e erinevate süsteemide vahel ülekantav.Lahendus 2 MS Accessis: UPDATE Reserveerimine INNER JOIN Hotell ON Reserveerimine.hotelli_nr = Hotell.hotelli_nr SET Reserveerimine.kommentaar = Null WHERE Hotell.linn='Tallinn'; Lahendus 2 PostgreSQLis UPDATE Reserveerimine SET kommentaar=NULL FROM Hotell WHERE Reserveerimine.hotelli_nr=Hotell.hotelli_nr AND Hotell.linn='Tallinn';NB! Veel üks võimalik lahendus (nii PostgreSQLis kui MS Accessis): UPDATE Reserveerimine AS R SET kommentaar = NULL WHERE EXISTS (SELECT * FROM Hotell, Reserveerimine AS R2 WHERE Hotell.hotelli_nr=R2.hotelli_nr AND linn='Tallinn' AND R.hotelli_nr=R2.hotelli_nr AND R.ruumi_nr=R2.ruumi_nr AND R.kylalise_nr=R2.kylalise_nr AND R.alguse_aeg=R2.alguse_aeg );UPDATE  lause WHERE klauslis on tingimus (EXISTS (korreleeruv alampäring)), mille täidetust saab kontrollida. Alampäringu viimased neli tingimust seovad alampäringu ja põhilause ning arvestavad sellega, et reserveerimise unikaalne identifikaator on hotelli_nr, ruumi_nr, külalise_nr ja alguse_aeg kombinatsioon. Kuna nii põhilauses kui alampäringus viidatakse samale tabelile (Reserveerimine), siis selleks, et käsitleda neid lause kontekstis justkui kahte erinevat tabelit kasutatakse aliasi (R ja R2). Ülesanne: Kustuta reserveerimised, mis on tehtud Tallinna hotellidesLahendus 1:DELETE FROM ReserveerimineWHERE hotelli_nr IN (SELECT hotelli_nrFROM HotellWHERE linn='Tallinn');Miks mitte kasutada ühendamist?Tõepoolest, see oleks võimalik, kuid erinevate andmebaasisüsteemide SQL dialektides e mägimurrakutes oleks see lause erinev. Seega kood on vähem porditav e erinevate süsteemide vahel ülekantav.Lahendus 2 MS Accessis: DELETE Reserveerimine.* FROM Reserveerimine INNER JOIN Hotell ON Reserveerimine.hotelli_nr = Hotell.hotelli_nr WHERE Hotell.linn='Tallinn'; Lahendus 2 PostgreSQLis DELETE FROM Reserveerimine USING Hotell WHERE Reserveerimine.hotelli_nr=Hotell.hotelli_nr AND Hotell.linn='Tallinn';   NB! Veel üks võimalik lahendus (nii PostgreSQLis kui MS Accessis): DELETE FROM Reserveerimine AS R WHERE EXISTS (SELECT * FROM Hotell, Reserveerimine AS R2 WHERE Hotell.hotelli_nr=R2.hotelli_nr AND linn='Tallinn' AND R.hotelli_nr=R2.hotelli_nr AND R.ruumi_nr=R2.ruumi_nr AND R.kylalise_nr=R2.kylalise_nr AND R.alguse_aeg=R2.alguse_aeg );DELETE lause WHERE klauslis on tingimus (EXISTS (korreleeruv alampäring)), mille täidetust saab kontrollida. Alampäringu viimased neli tingimust seovad alampäringu ja põhilause ning arvestavad sellega, et reserveerimise unikaalne identifikaator on hotelli_nr, ruumi_nr, külalise_nr ja alguse_aeg kombinatsioon. Kuna nii põhilauses kui alampäringus viidatakse samale tabelile (Reserveerimine), siis selleks, et käsitleda neid lause kontekstis justkui kahte erinevat tabelit kasutatakse aliasi (R ja R2). ## Küsimus: Milline on tüüpiline viga LIMIT klausli kasutamisel? **Vastus:** LIMIT klauslit ei saa kasutada MS Accessis, kuid saab kasutada mitmes teises SQL andmebaasisüsteemis. LIMIT n võimaldab päringu tulemusest väljastada esimesed n rida. SQL standard ei näe samuti ette LIMIT klauslit. Samas saab SQL standardi kohaselt kasutada FETCH FIRST n ROWS ONLY klauslit, mis teeb sama välja kui LIMIT.Üks ülesannete klass, kus LIMIT'it ebaõigelt kasutatakse, on kõigi nende ühte tüüpi olemite leidmine, millel mingi tunnuse väärtus on kõige suurem või kõige väiksem. Leia ametid, millel on kõige suurem min_palk väärtus.   Vale. Sorteerin read minimaalse palga jälgi kahanevalt ja siis valin ridade hulgast kõige esimese.   SELECT amet_kood, min_palk FROM Amet ORDER BY min_palk DESC LIMIT 1; SELECT *FROM AmetORDER BY palk DESCFETCH FIRST 1 ROWS ONLY; Õige. Leian ametid, mille minimaalne palk on kõigi minimaalsete palkade hulgast kõige suurem.   SELECT amet_kood, min_palk FROM Amet WHERE min_palk=(SELECT Max(min_palk) AS m FROM Amet); Esimene lahendus on vale, sest võib olla mitu ametit, millel on ühtemoodi kõige suurem palk. Esimene lahendus leiab ainult ühe sellise ameti (millise, on ennustamatu). Teine leiab kõik sellised ametid.MS Accessis oleks õige lahendus ka selline. TOP predikaat leiab minimaalse palga järgi kahanevalt sorteeritud ametite hulgast kõige esimese (e kõige suurema) minimaalse palgaga ametid. SELECT TOP 1 amet_kood, min_palk FROM Amet ORDER BY min_palk DESC;MS SQL Serveris tuleks sama tulemuse saavutamiseks kasutada TOP ... WITH TIES. SELECT TOP 1 WITH TIES amet_kood, min_palk FROM Amet ORDER BY min_palk DESC;Samuti annab õige tulemuse see päring, mis töötab näiteks PostgreSQLis. WITH TIES tagab, et vajadusel on päringu tulemuses rohkem kui üks rida.SELECT *FROM AmetORDER BY palk DESCFETCH FIRST 1 ROWS WITH TIES;Oluline on üle rõhutada, et TOP ja FETCH FIRST 1 ROWS WITH TIES lahendused eeldavad ridade sorteerimist - muidu on tulemus juhuslik rida. ## Küsimus: Milline võiks olla üldine SQL SELECT lausete koostamise strateegia? **Vastus:** Olen kunagi midagi kirjutanud SQL SELECT lausete koostamise üldise strateegia/metoodika kohta. See põhineb paljuski matemaatik Georg Pólya üldist probleemilahenduse strateegiat kirjeldaval raamatul Kuidas seda lahendada. Huvilised leiavad kirjutise lisamaterjalide lehelt (kasutajanimi: SIS2 parool: SIS2) SIIT. ## Küsimus: Milliseid materjale soovitate SQLi õppimisega alles alustanule, kes peab lähiajal töö- või praktikakoha saamise intervjuul vastama SQLi puudutavatele küsimustele? **Vastus:** 46 tööintervjuu küsimust SQLi kohta andmeteadlasele. Sealt leiate ka viite tegelikele küsimustele ja õigetele vastustele. https://www.datasciencecentral.com/46-questions-on-sql-to-test-a-data-science-professional-skilltest/   SQLi tööintervjuu küsimusi, millest osad on ka avalikud: https://www.testdome.com/tests/sql-online-test/12   Võibolla tasub sirvida eelmise aasta "Andmebaasid I" slaide SQLi kohta (kasutajanimi: SIS2 ja parool: SIS2). Kui kõiki ei jõua, siis vaadake slaide: tüüpiliste vigade kohta SQL lausetes, ebaotstarbekate SQL lausete kohta. Teadusartikkel tüüpiliste vigade kohta SQL lausetes: Brass, S., Goldberg, C., 2006. Semantic errors in SQL queries: A quite complete list. Journal of Systems and Software, 79(5), 630-644. [WWW] http://dbs.informatik.uni-halle.de/sqllint/jss06.pdf Äkki on abi ka järgnevast. Üldine strateegia andmete otsimise ülesannete lahendamiseks. Kui olete SQLiga rohkem tuttav, siis "trikke" selle kohta, kuidas otsida andmeid, mida andmebaasis ei ole. Muide, IEEE Spectrum 2022. aasta programmeerimiskeelte populaarsuse pingereas oli SQL 6. kohal, 2023. aastal populaarsuse pingereas oli SQL 7. kohal ning 2024. aasta populaarsuse pingereas oli SQL jälle 6. kohal. Kõigil nendel aastatel oli see keel tööandjate ootuse osas esikohal. Tööandjate ootus on, et lisaks muudele keeltele osataks kindlasti ka SQLi. ## Küsimus: Milliseid soovitusi annavad teadusuuringut selles osas, kuidas suurte keelemudelite abil SQL koodi genereerida? **Vastus:** Chang ja Lussier (2023) katsetavad erinevaid võimalusi ja annavad soovitusi suurte keelemudelite promptimiseks e viipade koostamiseks, et saada nendelt SQL koodi. Keelemudelile võiks SQL koodi genereerimiseks anda ette: Näiteülesanded sõnalise küsimuse ning lahenduseks oleva SQL koodi paaridena. Päringuid, kus näiteülesandeid ette ei anta nimetatakse zero-shot text-to-SQL. Päringuid, kus antakse ette mõned näiteülesanded nimetatakse few-shot text-to-SQL. Andmebaasi struktuuri kirjeldus kas tabelite loomise lausetena (CREATE TABLE) või struktuuri kirjeldusena kus on esitatud tabeli nimi, veergude nimed, võtmed ja seosed. Iga tabeli kohta kolm rida näiteandmetena, mille võib esitada näiteks komadega eraldatud nimekirjana, mille ees on nende andmete leidmiseks kasutatud päring (kujul: SELECT * FROM Tabel LIMIT 3) või siis esitada näiteandmed INSERT lausetena. Chang ja Lussier (2023) soovitavad esitada iga veeru kohta kolm erinevat näiteväärtust ja selle ees päringu nende andmete leidmiseks (kujul: SELECT DISTINCT veerg FROM Tabel LIMIT 3). Inimkeelne küsimus. Uuring näitas, et vastuse täpsuse jaoks oleks abi järgnevast. Etteantud teksti normaliseerimine (v.a andmeväärtuste näited). Normaliseerimine tähendab antud teksti esitamist väiketähtedena ja SQL lausetes treppimisest loobumist. See vähendab keelemudelile sisendiks mineva teksti hulka (võib olla piirang prompti pikkusele). Andmebaasi kirjelduses tabelite võtmete (PRIMARY KEY ja UNIQUE kitsendused) ja tabelite vaheliste seoste esitamisest (FOREIGN KEY kitsendused). Mõõdukast hulgast (nt kuni 15) näiteülesannete ja vastuste (SQL lausete) paaridest. Siin võib piirangu seada keelemudelist sõltuv küsimuse lubatud maksimumpikkus. Näiteandmete esitamisest kujul päring + tulemuseks olevad read. Rohkem pole alati parem – Rajkumar et al. (2022) toob välja, et kolm rida näiteandmeid oleks optimaalne – ridade arvu suurenemisel hakkab täpsus vähenema. Näiteülesanded võiksid olla sama andmebaasi põhjal, mille põhjal soovitakse enda ülesande lahendust. Andes näitena ette erinevaid andmebaase ning nendel põhinevaid näiteülesandeid hakkas mingist hetkest vastuste täpsus vähenema. Võimalik, et põhjuseks oli prompti liigne pikkus, sest uuritud mudelite korral saadi parimad tulemused umbes 5500 märgi pikkuse promptiga. Chang ja Lussier (2023) väidavad ChatGPT ja Codex näitel, et täpsus hakkab vähenema kui keelemudelile antud sisendi pikkus ületab 70% maksimaalselt lubatust. Rajkumar et al. (2022) järeldasid juba 2022. aastal, et suured keelemudelid (katsetati prorgammeerijatele mõeldud keelemudeli Codex põhjal) on inimkeelest SQLi genereerimisel tugevad tegijad. Loomulikult on oluline küsimuse (prompti) sõnastamine. Prompti kaudu näidete esitamine on tulemuste täpsuselt võrreldav väiksemate keelemudelite peenhäälestamise järel saadud tulemustega. Kui esitada ainult küsimus (ilma täiendava infota) on täpsus 8.3%. Kui lisaks esitati skeemi kirjeldus tõusis täpsus 59.9%. Kui tulemuses esitati tabelite kohta ka SELECT lause + kolm rida näiteandmeid kasvas tulemuse täpsus 67%-ni.Veel soovitusi: Kasutage prompti e viiba alguses sõna "Please" (Palun). Keelemudel ennustab, mis tekst peaks sisestatud tekstile jälgima. Viisakale tekstile peaks järgnema viisakam järg ning see on tavaliselt täpsem. Öelge küsimuses, kelle rollis Te küsimust esitate (nt andmebaasi programmeerija). Ingliskeelne küsimus võib anda veidi täpsema vastuse, kuid üldiselt saavad keelemudelid ka eesti keelega hästi hakkama. Sisemiselt toimub neil ikkagi tõlkimine inglise keelde. Vastuse esitamisel failina (nt testandmete genereerimisel) võib tehisintellekt teha vea andmete faili tõstmisel. Lahenduseks võib olla paluda esitada vastus kopeeritaval kujul, st mitte failina. Testandmete genereerimiseks võib paluda tehisintellektil genereerida kood, mis neid andmeid genereerib (sobivas programmeerimiskeeles, mis tuleb viibas ette öelda), selle asemel, et paluda andmeid genereerida ja väljastada. **Märksõnad:** LLM, suur keelemudel, AI, TI, tehisintellekt, prompt, viip ## Küsimus: Millistes SQL-andmebaasisüsteemides saab kasutada SELECT lauset, kus puudub FROM klausel ning millistes ei saa? **Vastus:** Kasutasin katsetamiseks keskkondi DB Fiddle, SQL Fiddle ja db<>fiddle.Katsetan lauset:SELECT 'Tere maailm' AS vastus;Andmebaasisüsteemid jagunesid kaheks: SELECT lauses peab olema FROM klausel. Andmebaasisüsteemi juures on ka viide kasutatud lausele. IBM DB2 Developer-C 11.1 SELECT 'Tere maailm' AS vastus FROM SYSIBM.SYSDUMMY1; Saab ka võimaldada Dual tabeli kasutamist Firebird 4 SELECT 'Tere maailm' AS vastus FROM RDB$DATABASE; HSQLDB 1.8 (LibreOffice Base) Tabel tuleb ise luua SELECT lauses ei pea olema FROM klauslit. PostgreSQL 17 MySQL 9 SQLite 3.46 MariaDB 10.7 MS SQL Server 2022 Oracle 23ai Enne Oracle 23ai tuli kirjutada: SELECT 'Tere maailm' AS vastus FROM Dual; MS Access 2019 ## Küsimus: Millistes SQL-andmebaasisüsteemides saab kasutada SQL standardis ettenähtud skeemi INFORMATION_SCHEMA, milles on süsteemikataloogi tabelite põhjal loodud vaated ja millistes ei saa? **Vastus:** INFORMATION_SCHEMA on SQL standardis kirjeldatud skeem, mis sisaldab süsteemikataloogi tabelite põhjal loodud vaateid. Süsteemikataloogi tabelites on andmed andmebaasi kohta. Mõte on selles, et erinevate andmebaasisüsteemide andmebaasides on süsteemikataloogi tabelite struktuur erinev, kuid kasutada võiks saada ühesuguse struktuuriga vaateid, mis on nende tabelite põhjal loodud. Süsteemikataloogi tabelite ja vaadete põhjal saab täita SELECT lauseid nagu ka kõigi ülejäänud andmebaasi tabelite ja vaadete põhjal. Kasutasin katsetamiseks keskkondi DB Fiddle, SQL Fiddle ja db<>fiddle.Katsetan lauset:SELECT Count(*) AS arv FROM INFORMATION_SCHEMA.tables;Andmebaasisüsteemid jagunesid kaheks: INFORMATION_SCHEMA ei ole toetatud. Oracle 23ai IBM DB2 Developer-C 11.1 SQLite 3.46 Firebird 4 MS Access 2019 HSQLDB 1.8 (LibreOffice Base) INFORMATION_SCHEMA on toetatud. PostgreSQL 17 MySQL 9 MariaDB 10.7 MS SQL Server 2022 ## Küsimus: Mis vahe on MS Accessi SQL mägimurrakus DISTINCT ja DISTINCTROW määrangutel? **Vastus:** SQL standard kirjeldab DISTINCT, kuid mitte DISTINCTROW (st viimane on andmebaasisüsteemi-spetsiifiline leiutis). Leidke külaliste perenimed nii, et kordused on eemaldatud. Esitage perenimed suurtähtedega. Sorteerige päringu tulemuses perenimed tähestikulisele järjekorrale vastupidises järjekorras. Õige: SELECT DISTINCT Ucase(perenimi) AS perenimi FROM Külaline ORDER BY Ucase(perenimi) DESC; SELECT Ucase(perenimi) AS perenimi FROM Külaline GROUP BY perenimi ORDER BY Ucase(perenimi) DESC; Õpetlik on, et ORDER BY klauslisse tuleb kirjutada ORDER BY Ucase(perenimi) DESC, mitte ORDER BY perenimi DESC; Kuigi MS Access lubaks ORDER BY lauses kirjutada ka ORDER BY perenimi DESC, siis PostgreSQL ja Oracle tahavad ka seal funktsiooni poole pöördumist (NB! PostgreSQL ja Oracle andmebaasisüsteemides on see funktsioon nimega Upper, mitte Ucase). Pealegi on see ülesande mõttes loogilisem – sorteerida tuleks nende andmete alusel, mis kasutajale esitatakse. Kui ma ei taha ORDER BY klauslisse funktsiooni poole pöördumist kirjutada, siis võin vormistada lahenduse mitmeosaliselt, kus kõigepealt leitakse suurtähtedega erinevad perenimed ja siis sorteeritakse tulemust. SELECT perenimi FROM (SELECT DISTINCT Ucase(perenimi) AS perenimi FROM Külaline) AS erinevad_perenimed ORDER BY perenimi DESC; Vale: SELECT DISTINCTROW Ucase(perenimi) AS perenimi FROM Külaline ORDER BY perenimi DESC; DISTINCTROW ignoreeritakse, kui andmeid küsitakse vaid ühest tabelist või on vaja väljastada andmed kõikidest FROM klauslis nimetatud tabelite veergudest. Viide. Veel üks näide. Leidke vähemalt ühe reserveerimise teinud külaliste erinevad perenimed. Päringu tulemuses on iga perenimi üks kord. SELECT DISTINCT perenimi FROM Külaline INNER JOIN Reserveerimine ON Külaline.külalise_nr = Reserveerimine.külalise_nr; Leidke vähemalt ühe reserveerimise teinud külalised. Väljastage igaühe kohta tema perenimi. Kui leidub rohkem kui üks sama perenimega külaline, kes on teinud vähemalt ühe reserveerimise, siis on see perenimi päringu tulemuses mitmekordselt. SELECT DISTINCTROW perenimi FROM Külaline INNER JOIN Reserveerimine ON Külaline.külalise_nr = Reserveerimine.külalise_nr; DISTINCTROW vaatleb korduste eemaldamiseks tervet tabeli rida, mitte ainult päringu tulemuses väljastatavaid andmeid. DISTINCTROW pole SQL standardis ja on MS Accessi-spetsiifiline kontsruktsioon (seda ei toeta isegi MS Accessi vanem vend – MS SQL Server). Alternatiiv selle kasutamisele: SELECT perenimi FROM Külaline WHERE EXISTS (SELECT * FROM Reserveerimine WHERE Külaline.külalise_nr = Reserveerimine.külalise_nr); ## Küsimus: Mis vahe on tabelite ühendamisel (join) ja ühendi leidmisel (union)? **Vastus:** Ühendamine (join) on selleks, et saada tabelist loetud ritta juurde uusi andmeid (enamasti mõnest teisest tabelist, ehki ka tabeli ühendamine iseendaga - self-join - on võimalik). Näiteks oletame, et andmebaasis on järgmise struktuuriga tabelid.[Tudeng]-1----------0..*-[Oppimine]Iga õppimine on seotud täpselt ühe tudengiga. Loen ridu tabelist Oppimine ja tahan, et igas saadud reas oleks ka selle õppimisega seotud tudengi perenimi. Selleks pean ühendada õppimise tabeli read tudengi tabeli ridadega. Pean seda tegema nii, et iga õppimise tabeli rida ühendatakse just ja ainult selle tudengi tabeli reaga, kus vastav tudeng on seotud vastava õppimisega.Vanem süntaks:SELECT Oppimine.*, Tudeng.perenimi AS tudengi_perenimiFROM Oppimine, TudengWHERE Oppimine.tudeng=Tudeng.tudkood;Uuem süntaks:SELECT Oppimine.*, Tudeng.perenimi AS tudengi_perenimiFROM Oppimine INNER JOIN Tudeng ON Oppimine.tudeng=Tudeng.tudkood;Ühendi (union) leidmine on selleks, et leida hulkade ühend. SELECT eesnimi, perenimiFROM TudengUNION SELECT eesnimi, perenimiFROM Oppejoud;Eelnev päring moodustab tabeli, kus on nii õppejõudude kui tudengite ees- ja perenimed. Vaikimisi eemaldatakse kordused.UNION operatsioonis osaleb kaks hulka (antud juhul ridade hulka). Nende hulga elementidel peab olema ühesugune struktuur.SELECT eesnimi, perenimiFROM Tudengleiab read, kus on kaks tekstitüüpi välja.SELECT eesnimi, perenimiFROM Oppejoud;leiab read, kus on kaks tekstitüüpi välja.Seega kahes ridade hulgas, mida UNION'iga kokku panen, peavad olema samasuguse struktuuriga read.Hästi piltlikult rääkides. Ühendamine (join) on nagu rongile vagunite lisamine, kusjuures rongile tuleb lisada õiged vagunid, mis peavad jõudma rongi sihtkohta. Ühendi (union) leidmine on nagu ühesuguse kujuga kastide üksteise otsa virna laadimine. ## Küsimus: Ühes õppematerjalis on öeldud "Objekt-relatsiooniliste andmebaasisüsteemide loomine tuleneb lõppkokkuvõttes sellest, et tänapäeva SQL-andmebaasisüsteemid ei realiseeri täies ulatuses relatsioonilist mudelit ja see tekitab probleeme." Millist osa relatsioonilisest mudelist SQL andmebaasisüsteemid ei realiseeri? Miks nõnda? **Vastus:** Põhinemine hulkade asemel multihulkadel (korduvad read ja veerud on lubatud),tühjade võtmete ja ilma veergudeta tabelite mitte lubamine (kuigi ka tühi hulk on hulk),NULLide kasutamine puuduvate andmete esitamiseks, liigsete piirangutega ja samas liiga keeruline uute tüüpide loomise võimalus, SQL-andmebaasisüsteemides praktikas esinevad piirangud deklaratiivsete kitsenduste loomisele (nt ei saa luua üldiseid kitsendusi e ASSERTIONeid),üleüldine järjekindlusetus asjade tegemises või lubamises,need on vaid mõned asjad, mis muudavad SQLi kasutamise keerukamaks kui peaks.Nii mõnedki erinevused SQLi ja relatsioonilise mudeli lähenemiste vahel on toodud välja teema nr 2 (relatsiooniline andmemudel) slaididel (märkused punastes kastides). Põhjalikumalt on teemat eesti keeles lahatud SELLES ettekandes ja SELLE materjali peatükis 6.Kes ei taha pelgalt piirduda vahendatud infoga, see võib uurida Kolmanda Manifesti kohta ilmunud värskeimat raamatut, kus relatsioonilise mudeli ideid väga põhjalikult ja paljude näidetega selgitatakse.SIIN on aga andmebaasisüsteem (Rel), mis realiseerib relatsioonilist mudelit nii nagu sellest aine teemas nr 2 juttu oli. --- # Teema: Vahendid - CASE ## Küsimus: Kas iseseisva töö projektis võib kasutada mõnda muud CASE vahendit kui Enterprise Architect (EA) või Rational Rose (RR)? **Vastus:** Keelatud see ei ole. Kuid palun arvestage järgnevaga. Sõltumata kasutatavast vahendist tuleb lõplikus töös esitada kõik nõutud visuaalsed skeemid e diagrammid: tegevusdiagramm e tegevusskeem, kasutusjuhtude diagramm e kasutusmalliskeem, olemi-suhte diagrammid e olemi-suhte skeemid (tükeldatult nii, et iga registri kohta on eraldi diagramm e skeem), seisundidiagramm e olekumasina mudel, andmebaasi füüsilist disaini esitavad diagrammid e skeemid (tükeldatult nii, et iga registri kohta on eraldi diagramm e skeem). Kui Te ei kasuta EA või RR, siis Te ei saa kasutada töövihiku projekti puhul eelnevalt valmistehtud diagramme ja peate need nullist käsitsi joonistama. Kui Te ei kasuta mõnda andmete modelleerimisele spetsialiseerunud CASE vahendit (näiteks kasutate ArgoUMLi või Cacood), siis Te ei saa kasutada kontseptuaalsest andmemudelist andmebaasi disaini mudeli genereerimise võimalust ja peate andmebaasi disaini mudeli looma nullist käsitsi. Kui Te ei kasuta mõnda andmete modelleerimisele spetsialiseerunud CASE vahendit (näiteks kasutate ArgoUMLi või Cacood), siis Te ei saa kasutada andmebaasi disaini mudelist SQL koodi genereerimise võimalust ja peate SQL koodi tabelite loomiseks kirjutama nullist käsitsi. ## Küsimus: Kas iseseisva töö projekti tegemiseks piisab mõnest andmete modelleerimiseks mõeldud modelleerimisvahendist (nt Vertabelo Data Modeler)? **Vastus:** Lisaks andmebaasi disaini mudelile (mida saab näiteks Vertabelo Data Modeler abil teha) on projektis vaja ka luua: tegevusdiagramm e tegevusskeem (activity diagramm), kasutusjuhtude diagramm e kasutusmalli skeem (use case diagram), paketidiagramm e paketiskeem (package diagram), seisundidiagramm e olekumasinaskeem (state-transition diagram), olemi suhte diagrammid (seal pole välisvõtmeid ega andmebaasisüsteemi spetsiifilisi andmetüüpe) UML klassidiagrammidena e klassiskeemidena (class diagram). Kui vahend nende loomist ei toeta, siis sellest vahendist üksi ei piisa. Kui projekti töövihiku järgi tegemisel Enterprise Architecti või Rational Rose'i mitte kasutada, siis tuleb kõik diagrammid e skeemid luua nullist ja see kulutab rohkem aega võrreldes nendega, kes täiendavad etteantud diagrammi põhju. **Märksõnad:** CASE, modelleerimisvahend, Enterprise Architect, EA, Rational Rose, RR, modelleerimisvahend, UML ## Küsimus: Kuidas käivitada Enterprise Architecti mudeliteisenduste täiendust arvutiklassides või virtuaalsel töölaual? **Vastus:** Kuna laienduse autor ei teadnud installeerimise programmi loomisel kõiki tsentraalse installeerimise eripärasid, siis on selle laienduse korrektseks tööle hakkamiseks vaja arvutiklassi arvutis üks kord käivitada reg.reg fail. Seda saavad üliõpilased oma konto alt ise teha. Pärast seda, peale EA taaskäivitamist, hakkab laiendus tööle. Kui arvutis on see fail korra käivitatud, siis rohkem pole seda vaja enam teha. Isiklikule arvutile installeerides seda pole vaja teha - peaks koheselt töötama, kui olete juhendis olevat installeerimise protseduuri järginud.Mingil põhjusel funktsioneerib see mudeliteisendus vaid osades arvutiklassi arvutites. Seega, kui see ühes ei tööta proovige teist.Virtuaalsel töölaual tuleb reg.reg fail käivitada iga kord peale sisselogimist. **Märksõnad:** virtuaalne töölaud ## Küsimus: Kuidas ma saan Enterprise Architect 12 vahendis MS Accessi andmebaasi kirjeldavas füüsilise disaini mudelis kasutada veeru tüübina Decimal? **Vastus:** Kui andmetüüpi ei ole disaini mudelis veeru andmetüüpide valikus, siis saab teha järgnevat. Valige menüüst Project => Settings => Database Datatypes Avanenud aknas valige liitboksist Product Name: "MS Access" Lisage uus andmetüüp järgnevate andmetega (vaadake ka vastusele lisatud faili) Datatype: Decimal Common type: decimal Precision & scale: Default: 28, 13; Max: 28 Maksimaalne väärtus 28 näitab seda, et maksimaalne numbrikohtade arv MS Accessi Decimal tüüpi väärtuses on 28 Precision e täpsus - maksimaalne numbrikohtade arv Scale e skaala - kohtade arv peale koma Vajutage nupule Save. Kui Te nüüd kirjeldate MS Accessi andmebaasi tabeleid ja valite andmetüübiks Decimal, siis vaikimisi pakutakse täpsuseks ja skaalaks 28 ja 13, kuid seda valikut saab tabeli veergude kirjelduse juures muuta (vaadake ka vastusele lisatud faili). ## Küsimus: Kuidas on võimalik Rational Rose'ist eksportida mõni diagramm bmp/jpg/gif/png kujul? **Vastus:** Diagrammi dokumenti kopeerimiseks pole seda vaja teha. Piisab, kui teete diagrammi aktiivseks, valite klaviatuurilt Ctrl+A (vali kõik diagrammi elemendid), Ctrl+C (kopeeri) ning dokumendis valite Ctrl+V (kleebi). Kui see mingil põhjusel ei sobi, siis näiteks Windowsi puhul võib kasutada spetsiaalset operatsioonisüsteemiga kaasa tulevat abiprogrammi (Windows Snipping Tool). ## Küsimus: Kuidas parandada Enterprise Architect CASE vahendis loodud andmebaasi disaini mudelis riknenud tabelite vahelist seost? **Vastus:** Vaadake palun SEDA videot või vastusele lisatud faili.Kui vaatamata kõigele ei õnnestu seose kirjeldust parandada, siis jätke see nii nagu on ja tehke parandus genereeritud SQL koodis. **Märksõnad:** välisvõti, foreign key ## Küsimus: Kuidas teha nii, et Enterprise Architect 12 vahendis ei genereeritaks MS Accessi andmebaasi disaini mudeli põhjal koodi, mida peab käsitsi parandama? **Vastus:** Tuleb muuta malle (template), mille põhjal koodi genereeritakse. Malle tuleb muuta eraldi iga faili puhul, milles olevast mudelist soovitakse koodi genereerida.Järgnevad probleemid esinevad nii EA12-ga kui ka EA16-ga vaikimisi kaasa tulevates mallides.Mallide vaatamiseks ja muutmiseks valige Package=>Database Engineering=>Edit DDL TemplatesSeejärel valige liitboksist Language andmebaasisüsteem - antud juhul MSAccess. Malli muutmise järel tuleb salvestamiseks selle juures vajutada Save nupule või vajutada Ctrl+S.1. Kuidas teha nii, et genereeritud koodis poleks andmebaasiobjektide identifikaatorid e nimed nurksulgudes? Näiteks lause CREATE TABLE [Riik] (... asemel tahaksin lauset CREATE TABLE Riik (....Valige mall DDL Left Surround ja kustutage sealt avav nurksulg ([). Ärge ridu kustutage.Valige mall DDL Right Surround ja kustutage sealt sulgev nurksulg (]). Ärge ridu kustutage.2. Kuidas teha nii, et genereeritud koodis oleksid andmebaasi disaini mudelis kirjeldatud vaikimisi väärtused, välisvõtmete kompenseerivad tegevused, CHECK kitsendused, veeru tüüp DECIMAL ja et indeksi loomise lauses oleks tabeli nimi.Selleks laadige alla selle vastusega seotud fail ning muutke oma mudelifailis järgmised mallid selliseks nagu need on selles failis. Jälgige, et iga malli lõpus oleks tühi rida. Kui klõpsate EA-s mallide nimekirjas veerul Name, siis saate need tähestiku järgi sorteerida. DDL Check Constraint DDL Column Definition DDL Create Table DDL Data Type DDL Index DDL Reference Definition DDL Script File **Märksõnad:** parandatud, mall, template, koodi genereerimine, generaator, SQL ## Küsimus: Kuidas toimida, kui kasutan Enterprise Architect 12 vahendit, soovin MS Accessi andmebaasi disaini mudelis määrata veeru tüübiks Decimal, kuid seda tüüpi ei ole pakutavate tüüpide valikus? **Vastus:** Project => Settings => Database Datatypes Sealt alt saaks lisada uusi andmetüüpe, mida andmebaasi disaini mudelis kasutada. Valige avanenud aknas Product Name: MS AccessPeate määrama baastüübi (Common Type) (saate valida decimal), täpsuse+skaala ja peate andma tüübile nime. Seejärel tuleb vajutada Save nupule.Decimal tüüpi veerg on mõeldud kümnendmurdude e püsikomaarvude registreerimiseks. Kasutage seda kui on vaja registreerida komakohtadega arve ning on teada maksimaalne kohtade arv peale koma. Kui  Te just ei tegele teadusmõõtmiste andmete registreerimisega, siis peakski komakohtadega arvude registreerimisel kasutama Decimal tüüpi. Sõltuvalt ujukomatüüpi andmete sisemise salvestamise viisist võivad nende puhul tekkida koondandmete leidmisel ümardamise vead.Muide, sellisel juhul peaks kontseptuaalses andmemudelis vastava atribuudi definitsioonis olema kirjas, kui palju komakohti on vaja.Decimal tüübi kasutamise puhul tuleb ära määrata täpsus (precision) ja skaala (scale). precision määrab ära maksimaalse numbrikohtade arvu ja skaala kohtade arvu peale koma. Näiteks veerus, mis on tüüpi Decimal (3,1), saab olla maksimaalne väärtus 99.9 ja minimaalne väärtus -99.9 (kolm numbrikohta, üks peale koma). **Märksõnad:** kümnendmurd, püsikomaarv, ujukomaarv, MSAccess ## Küsimus: Kui Enterprise Architecti litsentsi kehtivus lõpeb, siis kuidas saada litsents uuesti? **Vastus:** Litsents kehtib 10 nädalat. Litsentsi uuesti laenutamine toimub samamoodi nagu litsentsi algselt laenutamine - administraatori õigustes tuleb käivitada litsentsi laenutamise bat fail. Väljapool ülikooli Wifit olles tuleb eelnevalt luua FortiClient VPN ühendus. **Märksõnad:** vpn ## Küsimus: Kui mina muudan näiteks kaupade registri diagrammis klassi seost, siis mina pean uuesti genereerima SQL tabelite disaini kirjelduse? **Vastus:** Teil tuleb tagada kontseptuaalse andmemudeli, andmebaasi füüsilise disaini kirjelduse ja valmistehtud tabelite kooskõla. Selle saavutamiseks on erinevaid strateegiaid, uuesti genereerimine on nendest üks. Arvan, et kui muudatus kontseptuaalses andmemudelis ei ole väga suur, siis tulenevalt kasutatavate CASE vahendite tehnilistest piirangutest, võib muuta kontseptuaalset andmemudelit, siis muuta käsitsi andmebaasi füüsilise disaini kirjeldust ning siis genereerida uuesti SQL kood. ## Küsimus: Kui mul on Enterprise Architect (ver 12) CASE vahendis loodu mudelis Isiku klass koos atribuutidega Isikute registris, aga sooviksin teistes registrites nt Klientide registris seda klassi ilma atribuutideta kuvada, siis kuidas seda teha? **Vastus:** Aktiveerite klassi => parem hiireklõps Features and Properties => Feature and Compartment Visibility. Avanenud aknas eemaldate ülevalt vasakult nurgast linnukesed valikute "Attribute Visibility => All" ja "Operation Visibility => All" eest. **Märksõnad:** olemi-suhte diagramm, refaktoreerimine ## Küsimus: Kumba CASE vahendit eelistada projekti tegemiseks - kas Enterprise Architect (EA) või Rational Rose (RR)? **Vastus:** Mõlemad vahendid on projekti tegemiseks sobivad. Järgnevalt tuuakse esile kummagi tugevad küljed võrreldes teisega. EA eelised RR ees Palju uuem, ettevõtetes rohkem kasutusel 2018. aastal avaldatud ettevõtte arhitektuuri hetkesesisu uuringu kohaselt oli EA ülekaalukalt kõige populaarsem ettevõtte arhitektuuri modelleerimise vahend. Toimetaja hinnangul oli selle vahendi hind selline, et see sobib kasutamiseks paljudes erinevat tüüpi organisatsioonides. 2020. aastal avaldatud uuringu kohaselt (109 vastajat) oli EA kõige populaarsem UML keeles visuaalsete mudelite koostamise vahend sõltumata loodavate mudelite tüüpidest ja eluvaldkonnast, kus vastajad toimetasid. Näiteks funktsionaalsuste modelleerimiseks kasutas seda 53% vastajatest. Andmete modelleerimiseks kasutas seda 45% vastajatest ning teisi UML modelleerimisvahendeid selle ülesande jaoks peaaegu ei kasutatud. Installeerimine ja litsentsi hankimine lihtsam Võimalused luua palju rohkem erinevat tüüpi mudeleid (kuid selles aines ei lähe neid vaja) Võimalik programmeerida juurde laiendusi. Kahte täiendust võiksite proovida kasutada - vaadake palun ja proovige installeerida Tarkvara/EA mudeliteisenduse täiendus Tarkvara/EA klassidiagrammist inimkeelsed laused Andmebaasi disaini mudeli saab luua spetsiifiliselt PostgreSQL või MS Accessi jaoks Semestri alguses loengus projekti tehes kasutan EA-d (samas on RR kasutamise kohta olemas videod) Töövihiku järgi tehtud näiteprojekt on tehtud EA-s, st selle mudelite vaatamiseks on vaja EA-d RR eelised EA ees Litsentsi ei pea 10 nädala tagant värskendama Vähem funktsionaalsust (selleks aineks kõik vajalik olemas), kuid tänu sellele ka lihtsam ja kiiremini kasutatav kasutajaliides Kaasa tulev genereerimismoodul, mis tekitab kontseptuaalsest andmemudelist füüsilise SQL-andmebaasi disaini mudeli, on parem (disaineril on hiljem vaja teha vähem käsitsi muudatusi) Väga palju lihtsam ja kiirem on muuta SQL-andmebaasi disaini kirjeldustes välisvõtmeid - tegevus, mida on vaja päris palju teha Genereeritav SQL kood on lihtsamini käivitataval ja loetaval kujul - koodi tuleb vähem käsitsi muuta Mõlema vahendi nõrkused Fail võib rikneda, mis tähendab, et eelnev töö läheb kaotsi SQL lausete generaator teeb vaikimisi vigu (EA puhul on Teile välja jagatud mallides mitmed vead ära parandatud. Seda sai teha, sest EA puhul saab muuta malle, mille alusel vahend andmebaasi disaini mudelist SQL koodi genereerin) SIIN kataloogis on viited videotele Rational Rose kasutamise kohta. Seal on paralleelselt näha nii Rational Rose kasutamist kui on räägitud ka loogikast loodud mudelite taga. SIIN on demonstratsiooni käigus loodud tulemid (mudelid, SQL kood, loodud andmebaas). Slaidiesitlus (kasutajanimi: SIS2, parool: SIS2), mille teises pooles antakse ülevaade EA ja RR probleemidest seoses andmete modelleerimisega. Rational Rose eestikeelne juhend (kasutajanimi: SIS2, parool: SIS2).NB! Ülikooli vahendusel litsentsi saamise võimalus on vaid tarkvarale, mis on alla laaditud SIIT. ## Küsimus: Ma ei suuda Enterprise Architect (EA) vahendi menüüde rägastikus orienteeruda. Millised on kõige olulisemad menüüpunktid antud aine jaoks? **Vastus:** Järgnevalt on nimetatud EA12 näitel mõnede oluliste funktsioonide asukoht menüüsüsteemis. Tööriistakast, kust saab valida mudelisse lisamiseks uusi elemente. Kui olete selle kinni pannud, siis saate uuesti avada: Diagram=>Toolbox (kiirkorraldus ALT+5) Projekti elementide hierarhia. Kui olete selle kinni pannud, siis saate uuesti avada: View=>Project Browser (kiirkorraldus ALT+0) Andmebaasi disaini mudeli loomiseks mõeldud täiustatud teisenduse kasutusele võtmine: Project=>Data Management=>Import Reference Data Enne andmebaasi disaini mudeli teisenduse abil loomist tuleb määrata, millise andmebaasisüsteemi jaoks disaini mudel luuakse: Project=>Settings=>Database Datatypes Avanenud aknas tuleb soovitud andmebaasisüsteemi juures märkida Set as Default Mudeliteisendus kontseptuaalsest andmemudelist andmebaasi disaini mudeliks: Package=>Model Transformation (MDA)=>Transform Current Package SQL koodi genereerimine: Package=>Database engineering=>Generate package DDL ## Küsimus: Meil tekkis andmebaasi füüsilise disaini mudeli genereerimisega probleem: veerg nimega kood esineb mitmes kohas. Milles võib olla probleem? **Vastus:** See probleem tekib Enterprise Architecti (EA) täiendatud mudeliteisenduse kasutamise korral. Tekib, sest ka EA täiendatud mudeliteisendus pole paraku ideaalne. Konkreetne põhjus on selles, et kontseptuaalses andmemudelis on olemitüüp Klassifikaator, millel on atribuut kood. Klassifikaatoril on palju alamtüüpe (Riik, Amet, Töötaja_seisundi_liik jne) millest igaühe põhjal luuakse eraldi tabel. Kõikidesse nendesse tekib teisenduse tulemusena primaarvõtme veerg kood. See veeru nimi tuleb ära muuta nii klassifikaatorite tabelites kui ka tabelites, kuhu koodid lähevad välisvõtmeks. Näiteks kui tabelis Amet on veerg kood, siis selle uus nimi võiks olla amet_kood. Kui tabelis Töötaja on välisvõtme veerg kood, milles olevad andmed viitavad ridadele tabelis Amet, siis ka sellele veerule tuleb anda nimi amet_kood. Järgnevalt esitan soovitusliku parandamise algoritmi. Kõigepealt terminoloogiast: [Amet]-1--------0..*-[Töötaja] Välisvõti on tabelis Töötaja Amet - primaarne tabel, antud juhul klassifikaatori tabel Töötaja - sõltuv tabel 1. Juhul kui sõltuvas tabelis on täpselt üks välisvõtme veerg nimega kood (näiteks töövihiku kasutamise korral Klient). Muuda primaarvõtme veeru nime klassifikaatori tabelis (näiteks tabelis Kliendi_seisundi_liik: kood=> kliendi_seisundi_liik_kood). Muuda vastavat välisvõtme veeru nime sõltuvas tabelis (antud juhul tabelis Klient: kood=> kliendi_seisundi_liik_kood). 2. Juhul kui sõltuvas tabelis on rohkem kui üks välisvõtme veerg nimega kood (näiteks töövihiku kasutamise korral Töötaja). Kustuta sõltuvast tabelist kõik välisvõtme kitsendused, mis viitavad klassifikaatorite tabelitele (näiteks kaks kitsendust tabelist Töötaja). Muuda primaarvõtme veeru nime kõikides asjassepuutuvates klassifikaatori tabelites (näiteks tabelis Amet: kood=> amet_kood; tabelis Töötaja_seisundi_liik: kood=> töötaja_seisundi_liik_kood). Muuda vastavate välisvõtme veergude nimesid sõltuvas tabelis (antud juhul tabelis Töötaja: kood=> amet_kood; kood=> töötaja_seisundi_liik_kood ). Loo välisvõtme kitsendused mudelis käsitsi uuesti. ## Küsimus: Mida teha, kui arvutiklassi arvutis küsib Enterprise Architect (EA) avamisel võtit ja ei ole nõus ilma selleta käivituma? **Vastus:** Sulgege EA. Valige: Control Panel => System and Security => Configuration Manager => Configurations => evaluate CB WRK Enterprise Achitect Key Seejärel avage EA uuesti. **Märksõnad:** litsents, värskendamine, laenutamine, arvutiklass ## Küsimus: Mul registrite analüüsi mudel loodud. Pärast andmebaasi disaini mudeli nagu videos õppeaine kodulehel. Kokku kõik on korras, aga tekib tõsine probleem. CASE vahend ehitab seosed Kliendi, Ameti, Treeningu ja Töötaja seisundi liigi vahel. Aga ei peaks ja ma ei taha. Mida teha? **Vastus:** Arvan, et põhjuseks on analüüsi mudelisse kogemata tehtud ja korralikult kustutamata jäänud valed seosed. Konkreetsel juhul võtke palun lahti analüüsi mudelis klientide registri olemi-suhte diagramm ja lohistage sellele mudelist olemitüübid (klassid) Amet, Töötaja_seisundi_liik ja Treening. Kui selle tulemusel tekivad diagrammile ka seosed Kliendiga, siis kustutage need seosed. Seose mudelist kustutamiseks tehke: Enterprise Architect (EA) CASE vahendis seos aktiivseks; valige parema hiire klahvi alt hüpikmenüüst "Delete connector" või vajutage Delete klahvile; valige "Delete the connector from the model". Rational Rose (RR) CASE vahendis seos aktiivseks; valige parema hiire klahvi alt hüpikmenüüst "Edit" => "Delete from Model". Seejärel genereerige andmebaasi disaini mudel uuesti. Samuti eemaldage klientide registri olemi-suhte diagrammilt Amet, Töötaja_seisundi_liik ja Treening. Kuna kasutate analüüsi mudelit uue tehise (disaini mudeli) genereerimiseks, siis on väga oluline, et analüüsi mudelisse ei jääks "prügi". ## Küsimus: Rationa Rose-il pole menüüs punkti Data Modeler => New => Database, millega genereerida andmebaasi füüsilise disaini mudelit. Mis on valesti? **Vastus:** Selleks, et saaksite kasutada Rational Rose'i (2007) Data Modeleri, peab arvutis eelnevalt olema installeeritud .NET Framework redistributable (ver. 1.1) või kõrgem Installige enne .NET ja siis Rational. ## Küsimus: Soovin Enterprise Architect 12 vahendis genereerida SQL lauseid, kuid lausete genereerimise aknas ei saa ma muuta tabelite järjekorda genereeritavas skriptis (nupud järjekorra muutmiseks ei tööta). Mida teha? **Vastus:** Jah, see on EA probleem, mida mõnikord tuleb ette.Küsimus on selles, et kui mul on tabelite loomise kood, milles välisvõtmete deklareerimine on osa CREATE TABLE lausest, siis on lausete käivitamise järjekord oluline.CREATE TABLE A(a_id INTEGER,CONSTRAINT pk_a PRIMARY KEY (a_id));CREATE TABLE B(b_id INTEGER,a_id INTEGER NOT NULL,CONSTRAINT pk_b PRIMARY KEY (b_id),CONSTRAINT fk_b_a FOREIGN KEY (b_id) REFERENCES B(b_id));Kõigepealt tuleb luua tabel A ja siis saab luua tabeli B.EA vahendis saab koodi genereerimisel määrata tabelite loomise lause järjekorra. See on oluline, kui koodi genereerimisel on määratud: Options=>Separate Constraints from Tables=False Mida EA vahendis teha, kui selline probleem esineb? Proovida liigutada nimekirjas suvalisi tabeleid üles/alla. Mõnikord see justkui lukustab nimekirja lahti ja ka tabeleid, mida seni ei saanud nimekirjas üles/alla liigutada, saab peale seda liigutada. Siiski on suur tõenäosus, et see ei aita. Viia järjekord soovitule nii lähedaseks kui saab, genereerida SQL laused ja muuta genereeritud koodis lausete järekorda käsitsi. Valige Options=>Separate Constraints from Tables=True ning genereerida kood, kus tabeli loomise lausete järjekord ei ole oluline. ## Küsimus: Üritan Mauruse keskkonnas taotleda uut Enterprise Architect programmi litsentsi. Olen kunagi EA litsentsi juba taotlenud, seega saan veateate, et "Te olete seda ressurssi juba taotlenud". Mida teha? **Vastus:** Uuesti ei saagi taotleda, sest üks taotlus on olemas, rahuldatud ja endiselt kehtiv. Pääsete rahuldatud taotlustele vastavatele failidele ligi "Minu taotlused" alt. Sealt saate nii failid, millega EA enda arvutisse installeerida kui ka litsentsi taotlemiseks mõeldud bat faili. Tallinna Tehnikaülikooli ruumides saab laenutamist teha üle Wi-Fi. Väljaspool ülikooli tuleb enne laenutamist luua FortiClient VPN ühendus. Litsentsi aegumise järel tuleb laenutamist korrata. Veenduge, et Enterprise Architect (EA) on suletud, käivitage bat fail ning avage EA, veendumaks, et litsents on laenutatud ning programm avaneb. **Märksõnad:** vpn --- # Teema: Vahendid - MS Access ## Küsimus: Kas ja millised on MS Accessi eelised SQLi õppimisel? **Vastus:** SQL andmekäitluskeele lausete (SELECT, INSERT, UPDATE, DELETE) koostamiseks saab kasutada graafilist kasutajaliidest - Query Designer. See graafiline kasutajaliides realiseerib visuaalse andmebaasikeele Query by Example. Võimalik on tõlkida lauseid ühest keelest (SQL ja Query by Example) teise. Siit saab vaadata videoid Query by Example abil päringute kooostamisest. Tabelites on läbi graafilise kasutajaliidese lihtne teha andmemuudatusi. Nii saab kergelt teha andmemuudatusi, kontrollimaks, et koostatud SQL laused annavad igas olukorras oodatud tulemuse. MS Accessi SQLi mägimurrak ei ole nii suurte võimalustega kui võimekamatel SQL-andmebaasisüsteemidel, kuid kõik põhiline on olemas. Näiteks lendama õppimisel ei alustata praktiseerimist ka mitte kohe reisi- või sõjalennukist, vaid kõigepealt saavutatakse põhjendatud enesekindlus väikesel lennukil ja sellega sillutatakse teed aina suuremate lennukitega lendamiseks. PostgreSQL ja Oracle lisavõimalusi võib vaadata lisamaterjalide lehelt (kasutajanimi: SIS2 ja parool: SIS2) SIIT (Ja mõelge, kas tahaksite ka kõige selle peale kontrolltööd teha). ## Küsimus: Kas MS Accessis tuleks hoiduda Decimal tüübi kasutamisest? **Vastus:** Ei!Kui loete soovitusi (nagu see siin), siis pöörake tähelepanu millise süsteemi versiooni kohta need on. See konkreetselt on vana versiooni kohta ning vähemalt MS Access 2019 ja uuemates ei kehti. Tehke katse. Käivitage oma andmebaasis ükshaaval järgmised laused:CREATE TABLE Decimal_test (v DECIMAL (3,2));INSERT INTO Decimal_test (v) VALUES (1.0);INSERT INTO Decimal_test (v) VALUES (-1.0);INSERT INTO Decimal_test (v) VALUES (-3.22);INSERT INTO Decimal_test (v) VALUES (-1.01);INSERT INTO Decimal_test (v) VALUES (0);Seejärel proovige päringut:SELECT * FROM Decimal_testORDER BY v;Päringu tulemuses on sorteerimisega on kõik korras. **Märksõnad:** MSAccess ## Küsimus: Kirjutan MS Accessi päringus ajahetke esitava stringi niimoodi - '31.12.2010 23:59:59' - ja saan vea. Kuidas on õige ajatemplit esitavat väärtust kirja panna? **Vastus:** MS Accessis tuleb ajatemplit esitav string e sõne (märkide jada) kirjutada formaadis - #YYYY-MM-DD HH24:MI:SS#Kasutage ISO 8601 standardis kirjeldatud formaati.Näide: #2100-12-31 23:59:59#See on 31. detsember 2100 kell 23:59:59.SELECT *FROM ReserveerimineWHERE lopu_aeg<#2010-12-31 23:59:59#;Alternatiiviks on kasutada funktsiooni DateValue.SELECT *FROM ReserveerimineWHERE lopu_aeg<DateValue('31.12.2010 23:59:59');Võrdluseks - PostgreSQLis.SELECT *FROM ReserveerimineWHERE lopu_aeg<'2010-12-31 23:59:59';SELECT *FROM ReserveerimineWHERE lopu_aeg<to_date('31.12.2010 23:59:59', 'DD.MM.YYYY HH24:MI:SS');to_date funktsiooni esimene argument on ajahetke esitav string ja teine argument on muster, mis ütleb süsteemile, kuidas seda interpreteerida. **Märksõnad:** PostgreSQL ## Küsimus: Kuidas jõustada MS Accessis kitsendus, et isikukood peab koosnema ainult tähtedest, numbritest, tühikutest, sidekriipsudest, plussmärkidest, võrdusmärkidest ja kaldkriipsudest? **Vastus:** MS Access ei paku täielikku toetust regulaaravaldiste kasutamisele, kuid selle LIKE predikaadi mustrite koostamise võimalusi on laiendatud regulaaravaldistest tuntud võimalustega. Kui on valitud File => Options => Object Designers => Query design => SQL Server Compatible Syntax (ANSI 92) => This database(Fail => Suvandid => Objektikujundajad => Päringu kujundus => SQL Serveriga ühilduv süntaks (ANSI 92) => See andmebaas), siis * asemel tuleb kasutada % ja ? asemel _MS Accessi andmebaasi saab lokaliseerida (konkreetse keele keskkonnaga kohandada), määrates andmebaasis tekstiliste väärtuste sorteerimiseks kasutatava keele:Fail=>Suvandid=>Üldist=>Uue andmebaasi sortimisjärjestusFile=>Options=>General=>New database sort orderKonkreetse andmebaasi puhul kasutatav keel määrab, milliste märkide vahemikku tuleks mustri koostamisel kasutada. Eesti tähestiku esimene täht on A ja viimane täht on Y. Kui andmebaasis on sorteerimise keeleks eesti keel, siis lisan tabelis Isik veerule isikukood valideerimisreegli:Not ALike '%[!A-Y0-9 +=/\-]%'Isikukood ei tohi olla selline, kus sisaldub mõni lubatud märkide hulka mittekuuluv märk. Hüüumärk tähistab Accessis selles kontekstis eitust - ei kuulu loetletud märkide hulka.[!A-Y0-9 +=/\-]Nii tähistatakse märkide hulka, kuhu kuulub üks märk. Selles märkide hulgas on kõik märgid, mis ei ole tähemärgid, numbrimärgid, tühik, plussmärk, võrdusmärk, kaldkriips, sidekriips.Kui andmebaasis on sorteerimise keeleks määratud general e inglise keel, siis lisan tabelis Isik veerule isikukood valideerimisreegli, sest inglise tähestiku esimene täht on A ja viimane Z:Not ALike '%[!A-Z0-9 +=/\-]%'Võrdluseks - PostgreSQLis ja Oracles tuleks kasutada regulaaravaldist '^[[:alnum:] +=-\/\]*$'. Alates stringi algusest (^) kuni lõpuni ($) peab selles olema null või rohkem(*) nurksulgudes kirjeldatud märkide hulka kuuluvat märki. [[:alnum:]] on eeldefineeritud märkide klass, kuhu kuuluvad tähed ja numbrimärgid. PostgreSQLis oleks CHECK kitsenduse tingimus  isikukood~'^[[:alnum:] +=-\/\]*$' ~ on operaator tõstutundlikuks (case sensitive) regulaaravaldise mustrile vastavuse kontrollimiseks.Oracles oleks CHECK kitsenduse tingimus REGEXP_LIKE(isikukood,'^[[:alnum:] +=-\/\]*$')REGEXP_LIKE on funktsioon regulaaravaldise mustrile vastavuse kontrollimiseks. **Märksõnad:** valideerimisreegel, check, validation rule, PostgreSQL, Oracle ## Küsimus: Kuidas jõustada MS Accessis kitsendus, et kui üks ja sama töötaja omab ühte ja sama rolli mitu korda, siis ei tohi rolli omamise ajaperioodid kattuda? **Vastus:** Saan jõustada nõrgema kitsenduse, mille kohaselt andmete registreerimise hetke seisuga ei tohi ühel ja samal töötajal olla ühe ja sama rolli kohta rohkem kui üks kehtiv rolli omamine. Kehtiv rolli omamine on selline, mille puhul hetke aeg jääb rolli omamise alguse ja lõpu aja vahele. Seega, kui töötajal 1 on 01.01.2022 kuni 01.01.2023 roll koodiga 3, siis ei saa 06.01.2022 lisada sellele töötajale teist rolli 3 omamist vahemikuks 01.05.022 kuni 01.05.2023.ALTER TABLE Tootaja_rolli_omamineADD CONSTRAINT chk_tootaja_rolli_omamine_unikaalsusCHECK (NOT EXISTS(SELECT isik_id, tootaja_roll_koodFROM Tootaja_rolli_omamineWHERE Now() BETWEEN alguse_aeg AND lopu_aegOR (alguse_aeg<=Now() AND lopu_aeg IS NULL)GROUP BY isik_id, tootaja_roll_koodHAVING Count(*)>1));MS Accessis, erinevalt paljudest teistest andmebaasisüsteemidest, saab CHECK kitsenduses kasutada alampäringut. SQL standard ei luba CHECK kitsendustes kasutada mittedeterministlikku funktsiooni. Selline funktsioon tagastab samade argumentidega väljakutsudes erinevatel hetkedel erineva tulemuse. Now() on mittedeterministlik funktsioon.MS Access (aga ka näiteks PostgreSQL) lubavad CHECK kitsendustes selliseid funktsioone kasutada.Võrdluseks - PostgreSQLis saab küsimuses nimetatud piirangu jõustada täielikult. Selleks tuleb luua EXCLUDE kitsendus. EXCLUDE kitsendus on unikaalsuse kitsenduse edasiarendus, mille puhul saab väärtuste unikaalsuse e kordumatuse kontrollimiseks kasutada ka mõnda muud operaatorit kui võrdsuse kontrolli operaator (=), mida kasutab UNIQUE kitsendus. Vaadake täpsemat näidet slaidikomplektist. Otsige sealt fraasi "Kattuvate perioodide vältimine". **Märksõnad:** valideerimisreegel, check, validation rule, PostgreSQL ## Küsimus: Kuidas jõustada MS Accessis kitsendus, et meiliaadress on isiku tõstutundetu unikaalne identifikaator? **Vastus:** Tõstutundetu unikaalsus tähendab näiteks, et kui süsteemis on registreeritud isiku meiliaadress Mati@mets.ee, siis mõnele teisele isikule meiliaadressi mati@mets.ee registreerida ei saa.Tõstutundetu unikaalsuse jaoks MS Accessis piisab kui defineerite unikaalsuse kitsenduse. MS Access, erinevalt paljudest teistest andmebaasisüteemidest, kasutab tõstutundetut stringide võrdlemist.Seega näiteksSELECT *FROM IsikWHERE perenimi='METS';leiab nii isikud perenimega mets, Mets kui ka METS. Unikaalsuse e kordumatuse kontrollimisel kasutatakse väärtuste võrdlemist. MS Accessi jaoks on järgnev tõene väide: Mati@mets.ee=mati@mets.eeSeega veerus e_meil ei saa need väärtused samaaegselt olla.Võrdluseks - PostgreSQLis ja Oracles on unikaalsuse kontroll vaikimisi tõstutundlik, st Mati@mets.ee<>mati@mets.ee ja erinevatel isikutel võivad sellised meiliaadressid olla registreeritud.PostgreSQLis tuleks sellise reegli jõustamiseks luua kas funktsioonil (upper või lower) põhinev unikaalne indeks või EXCLUDE kitsendus. EXCLUDE kitsendus on unikaalsuse kitsenduse edasiarendus, mille puhul saab väärtuste unikaalsuse e kordumatuse kontrollimiseks kasutada ka mõnda muud operaatorit kui võrdsuse kontrolli operaator (=), mida kasutab UNIQUE kitsendus. Oracles tuleks luua funktsioonil (upper või lower) põhinev unikaalne indeks.Ei indekseid ega ka EXCLUDE kitsendust SQL standard ette ei näe, st tegemist on võimalustega, mis on spetsiifilised konkreetsele andmebaasisüteemidele. **Märksõnad:** PostgreSQL, Oracle ## Küsimus: Kuidas jõustada MS Accessis kitsendus, et mittelõpetatud tubade nimetused peavad olema unikaalsed? **Vastus:** Kui andmebaasis defineerida tabelis Tuba unikaalsuse kitsendus UNIQUE (nimetus), siis on nimetus globaalselt unikaalne. Seega, kui tuba on lõpetatud, siis uuesti sama nimetusega tuba registreerida ei saa. Järelikult selline UNIQUE kitsendus ei sobi. Kustutan kõigepealt sellise unikaalsuse kitsenduse:ALTER TABLE TubaDROP CONSTRAINT AK_Tuba_nimetus;MS Accessis saab kasutada CHECK kitsendustes alampäringuid. Ülesande lahendamiseks tuleb tabelile Tuba lisada järgnev kitsendus. Eeldame, et seisund "Lõpetatud" on koodiga 4. ALTER TABLE TubaADD CONSTRAINT chk_toa_nimetuse_unikaalsusCHECK (NOT EXISTS(SELECT nimetusFROM TubaWHERE toa_seisundi_liik_kood<>4GROUP BY nimetusHAVING Count(*)>1));Ei tohi eksisteerida olukorda, et mittelõpetatud tubasid, mis on ühesuguse nimega, on rohkem kui üks.Võrdluseks - PostgreSQLis tuleks sellise reegli jõustamiseks luua kas osaline unikaalne indeks (see on indeks, mis on loodud ainult teatud tingimustele vastavatele ridadele - partial unique index) või EXCLUDE kitsendus. EXCLUDE kitsendus on unikaalsuse kitsenduse edasiarendus, mille puhul saab väärtuste unikaalsuse e kordumatuse kontrollimiseks kasutada ka mõnda muud operaatorit kui võrdsuse kontrolli operaator (=), mida kasutab UNIQUE kitsendus. Oracles tuleks luua osaline unikaalne indeks.Ei indekseid ega ka EXCLUDE kitsendust SQL standard ette ei näe, st tegemist on võimalustega, mis on spetsiifilised konkreetsele andmebaasisüteemidele. **Märksõnad:** PostgreSQL ## Küsimus: Kuidas jõustada MS Accessis kitsendus, et riigi kood koosneb täpselt kolmest suurtähest, kusjuures täpitähed ja katusega tähed pole lubatud? **Vastus:** MS Access ei paku täielikku toetust regulaaravaldiste kasutamisele, kuid selle LIKE predikaadi mustrite koostamise võimalusi on laiendatud regulaaravaldistest tuntud võimalustega. Kui on valitud File => Options => Object Designers => Query design => SQL Server Compatible Syntax (ANSI 92) => This database(Fail => Suvandid => Objektikujundajad => Päringu kujundus => SQL Serveriga ühilduv süntaks (ANSI 92) => See andmebaas), siis * asemel tuleb kasutada % ja ? asemel _Lisan tabelis Riik veerule riik_kood, valideerimisreegli, mis koosneb omavahel seotud alamtingimusest, mis peavad kõik olema täidetud.Not ALike '%[!ABCDEFGHIJKLMNOPQRSTUVWXYZ]%' And StrComp([riik_kood];UCase([riik_kood]);0)=0 And Len([riik_kood])=3Not ALike '%[!ABCDEFGHIJKLMNOPQRSTUVWXYZ]%' - Riigi kood ei tohi vastata mustrile, mille kohaselt on seal vähemalt üks märk, mis ei ole ABCDEFGHIJKLMNOPQRSTUVWXYZ. Need on võimalikud tähed, mida riikide koodides kasutatakse. Täpitähed ja katusega tähed sinna hulka ei kuulu. Hüüumärk (!) ütleb, et märk ei kuulu nende märkide hulka.StrComp([riik_kood];UCase([riik_kood]);0)=0 - MS Access on stringide võrdlemisel vaikimisi tõstutundetu (case insensitive). Seega MS Accessi jaoks on EST ja est ühesugused (võrdsed) stringid. StrComp on MS Accessi funktsioon, mis võimaldab stringide tõstutundlikku võrdlemist. Tõstutundlikult võrreldes peab riigi kood olema võrdne suurtähtedeks teisendatud riigi koodiga.Len([riik_kood])=3 - Riigi kood peab olema täpselt kolm märki pikk. Len on MS Accessi funktsioon, mis leiab etteantud stringi pikkuse.Võrdluseks - PostgreSQLis ja Oracles tuleks kasutada regulaaravaldist '^[A-Z]{3}$'. Alates stringi algusest (^) kuni lõpuni ($) peab selles olema täpselt kolm suurtähte A-Z. PostgreSQLis oleks CHECK kitsenduse tingimus  riik_kood~'^[A-Z]{3}$' ~ on operaator tõstutundlikuks (case sensitive) regulaaravaldise mustrile vastavuse kontrollimiseks.Oracles oleks CHECK kitsenduse tingimus REGEXP_LIKE(riik_kood, '^[A-Z]{3}$')REGEXP_LIKE on funktsioon regulaaravaldise mustrile vastavuse kontrollimiseks. **Märksõnad:** valideerimisreegel, check, validation rule, PostgreSQL, Oracle ## Küsimus: Kuidas jõustada MS Accessis kitsendus, et tuba saab aktiivsesse seisundisse viia ainult siis, kui see tuba on seotud vähemalt ühe kategooriaga? **Vastus:** Eeldame, et seisund "Aktiivne" on koodiga 2. Tuleb luua CHECK kitsendus.ALTER TABLE TubaADD CONSTRAINT chk_tuba_aktiivne_peab_olema_kategooriaga CHECK (NOT EXISTS (SELECT *FROM TubaWHERE toa_seisundi_liik_kood=2AND NOT EXISTS (SELECT *FROM Toa_kategooria_omamineWHERE Tuba.tuba_kood=Toa_kategooria_omamine.tuba_kood)));Ei tohi eksisteerida mitte ühtegi aktiivses seisundis tuba, millel pole ühtegi seotud kategooriat.See kitsendus rakendub, kui muudetakse toa seisundit tabelis Tuba. See kitsendus ei keela aktiivsete tubade kategooriad ära kustutada.Töövihiku projektis tuleneb see kitsendus sellest, et aktiivsete tubade vaatamine toimub kategooriate järgi. Kui aktiivne tuba pole üheski kategoorias, siis selle toa andmeid vaadata ei saa. Töövihiku projektis on see kitsendus väljendatud valvurtingimusena seisundidiagrammil oleval seisundi üleminekutel seisundisse "Aktiivne". SQL näeb ka ette andmebaasiobjekti tüüpi üldine kitsendus (assertion). See on eraldisseisev nimega CHECK kitsendus, mis pole seotud otseselt ühegi tabeliga, kuid mille loogikaavaldises olev päring võib viidata andmebaasi erinevatele tabelitele. Tänapäeva turul olevad andmebaasisüsteemid paraku sellise andmebaasiobjekti loomist ei võimalda. Oracle foorumis tekitas sellist tüüpi objekti toe lisamine väga palju positiivset tagasisidet, kuid Oracle andmebaasisüsteemi pole seda tüüpi objekti tuge ikkagi lisatud.MS Accessis saab luua lisakitsendusi tabeliga seotud CHECK kitsendustena. Erinevalt paljudest teistest andmebaasisüsteemidest (nt PostgreSQL, Oracle, MySQL), saab MS Accessis kasutada sellistes CHECK kitsendustes alampäringuid. Üldised kitsendused ja tabeli CHECK kitsendustes alampäringute kasutamine võimaldavad jõustada keerukamaid reegleid ühes kohas, kaitstavatele andmetele lähedal (andmebaasis), kontrollist möödahiilimist vältival viisil, väikese koodi hulgaga. Tulles tagasi vastuse alguses oleva näite juurde, siis kui selle kitsenduse saaks jõustada üldise kitsendusena (assertion), siis keelaks see ka aktiivselt toalt kõikide kategooriate kustutamise. Praegune lahendus seda ei keela.Võite küsida, milleks sellest rääkida, kui paljudes teistes andmebaasisüsteemides sellist kitsendust luua ei saa. Vastusena ütleksin, et siin on MS Access ajast ees, mitte ajast maas. Kui kitsendusi saab luua andmebaasi tasemel väikese koodi hulgaga ja möödahiilimist välistaval viisil, siis see lihtsustab märkimisväärselt andmebaasirakenduse loomist.Nende teiste, kaasaegsemate ja võimekamate süsteemide puhul, tuleb kontrolle teha andmebaasis trigeritega, andmete registreerimiseks mõeldud andmebaasiserveris talletatud rutiinides, rakenduses või jätta üldse tegemata - kõigi selliste lahendusvariantidega on seotud omad suured probleemid ja raskused. **Märksõnad:** valideerimisreegel, check, validation rule, PostgreSQL, Oracle ## Küsimus: Kuidas jõustada MS Accessis tabeliga seotud kitsendus, et elukoht ei tohi olla ainult numbritest koosnev string? **Vastus:** MS Access ei paku täielikku toetust regulaaravaldiste kasutamisele, kuid selle LIKE predikaadi mustrite koostamise võimalusi on laiendatud regulaaravaldistest tuntud võimalustega. Nimetatud kitsenduse jõustamiseks on abi, kui see kitsendus ümbersõnastada. Kui elukoha stringis on vähemalt üks numbrimärk, siis peab selles olema ka mõni selline märk, mis ei ole numbrimärk. Teatavasti võib binaarset loogilist operatsiooni implikatsioon kasutava avaldise P=>Q kirjutada teisendusreeglite alusel ümber samaväärseks avaldiseks: NOT (P) OR Q. Sellise avaldise saab aga juba tabelitaseme valideerimisreeglina kirja panna. Antud juhul P="Kui elukoha stringis on vähemalt üks numbrimärk" Q="peab selles olema ka mõni selline märk, mis ei ole numbrimärk" Seega seon MS Accessis veeruga elukoht valideerimisreegli: Not ([elukoht] ALike '%[0-9]%') Or ([elukoht] ALike '%[!0-9]%') [!0-9] ütleb mustris, et leiduma peab vähemalt üks märk, mis ei kuulu numbrimärkide hulka. Veel üks võimalus on defineerida MS Accessis veeruga elukoht seotud valideerimisreegel: IsNumeric([elukoht])=False Võrdluseks, PostgreSQL ja Oracle võimaldavad regulaaravaldiste kasutamist: PostgreSQLis tuleks tabeliga Isik siduda CHECK kitsendus: CHECK (elukoht!~'^[[:digit:]]+$') Oracles tuleks tabeliga Isik siduda CHECK kitsendus: CHECK(NOT REGEXP_LIKE(elukoht,'^[[:digit:]]+$')) Need kitsendused kontrollivad, et elukoht ei vastaks mustrile, mille kohaselt sisaldab see ainult numbrimärke. **Märksõnad:** MSAccess ## Küsimus: Kuidas kirjeldada Decimal tüüpi veergu läbi tabeli graafilise disaineri? **Vastus:** Määrake veeru omaduste juures järgnevat:Data Type (Andmetüüp): Number (Arv)Field Size (Välja suurus): Decimal (Kümnendarv)Precision (Täpsus): Soovitud maksimaalne numbrikohtade arvScale (Mastaapimine): Soovitud kohtade arv peale komaValik Decimal Places (Kümnendkohad) määrab kuvatavate komakohtade arvu ja sinna võib jätta Auto (Automaatne).Näiteks veerus, mis on tüüpi Decimal (3,1), saab olla maksimaalne väärtus 99.9 ja minimaalne väärtus -99.9 (kolm numbrikohta, üks peale koma). Antud juhul on täpsus 3 ja skaala 1. ## Küsimus: Kuidas saab MS Accessis ja PostgreSQLis lisada veergudele kommentaare? **Vastus:** MS Accessis saab minna tabeli disainivaatesse e kujundusvaatesse ja kirjutada kommentaari tekst veeru juurde välja Kirjeldus (Valikuline) / Description (Optional).PostgreSQLis saab kommentaari lisada SQL-standardis mitte ettenähtud COMMENT lausega. COMMENT ON COLUMN Amet.max_tootunde_nadalas IS 'Maksimaalne töötundide arv nädalas peab olema vahemikus 0 – 50 (otspunktid kaasa arvatud)';PostgreSQLis saab kommentaari lisada ka kitsendusele, MS Accessis ei saa.COMMENT ON CONSTRAINT chk_synni_kp ON Tootaja IS 'Sünni kuupäev peab olema vahemikus 1. jaanuar 1920 ja tänane kuupäev (otspunktid kaasa arvatud).';Kommentaarid on kasulikud, sest need säilitatakse andmebaasis ja tulevased andmebaasi hooldajad ning arendajad saavad neid lugeda. ## Küsimus: Kuidas saab MS Accessis ja PostgreSQLis tagada andmete reeglitele vastavuse kontrollimisel "ilusaid" veateateid? **Vastus:** Kui luua andmebaasis CHECK kitsendus (saab luua nii MS Accessi kui PostgreSQL andmebaasides), siis juhul kui andmemuudatus eksib selle kitsenduse vastu, siis veateates näidatakse kitsenduse nime. Muutes nime arusaadavamaks, muutub ka veateade arusaadavamaks.SQL standard kirjeldab trigeri objekti (CREATE TRIGGER lause). PostgreSQLis saab trigereid luua. Triger on andmebaasis olev programm, mis käivitub tabelis tehtava andmemuudatuse tulemusel. Trigerite abil saab kontrollida andmemuudatuste reeglitele vastavust ja ebasobiva muudatuse tagasi lükata. Kui tahaksite, et PostgreSQL annaks andmete reeglitele vastavuse kontrolli käigus "ilusaid" veateateid, siis tuleks luua andmebaasis tabeliga seotud triger. MS Accessis trigereid luua ei saa, aga seal on väga sarnane võimalus luua andmemakrosid (data macros) - sisuliselt sama asi, lihtsalt loomiseks ei saa kasutada andmebaasikeelt, vaid see tuleb ehitada graafilises kasutajaliideses."Ilusate veateadete" jaoks pole MS Accessis andmemakrosid üldiselt vaja, sest piiranguid saab jõustada valideerimisreeglitega ning sinna juurde saab lisada valideerimisteksti. Valideerimisteksti kuvatakse siis, kui andmemuudatus selle reegli vastu eksib.PostgreSQLis (ja SQL-andmebaasisüsteemides üldiselt) on trigerite abil "ilusate veateadete" saamisel kõrge hind - rohkem koodi, rohkem testimist, kerge teha vigu ning andmebaasisüsteem ei oska trigerite abil jõustatud reegleid SQL lausete täitmise optimeerimisel ära kasutada.Seega PostgreSQL korral (ja SQL-andmebaasisüsteemides üldiselt) oleks eelistatud lahendus deklaratiivne (ütlen, mida peab kontrollima, mitte kuidas peab kontrollima) kitsenduste jõustamine CHECK kitsenduste abil.Samas leidub keerukamaid reegleid (kontroll hõlmab andmete lugemist erinevatest tabelitest või sama tabeli erinevatest ridadest), mida PostgreSQLis (ja SQL-andmebaasisüsteemides üldiselt) ei saagi muul viisil realiseerida kui trigeritega. ## Küsimus: Kuidas teha nii, et MS Accessis oleksid avatud aknad (näiteks tabelid või SQL lausete kirjutamise aknad) organiseeritud sakkidena (kaartidena) üksteise kõrval (vt lisatud pilt)? **Vastus:** Valige File=> Options=> Current Database => Tabbed DocumentsSee valik on üsna pakutavate valikute nimekirja alguses.Samuti veenduge, et sealsamas on märgistatud "Display Document Tabs".Kui soovite, et aknad oleksid üksteisest sõltumatult väiksemaks ja suuremaks tehtavad ning võivad ka üksteist katta,siis sealsamas on valik "Overlapping Windows".Vt ka: https://599cd.com/glossary/access/overlappingwindowstabbeddocuments/?key= ## Küsimus: Kust saab infot MS Accessis kasutusel oleva SQL mägimurraku e dialekti kohta? **Vastus:** Kuigi SQL on rahvusvaheline standard, ei realiseeri paraku ükski andmebaasisüsteem seda täielikult. Ilmselt on põhjus selles, et standard on väga mahukas. See tähendab, et mistahes SQL-andmebaasisüsteemis on ilmselt võimalusi, mida standard näeb ette, kuid süsteem ei paku nagu ka võimalusi, mis on spetsiifilised sellele süsteemile. See on paraku elu tõsiasi. Need on mõned allikad, kus aine materjalidele lisaks MS Accessi SQL mägimurraku kohta lugeda. Jet SQL (see on MS Accessi aluseks oleva andmebaasimootori nimi), Microsoft Access SQL reference. **Märksõnad:** mägimurrak, MSAccess, MS Access ## Küsimus: Käivitan MS Accessis päringu (query), mis ei ole SELECT lause. Tulemuseks on teade: Päringul peab olema vähemalt üks sihtväli/Query must have at least one destination field. Mida ma teen valesti? **Vastus:** Te olete avanud ekraanil päringu (query) ning käivitamiseks teete topeltklõpsu selle päringu ikoonil Accessi objektide nimekirjas (vt lisatud pilti). Selle peale arvab MS Access, et tahate käivitada SELECT lauset ja tulemuseks on nimetatud viga. Lause käivitamiseks tuleb antud juhul valida lindilt (ribbon) menüü Kujundus (Design) ning vajutada seal hüüumärgiga nupule Käivita (Run). **Märksõnad:** MS Access ## Küsimus: Mille poolest erineb MS Accessi andmetüüp BIT (YESNO) SQL standardis ettenähtud andmetüübist BOOLEAN? **Vastus:** MS Accessis on BIT tüüp selline, mille korral tehakse teisendus NULL=>FALSECREATE TABLE Toode (toode_kood INTEGER,on_aktiivne BIT DEFAULT TRUE,CONSTRAINT pk_toode PRIMARY KEY (toode_kood));INSERT INTO Toode (toode_kood, on_aktiivne) VALUES (1, NULL);SELECT Count(*) AS cntFROM ToodeWHERE on_aktiivne=FALSE;--Tulemuses 1 ridaSELECT Count(*) AS cntFROM ToodeWHERE on_aktiivne IS NULL;--Tulemuses 0 ridaSamas tõelise BOOLEAN tüübi korral seda ei tehta. Näide PostgreSQList.CREATE TABLE Toode (toode_kood INTEGER,on_aktiivne BOOLEAN DEFAULT TRUE,CONSTRAINT pk_toode PRIMARY KEY (toode_kood));INSERT INTO Toode (toode_kood, on_aktiivne) VALUES (1, NULL);SELECT Count(*) AS cntFROM ToodeWHERE on_aktiivne=FALSE;--Tulemuses 0 ridaSELECT Count(*) AS cntFROM ToodeWHERE on_aktiivne IS NULL;--Tulemuses 1 ridaNULL tähistab antud juhul tõeväärtust UNKNOWN. Seega registreerisin väite, et pole teada, kas toode 1 on aktiivne või mitte. Vältimaks kolmevalentse loogika kasutamist, mille korral väite kontrolli tulemus võib olla TRUE/FALSE/UNKNOWN, tuleks veerule on_aktiivne deklareerida NOT NULL kitsendus. **Märksõnad:** PostgreSQL, MS Access ## Küsimus: Millised on MS Accessi eelised teiste SQL-andmebaasisüsteemide ees? **Vastus:** Iga töö jaoks on oma tööriistad. Töövahend pole universaalselt halb ega hea, vaid sellel on sobivad ja mittesobivad kasutusvaldkonnad. Ma pole nõus nendega, kes MS Accessi põlastavad ja selle peale nina kirtsutavad. Prototüüpide, üksikkasutajate andmebaaside ja väikeettevõtete andmebaaside loomiseks on see väga hea vahend. Saan aru, kui kõhklusi tekitab hind, suletud lähtekood või tootjafirma maine, kuid funktsionaalsuselt on see väga hea vahend. Lihtsalt "ilusate silmade" eest selles pingereas kõrgele kohale ei jõua (MS Access on seal esikümnes või selle lähedal).Siin on näide artiklist, kus tuuakse välja MS Accessi puuduseid. Samas selles samas artiklis välja toodud alternatiivide juures tuuakse välja nende nõrgad küljed, mis näitavad nende alternatiivide nõrkuseid. Selle sama artikli kommentaaride osas on elav arutelu, kus ei olda autoriga nõus. Muuhulgas viidatakse seal 2019. aasta intervjuule MS Accessi programmijuhiga, kes kinnitab Microsofti jätkuvat pühendumust MS Accessi edasi arendada. Siin, siin ja siin on hiljutised arutelud selle kohta, kas "Access on surnud" (arutlejad on üldiselt seisukohal, et ei ole).Nimetan järgnevalt mõningaid MS Accessi eeliseid konkurentide ees. MS Access on töölaua andmebaasisüsteem. Võrreldes "vanemate vendade/õdedega" - serveri andmebaasisüsteemidega (nt PostgreSQL, Oracle erinevad väljaanded, MySQL) - on sellel palju puudujääke. Kuid kas on ka eeliseid? Jah on. Üksiti võttes võivad tunduda väikesed asjad, kuid palju väikeseid asju annab kokku ühe suure. Tabeli veergude järjekorra muutmiseks tabelis tuleb tabeli disainivaates veergu sobivale kohale lohistada. SQL tabelites on veerud vasakult paremale järjestatud. Igal veerul on järjekorranumber. Mõnes olukorras tuleb seda järjekorranumbrit teada. Paraku ei paku SQL  lauset tabeli veergude järjekorra muutmiseks või veeru lisamiseks konkreetsele positsioonile. Seega on teistes süsteemides enamasti lahenduseks tabeli kustutamine ja uuesti loomine. CHECK kitsendustes saab kasutada alampäringuid. Võimaldab realiseerida deklaratiivsel viisil keerukate reeglite kontrolli. See tähendab, et süsteemile öeldakse, mida peab kontrollima, mitte kuidas seda teha. Näiteks PostgeSQL ja Oracle ei luba CHECK kitsendustes alampäringuid ning keerukamate reeglite andmebaasi tasemel jõustamiseks ei jää üle muud kui luua trigereid. Trigerites kirjeldatakse andmete kontrolli protseduur. Koodi on palju rohkem kui deklaratiivsete kitsenduste puhul ning lihtne on teha vigu. Muide, ka MS Accessis on võimalus sisuliselt luua trigereid - selleks tuleb luua andmemakrod. Attachment tüübi kasutamine veeru tüübina, mida saab määrata ainult läbi graafilise kasutajaliidese, võimaldab lihtsalt ja mugavalt realiseerida failide andmebaasis hoidmise. Andmebaasirakenduse kaudu hallatavate failide (näiteks veebipoe kaupade pildid) hoidmine väljapool andmebaasi (andmebaasisüsteemi kontrolli alt väljas) on üks SQL disaini antimustritest - Assume You Must Use Files (Phantom Files) (Chapt 12). Tabeli disainivaates saab valideerimisreeglitega koos määrata valideerimisteksti. Seda näidatakse kasutajale kui tema andmemuudatus eksis selle reegli vastu. Niimoodi on võimalik kerge vaevaga määrata (loodetavasti head ja arusaadavad) veateated, mida kasutajale näidatakse. Paraku ei pöörata veateadete heale kasutatavusele paljude programmide puhul piisavat tähelepanu. Päringute kujundaja (query designer) pakub ka võimalust andmete muutmise lausete (INSERT/UPDATE/DELETE) koostamiseks. SELECT lausete graafilise kasutajaliidese abil koostamise võimalust pakutakse paljudes programmides, kuid andmete muutmise lausete sellise koostamise võimalusega polegi ma muudes programmides kokku puutunud. TOP predikaat, mida saab kasutada ka teistes Microsofti andmebaasisüsteemides, kuid mida ei kirjelda SQL standard, võimaldab mitmeid ülesandeid lihtsamalt lahendada. Näiteks - leia hotellid, milles on toimunud kõige rohkem reserveerimisi (selliseid hotelle võib olla rohkem kui üks). SELECT TOP 1 hotelli_nrFROM ReserveerimineGROUP BY hotelli_nrORDER BY Count(*) DESC; Andmebaasisüsteemiga ühte programmi integreeritud andmebaasirakenduste loomise võimalus on hea näide väikese kodeerimise vajadusega arenduskeskkonnast (low code development environment). See on IT süsteemide arenduse üks oluline tulevikusuund. IT on igal pool ja inimestel on vajadus/soov luua kiiresti endale kõige sobivamat tarkvara. Süsteemiarendus demokratiseerub, st võimalikult paljud peaksid seal saama kaasa lüüa. Näiteks Oracle veebirakenduste kiirprogrammeerimise keskkonnas Apex andmebaasirakenduse loomise kasutajakogemus meenutab väga palju MS Accessi kasutamise kogemust. Vahe on selles, et Apexis on kogu arendusliides veebipõhine ja arenduse tulemusena valmib Oracle andmebaasi kasutav veebirakendus. Võimalus kasutada SQL lausetes parameetreid, mille väärtust küsitakse lõppkasutajalt või loetakse mõnelt ekraanivormilt. Andmebaasirakenduse mugavam muutmine. Muutes tabeli/veeru nime muudetakse paljudel juhtudel automaatselt (siiski küll mitte alati) ka salvestatud SQL lauseid (queries) nii, et need arvestaksid uute nimedega. Paraku alampäringuid ei osata muuta. Muutes tabeli/veeru nime muudetakse paljudel juhtudel automaatselt (siiski küll mitte alati) ka ekraanivorme nii, et need arvestaksid uute nimedega.  Muudetakse just selliseid vorme, mis on seotud tabelitega (bound forms), st mitte selliseid, kus andmete leidmine ja esitamine käib kasutaja kirjutatud VBA koodi kaudu. **Märksõnad:** MSAccess ## Küsimus: Mis probleem tekib MS Accessi andmebaasi kasutamisel universaalse andmebaasi haldamise programmi (nt DBeaver ja DbSchema) kaudu? **Vastus:** Nende vahendite kaudu saab käivitada SQL lauseid, mis on illegaalne SQL, ei ole kooskõlas MS Accessi SQL dialektiga, st lauseid otse andmebaasisüsteemis käivitades need ei toimi. Põhjus saab olla selles, et see programm kui vahendaja kirjutab lauseid enne käivitamist ümber andmebaasisüsteemile sobivaks. See muutub probleemiks, kui  sellise vahenda puudumisel ei oska kasutaja andmebaasisüsteemis toimivat koodi kirjutada.Esitan järgnevalt näiteid.Illegaalse SQLi näideSELECT [oppimine] , tulemusFROM [Oppimine] INNER JOIN [Eksam] ON Oppimine.[oppimine] =Eksam.[oppimine];Veerg oppimine on nii tabelites Oppimine kui Eksam. Veerule viidates ei täpsustata tabelit, milles see veerg sisaldub.Korrektne oleks:SELECT Oppimine.[oppimine] , tulemusFROM [Oppimine] INNER JOIN [Eksam] ON Oppimine.[oppimine] =Eksam.[oppimine];Näited lausetest, mida MS Accessi SQL dialekt ei toeta, kuid mida saan DBeaveris MS Accessi andmebaasi põhjal käivitadaSELECT Count(DISTINCT aine) AS arvFROM [Oppimine];--leian erinevate ainete arvu, mida on vähemalt korra õpitudWITH erinevad AS (SELECT DISTINCT [aine]  FROM [Oppimine])SELECT Count(*) AS arvFROM erinevad;/*ühine tabeli avaldis (Common Table Expression) - deklareerin alampäringu ja siis kasutan*/SELECT *FROM [Oppimine]ORDER BY [oppim_algus] DESC LIMIT 2;SELECT *FROM [Tudeng] INNER JOIN [Oppimine] ON Tudeng.[tudkood] = Oppimine.[tudeng] INNER JOIN [Aine] ON Oppimine.[aine] = Aine.[aine_kood] --ühendamisoperatsioonid pole sulgudesSELECT *FROM [Tudeng] JOIN [Oppimine] ON Tudeng.[tudkood] = Oppimine.[tudeng] JOIN [Aine] ON Oppimine.[aine] = Aine.[aine_kood] --sõna JOIN fraasi INNER JOIN asemelSELECT *FROM [Oppimine] INNER JOIN [Eksam] USING (oppimine);--kompaktsem süntaks ühendamiseks üle samanimeliste veergudeSELECT *FROM [Oppimine] WHERE Extract(YEAR FROM [oppim_algus])=1999;--Extract funktsioon kuupäevast aastaarvu eraldamiseksSELECT *FROM [Oppimine] WHERE [oppim_algus]='1999-09-01'--Kuupäevastring on ülakomade vahelNäited SQL lausetes, mida saab MS Accessis otse käivitadaSELECT Count(aine) AS arvFROM (SELECT DISTINCT [aine]FROM [Oppimine]) AS ap; SELECT *FROM ([Tudeng] INNER JOIN [Oppimine] ON Tudeng.[tudkood] = Oppimine.[tudeng])INNER JOIN [Aine] ON Oppimine.[aine] = Aine.[aine_kood] --sulud ühendamisoperatsioonide ümberSELECT *FROM [Oppimine] WHERE Year([oppim_algus])=1999;--MS Accessis on funktsioon YearSELECT *FROM [Oppimine] WHERE [oppim_algus]=#1999-09-01#; ## Küsimus: Teen MS Accessis currency veeru põhjal näiteks summeerimise või keskmise leidmise päringu. Tulemuses ei ole valuuta tähiseks Eur. Mida teha? **Vastus:** Põhjus on Windowsi regionaalsetes sätetes. Tähis võetakse sealt ning järelikult peitub ka tulemuse põhjus seal. **Märksõnad:** euro ## Küsimus: Võtsime lahti Accessi faili, mida sai kunagi arvutiklassis täiendatud, ning nüüd viskab Error 2950-it (Action name: Set property). Milles on probleem ja kuidas seda lahendada? **Vastus:** Avasite 32-bitises MS Accessis tehtud faili 64-bitises MS Accessis. Kui seda teha, siis võib olla vaja VBA koodi parandada. --- # Teema: Vahendid - muu ## Küsimus: Kas "Andmebaasid I" iseseisvas töös võib rakenduse prototüübi tegemisel kasutada mõnda ORM (Object-Relational Mappers, objekt-relatsioonvastenduse) vahendit. **Vastus:** See pole keelatud. Kuid palun tutvuge ka probleemidega, millest ma kirjutan pikemalt SIIN.NB! "Andmebaasid II" aines pole see ka keelatud, kuid siis tuleb tingimata tagada, et loodud rakendus kasutab andmebaasi läbi avaliku andmebaasi liidese e virtuaalse andmete kihi. Teiste sõnadega peaks rakendus lugema andmeid vaadetest (näiteks Djangos on see võimalik) ning muutma andmeid kasutades andmebaasiserveris talletatud rutiine (näiteks Djangos on see võimalik). Andmete kitsendustele vastavuse kontroll peab toimuma andmebaasi tasemel (kasutades deklaratiivseid kitsendusi ja reegleid), mitte rakenduse tasemel nagu ORM vahendid üldiselt propageerivad. "Andmebaasid I" õppeaines, kus iseseisva töö üheks tulemuseks on rakenduse prototüüp, ei ole avaliku andmebaasi liidese loomine nõutud. Küll aga tuleb ka selles aines kitsendusi maksimaalselt andmebaasi tasemel jõustada. **Märksõnad:** rutiin, funktsioon, protseduur, hetktõmmis, materialiseeritud vaade, virtuaalne andmete kiht, andmebaasi avalik liides ## Küsimus: Kas on võimalik kasutada aines vajalikku tarkvara ilma seda enda arvutisse installeerimata? **Vastus:** Jah, alates 2024. aastast on selleks võimalik kasutada arvutiklasside arvuteid kaugkasutuse korras vastavalt SELLELE juhendile. **Märksõnad:** mac, linux, kaugkasutus, kaugtöölaud, remote desktop, vpn, kaug, kaugtöö ## Küsimus: Kas projekti dokumenti võib teha Githubi Wikis, Google Docs'is või muus sarnases rühmatööd toetavas keskkonnas? **Vastus:** Miks mitte, kuid soovitan ikkagi kaaluda MS Wordi kasutamist, sest seal on mudeli koostajale väga kasulik funktsionaalsus - Split screen. See funktsionaalsus lihtsustab projekti erinevate osade kooskõla kontrollimist. Ükskõik mis vahendit Te dokumendi loomiseks kasutate, siis õppejõud soovib hindamiseks projekti dokumenti sellises formaadis, et seda saab MS Word programmis avada ja "Split screen" abil vaadata. Projekti pealkirjade struktuur PEAB täpselt vastama mallis ette antud struktuurile. See on vajalik, et oleks võimalik lühikese ajaga suur hulk projekte kiiresti läbi vaadata ja sisukat tagasisidet anda. ## Küsimus: Kuidas kasutada PostgreSQLi küsitlustulemuste analüüsimiseks sh vabatekstiliste vastuste analüüsimiseks? **Vastus:** Moraal on selles, et vaba teksti väljas olevate väärtuste analüüsimine nõuab rohkem tööd ning kui andmebaasis oleks vaja registreerida andmeid millegi kohta, et nende andmete alusel saaks hiljem teha otsinguid, siis vabateksti asemel tuleks eelistada rohkem struktureeritud väärtuste salvestamist.Küsitlus Microsoft Forms keskkonnas, kus on viis küsimust: Kui heaks hindate Te 10 palli skaalal oma SQLi oskust (0 üldse ei oska - 10 väga hea)? (vastuseks arv 0-10) Milline on Teie varasem kokkupuude andmebaaside loomisega? (vastus vabatekst) Milliseid andmebaasisüsteeme Te olete oma elus kasutanud? (vastus vabatekst) Milline on Teie varasem kokkupuude andmebaasiakenduste loomisega? (vastus vabatekst) Millised on Teie ootused "Andmebaasid I" õppeaine suhtes? (vastus vabatekst) Laadin alla vastused Exceli failina.Kustutan üleliigsed veerud. Faili jääb viis veergu. Esimene rida on päis, väärtuste eraldaja on ;Jätan alles tabeli päise.Salvestan CSV formaadis. Laen faili Kysitlus.csv serverisse, kus on PostgreSQL, kataloogi tmp.Järgnevad laused käivitan PostgreSQL andmebaasis./*Loon andmebaasis laienduse, et saaksin andmebaasis kasutada andmebaasivälises failis olevaid andmeid.*/CREATE EXTENSION IF NOT EXISTS file_fdw; CREATE SERVER file_fdw_server FOREIGN DATA WRAPPER file_fdw; /*Loon välise tabeli, mille kaudu saan vaadata serverisse laaditud CSV failis olevaid andmeid.Määran, et fail on CSV formaadis, failis on tabelil päis (veergude nimed), näitan faili asukoha, määran kuidas esitatakse jutumärke ningpuuduvaid andmeid ning milline on väärtuste eraldaja.*/ CREATE FOREIGN TABLE kysitlus ( SQL SMALLINT, varasem TEXT, andmebaasisysteemid TEXT, andmebaasirakendused TEXT, ootused TEXT) SERVER file_fdw_server OPTIONS (format 'csv',header 'true', filename '/tmp/Kysitlus.csv', quote '"', delimiter ';', null ''); /*Mediaanväärtuse leidmiseks kasutan andmebaasis kasutaja poolt loodud funktsiooni.*/ SELECT Median(SQL) AS mediaan, Avg(SQL) AS aritmeetiline_keskmine FROM Kysitlus; /*Moodi e kõige sagedamini esineva väärtuse leidmiseks saab kasutada spetsiaalset kokkuvõttefunktsiooni. NB! Kui on mitu ühesugust väärtust, siis valitakse nendest juhuslikult üks.*/ SELECT mode() WITHIN GROUP (ORDER BY SQL) AS mood FROM Kysitlus; /*Erinevate SQL oskuse hinnangute arv.*/ SELECT SQL, Count(*) AS arv FROM Kysitlus GROUP BY SQL ORDER BY SQL;/*Milliseid SQL oskuse hinnanguid ei ole kordagi antud? generate_series funktsioon genereerib antud juhul tabeli,kus on 11 rida ning igas reas on üks täisarv (0-10). Alampäringus peab olema tingimus SQL IS NOT NULL, sest kui küsitluses oleks mõnel juhul SQL oskuse hinnang puudu, siis ilma selle tingimuseta poleks päringu tulemuses kunagi ühtegi rida.WITH klauslis on ühine tabeli avaldis (common table expression), mis võimaldab defineerida alampäringu, anda sellele nime ning seda hiljem lauses kasutada.*/WITH voimalikud AS (SELECT generate_series(0,10) AS hinnang)SELECT hinnangFROM voimalikudWHERE hinnang NOT IN (SELECT SQL FROM KysitlusWHERE SQL IS NOT NULL)ORDER BY hinnang; /*Jagades hinnangud nelja klassi - 0, 1-3, 4-6, rohkem kui 6, siis kui mitu vastajat kuulub igasse klassi ning milline on igasse klassi kuuluvatevastajate protsent kõigi vastajate arvust. Arvestatakse vaid vastuseid, kus SQL hinnang on antud.*/ WITH eeltootle AS (SELECT CASE WHEN SQL=0 THEN 'ei oska midagi' WHEN SQL BETWEEN 1 AND 3 THEN 'oskab vähe' WHEN SQL BETWEEN 4 AND 6 THEN 'oskab keskmiselt' ELSE 'oskab hästi' END AS hinnang FROM Kysitlus WHERE SQL IS NOT NULL) SELECT hinnang, Count(*) AS arv, Round(Count(*)*100/(SELECT Count(*) FROM eeltootle),1) AS protsent FROM eeltootle GROUP BY hinnang ORDER BY arv DESC; /*Milline on andmebaasisüsteemide populaarsus e mainimise sagedus? Lause töötleb vabatekstilisi vastuseid.Alampäringud:eemalda - esitatakse tabel sõnadega (iga sõna eraldi reas), mida analüüsis ei arvestata.eeltootle - tekstis muudetakse kõik tähed väiketähtedeks (lower funktsioon), fraas "sql server" asendatakse "sqlserver" (replace funktsioon) ning tekstist kustutatakse eraldajateks olevad sümbolid (punktid, komad, semikoolonid) (trasnslate funktsioon - etteantud sümbolid asendatakse mitte millegagi).tykelda - tekst jaotatakse sõnadeks arvestusega, et eraldajaks on tühikud, ning luuakse tabel, kus iga sõna on eraldi reas.puhasta - CASE avaldisega koondatakse erinevad samale andmebaasisüsteemile viitavad sõnad üheks sõnaks ning eemaldatakse analüüsis mittearvestatavad sõnad.Kõige lõpuks leitakse andmebaasisüsteemide mainimiste arv ning tulemus sorteeritakse arvu järgi kahanevalt.*/ WITH eemalda AS (VALUES ('ja'),('ning'),('ei'),('pole'),('-'),('on'),('ole'),('kasutanud'),('ka'),('töötan'),('kasutan')), eeltootle AS (SELECT translate(replace(lower(andmebaasisysteemid),'sql server','sqlserver'),',.;','') AS andmebaasisysteemid FROM kysitlus), tykelda AS (SELECT regexp_split_to_table(andmebaasisysteemid, ' ') AS andmebaasisysteemid FROM eeltootle), puhasta AS (SELECT CASE WHEN andmebaasisysteemid IN ('postgres','postgre','postgressql') THEN 'postgresql'  WHEN andmebaasisysteemid IN ('ms','microsoft') THEN 'microsoft' WHEN andmebaasisysteemid IN ('msaccess','access') THEN 'access' ELSE andmebaasisysteemid END AS andmebaasisysteemid FROM tykelda WHERE andmebaasisysteemid NOT IN (SELECT column1 FROM eemalda)) SELECT andmebaasisysteemid, Count(*) AS arv FROM puhasta WHERE andmebaasisysteemid<>'' GROUP BY andmebaasisysteemid ORDER BY arv DESC; /*Kuna andmebaasisüsteemide nimed võivad olla pandud kirja ebatäpselt või samale andmebaasisüsteemile viidatakse sõnaga, kus on mõni täht erinevust (nt postgresql vs postgresqli), siis saab kasutada lauset, kus antakse ette kõige populaarsemate andmebaasisüsteemide nimed ning leitakse vastusest eraldatud sõnade Levenshteini kaugus nende andmebaasisüsteemide nimedest. Kui see kaugus on piisavalt väike, siis järelikult sõna viitab sellele andmebaasisüsteemile. Levenshteini kaugus kahe sõne vahel näitab ühemärgiliste muudatuste arvu, mida tuleb teha, et jõuda ühest sõnest teisini. Levenshteini kauguse arvutamise funktsioonid sisaldavad PostgreSQLi laienduses fuzzystrmatch. Enne lõpliku tulemuse leidmist tuleb vastuses esitatud sõnadest eemaldada sõnad, mis ei esita andmebaasisüsteemide nimesid, kuid mille Levenshteini kaugus mõne andmebaasisüsteemi nimest on väike. Levenshteini kauguse alusel sõnade võrdlemine on näide hägusast otsingust (fuzzy search).Hägus otsing tuvastas PostgreSQLina ka sõnad: progresql, postgressql, posrtgresql*/CREATE EXTENSION IF NOT EXISTS fuzzystrmatch;WITH eemaldatavad AS (VALUES ('ms'),('nosql'),('sql'),('sqli'),('ole'),('on'),('ole'),('ei'),('rollis')),populaarseimad AS (VALUES ('postgresql'),('mysql'),('access'),('oracle'),('sqlite'),('sqlserver'),('vertica'),('mongodb'),('redis'),('mariadb')),eeltootle AS (SELECT translate(replace(lower(andmebaasisysteemid),'sql server','sqlserver'),'-,.;','') AS andmebaasisysteemidFROM kysitlus),tykelda AS (SELECT regexp_split_to_table(andmebaasisysteemid, ' ') AS andmebaasisysteemidFROM eeltootle),eemalda AS (SELECT andmebaasisysteemidFROM tykeldaWHERE andmebaasisysteemid NOT IN (SELECT column1FROM eemaldatavad))SELECT populaarseimad.column1 AS andmebaasisysteem, Count(*) AS arvFROM populaarseimad, eemaldaWHERE levenshtein_less_equal(eemalda.andmebaasisysteemid, populaarseimad.column1,3)<=3GROUP BY andmebaasisysteemORDER BY arv DESC; /*Millised on kõige sagedasemad varasema andmebaaside loomise kogemuse iseloomustamiseks kasutatavad sõnad?Eemaldatakse stoppsõnad ning esitatakse vaid sõnad, mida esitatakse rohkem kui üks kord.*/ WITH eemalda AS (VALUES ('ja'),('ning'),('või'), ('-'),('ka'),('et')), eeltootle AS (SELECT translate(lower(varasem),',.-','') AS varasem FROM kysitlus), tykelda AS (SELECT regexp_split_to_table(varasem, ' ') AS varasem FROM eeltootle), puhasta AS (SELECT varasem FROM tykelda WHERE varasem NOT IN (SELECT column1 FROM eemalda)) SELECT varasem, Count(*) AS arv FROM puhasta WHERE varasem<>'' GROUP BY varasem HAVING Count(*)>1 ORDER BY arv DESC; /*Millised on kõige sagedasemad varasema andmebaasirakenduste loomisega kokkupuute iseloomustamiseks kasutatavad sõnad?Eemaldatakse stoppsõnad ning esitatakse vaid sõnad, mida esitatakse rohkem kui üks kord.*/ WITH eemalda AS (VALUES ('ja'),('ning'),('või'), ('-'),('ka'),('et')), eeltootle AS (SELECT translate(lower(andmebaasirakendused),',.-','') AS varasem FROM kysitlus), tykelda AS (SELECT regexp_split_to_table(varasem, ' ') AS varasem FROM eeltootle), puhasta AS (SELECT varasem FROM tykelda WHERE varasem NOT IN (SELECT column1 FROM eemalda)) SELECT varasem, Count(*) AS arv FROM puhasta WHERE varasem<>'' GROUP BY varasem HAVING Count(*)>1 ORDER BY arv DESC; /*Millised on kõige ootuste iseloomustamiseks kasutatavad sõnad?Eemaldatakse stoppsõnad ning esitatakse vaid sõnad, mida esitatakse rohkem kui üks kord.*/ WITH eemalda AS (VALUES ('ja'),('ning'),('või'), ('-'),('ka'),('et')), eeltootle AS (SELECT translate(lower(ootused),',.-','') AS ootused FROM kysitlus), tykelda AS (SELECT regexp_split_to_table(ootused, ' ') AS ootused FROM eeltootle), puhasta AS (SELECT ootused FROM tykelda WHERE ootused NOT IN (SELECT column1 FROM eemalda)) SELECT ootused, Count(*) AS arv FROM puhasta WHERE ootused<>'' GROUP BY ootused HAVING Count(*)>1 ORDER BY arv DESC;Tulemuse, kus on sõnad ja nende kaalud (näiteks esinemiste arv), saab anda sisendiks tasuta veebipõhisele sõnapilve koostamise tarkvale nagu näiteks SEE. Sinna saab anda sisendi CSV formaadis ning PostgreSQLis olevaid andmeid saab CSV formaadis eksportida näiteks COPY TO lausega. Sellised vahendid võimaldavad sisendiks võtta ka lihtsalt teksti, kuid taolise päringu tulemusel sisendi leidmine on kasulik seetõttu, et selle abil saab eemaldada just eesti keele stoppsõnu. **Märksõnad:** tekstikaeve, vabatekst, hägus otsing Levenshteini kaugus ## Küsimus: Kuidas on seotud andmebaasid ja tehisaru (AI)? **Vastus:** Andmebaasisüteemid on seotud tehisaruga erinevates aspektides. Treeningandmed võivad tulla andmebaasist. Mingisugune osa tehisaru süsteemidest saab olla realiseeritud andmebaasisüsteemi vahendeid kasutades – mitte andmed ei tule realisatsiooni juurde, vaid realisatsioon tuleb andmete juurde. Süsteem tuleb ise realiseerida, kasutades pakutavaid andmetüüpe, luues rutiine. Süsteemi loomiseks saab kasutada valmis komponente. Andmebaasisüsteem kasutab oma sisemise toimimise korraldamiseks tehisaru. See on võimalik isejuhtivate andmebaasisüsteemide puhul. Andmebaasiga seotud ülesannete lahendamiseks kasutatakse tehisaru.   Miks andmebaasis?   Miks realiseerida tehisaru süsteeme kasutades andmebaasisüsteemide pakutavaid võimalusi? Momijan (2024) põhjendab seda sellega, et tehisaru süsteemid nõuavad palju andmeid ning efektiivsem on tuua algoritmid andmete juurde, selle asemel, et viia andmeid algoritmide juurde. Eeliseks on, et andmetele juurdepääs on lihtne ja kiire ning arvesse saab võtta kõige värskemaid andmeid. Jääb ära ajakulu andmete ülekandmisele andmebaasist rakenduse juurde. Kuna andmeid ei pea liigutama üle võrgu, siis on andmete turvalisus ja andmesubjektide privaatsus paremini tagatud. Kuna väheneb kasutatavate serverite hulk, siis on ka süsteemi tehniline arhitektuur lihtsam.   Tehisaru‑põhistel süsteemidel võib olla abi erinevatest andmebaasisüsteemides realiseeriseeritud võimalustest nagu näiteks tehingute haldus, andmete samaaegse kasutamise võimalus erinevate kasutajate poolt, varundamine ning taastamine, keerukad andmetüübid, täistekstotsing ning erinevat tüüpi indeksid.    Andmebaasist andmete lugemisel saab kasutada kõiki andmekäitluskeele võimalusi. Samuti on abiks andmete maskimise (PostgreSQL, Oracle) ja anonümiseerimise võimalused.      Retrieval Augmented Generation   Lugemisega täiendatud genereerimine (Retrieval-Augmented Generation, RAG) on suurte keelemudelite kasutatav tehnika, mille korral enne kasutaja küsimusele inimkeelse vastuse genereerimist otsitakse andmeid välistest allikatest nagu dokumendid, veebilehed ja andmebaasid. Nii parandatakse vastuse täpsust ja olulisust ning vähendatakse hallutsioneerimist (e jama ajamist). Süsteem otsib kasutaja päringule vastamiseks välistest allikatest vastuse jaoks olulist sisendit. Leitud sisend ühendatakse kasutaja promptiga (küsimusega), et anda keelemudelile vastuse genereerimiseks täpsemat konteksti. Niimoodi moodustatud uus prompt antakse sisendiks teksti genereerimisele. Selline lähenemine võimaldab  võtta arvesse värskeimat infot, ilma, et peaks keelemudeleid uuesti treenima.    RAG süsteemi osaks võiks olla andmebaas, kus on dokumendid (tekst, pildid, videod) ning iga dokumendiga on seotud n‑mõõtmeline vektor (embedding), mis seda dokumenti iseloomustab. Sõltuvalt kasutatavast mudelist võib n olla mitusada või isegi mitu tuhat. Üldiselt, mida suurem n, seda täpsem tulemus. Vektorite moodustamiseks kasutatakse transformerit, mis teisendab muutuva pikkusega sisendi fikseeritud pikkusega vektoriks. Loodud vektor on hulk ujukomaarve, mis ei ütle inimkasutajale midagi.  Oracle OCI nimetab sellist andmebaasi vektorandmebaasiks. Etteantud andmete alusel vektori arvutamise teenust pakuvad erinevad tehisaru arendavad ettevõtted. Nende vektorite omavaheline võrdlemine leiab väärtuste semantilist sarnasuse – mida sarnasemad väärtused, seda sarnasemad vektorid. Seda saab kasutada otsinguks, klasterdamiseks, soovitamiseks, anomaaliate tuvastamiseks, mitmekesisuse mõõtmiseks ja klassifitseerimiseks.    RAG süsteem võtab kasutaja päringu, laseb selle põhjal (mõnel välisel teenusel) arvutada vektori, leiab selle vektori alusel oma andmebaasist päringule kõige sarnasemad (päringu jaoks kõige olulisemad) dokumendid, lisab need kasutaja päringule ning algatab selle alusel vastuse genereerimise. Kuna andmebaasisüsteemi poolt vektori ükshaaval kõigi ülejäänud vektoritega võrdlemine kõige lähedasemate vastete leidmiseks võib võtta liiga palju aega, siis kasutatakse ka optimeeritud algoritme, mis leiavad "piisavalt lühikese ajaga“ "piisavalt hea vastuse". Nende algoritmide kasutamise eelduseks on, et andmebaasis on vektoritele loodud spetsiaalne indeks.RAGi kasutava süsteemi näiteks on teadusartiklite kokkuvõtete andmebaas Scopus, mille tehisaru‑põhine funktsionaalsus (Scopus AI) võimaldab kasutajal esitada inimkeeles küsimusi, millele genereeritakse teadusartiklite põhjal neid kokkuvõttev vastus. Selles kokkuvõttes on viited allikatele, mille põhjal vastus koostati. Graph Retrieval Augmented Generation   Valdkonna teadmiste graafis (knowledge graph) esitatakse valdkonna mõisted ja nende vahelised seosed – mõisted on graafi tipud ja mõistete seosed on graafi kaared. Rathle (2024) argumenteerib selle poolt, et vektorid ei pruugi olla päringule vastava konteksti otsimisel piisavad ning lisaks vektoritele võiks otsida sobivaid seotud dokumente ka teadmiste graafi (knowledge graph) kasutades. Sellist lähenemist võiks nimetada GraphRAG - graafi lugemisega täiendatud genereerimine. Rathle (2024) märgib, et stringide e sõnede (strings) töötlemise asemel on parema tulemuse jaoks vaja töödelda asju (things) ning graaf on viis kuidas "asju" kirjeldada.   Autori hinnangul oleks graafipõhised andmebaasid sellise süsteemi loomiseks justkui loodud. Programm moodustaks valdkonna kohta konteksti pakkuvate dokumentide alusel teadmiste graafi, mis salvestatakse graafipõhisesse andmebaasi. Sinna salvestatakse ka dokumente iseloomustavad vektorid. GraphRAG süsteem kasutaks seda andmebaasi, et anda suurele keelemudelile ette kasutaja päringule vastamiseks vajalikku kontekstteavet. Teadmiste graaf on kombinatsioon leksikaalsest graafist ja valdkonna graafist. Leksikaalne graaf esitab dokumendi struktuuri elemente ja nende seoseid ning selle koostamine on lihtne. Valdkonna graaf esitab dokumendi käsitletavas sisus esinevaid mõisteid ja nende seoseid. Neo4j (graafipõhine andmebaasisüsteem) pakub selleks tööriista Neo4j Knowledge Graph Builder. SQL‑andmebaasis olevate struktureeritud andmete importimiseks saab kasutada Neo4j Data Importer töövahendit.   Rathle (2024) toob välja GraphRAG erinevaid eelised ainult vektoreid kasutava RAGi ees. Teadmiste graafide sellisel viisil kasutamine võimaldab anda kasutajate päringutele täpsemaid, täielikumaid ja seega ka kasulikumaid vastuseid. Rathle viitab erinevatele uuringutele, mis seda väidet kinnitavad.  Graaf on arusaadav nii inimesele kui masinale. Süsteemi kasutaja saab uurida dokumentide alusel moodustatud graafi ning saab selle kaudu ette parema pildi andmetest ja oskab seega ka süsteemi antavaid vastuseid teistele paremini selgitada.  Dokumentide vektorite uurimine (iga vektor on suur hulk ujukomaarve) sellist pilti kindlasti ei anna.  Graafis olevate viitade kaudu saab liikuda tagasi vigade algpõhjusteni.  Graafi andmebaasis jagatavate õiguste kaudu (milliste tippude ja kaarte andmeid on konkreetsel kasutajal lubatud lugeda) saab reguleerida seda, milline info antakse suurele keelemudelile sisendiks. Juurdepääs andmetele sõltub kasutaja rollist. Näiteks, kui päringu teeb arsti rollis kasutaja, siis  keelemudeli sisendiks lähevad ka patsiendi diagnoosi andmed, kuid kui päringu teeb klienditeenindaja, siis ei lähe.   Kokkuvõttes saab öelda, et Neo4j pakub graafiliste kasutajaliideste kaudu võimaluse dokumentide või SQL‑andmebaasides olevate andmete importimiseks, nende põhjal graafi genereerimiseks ning siis graafi vaatamiseks. See on kasulik funktsionaalsus isegi siis, kui ei hakata GraphRAG süsteemi realiseerima.   Andmebaasisüsteemide võimalusi   Andmebaasisüsteemid pakuvad vahendeid tehisaru kasutavate süsteemide, sh RAG süsteemide, hõlpsamaks realiseerimiseks.  Leidub spetsiifiliselt vektorite haldamiseks mõeldud andmebaasisüsteeme, kuid ka  olemasolevaid üldotstarbelisi andmebaasisüsteeme saab selleks otstarbeks kohandada. Näiteks võivad SQL‑andmebaasisüsteemid pakkuda vektori andmetüüpi, mida saab kasutada tabeli veeru tüübina. PostgreSQLis tuleb selle kasutuselevõtuks installeerida laiendus pgvector (Jelinek, 2024). Seda tüüpi veergudele saab otsingute kiirendamiseks luua spetsiaalsed indeksid.  Oracles on oodata sellise tüübi lisandumist versiooni 23.4ai (Curtis, 2024). Näiteks OpenAI pakub rakendusliidest, et arvutada tekstilise väärtuse põhjal välja seda iseloomustav n‑mõõtmeline vektor. Jelinek (2024) esitab koodinäite, kuidas neid vektoreid PostgreSQL andmebaasi laadida. Sewrathan et al. (2024) kirjutab veel kahest PostgreSQL laiendusest – pgai ja pgvectorscale. pgvectorscale parandab võrreldes laiendusega pgvector vektorite kasutamise jõudlust ning skaleeritavust. pgvector on kirjutatud C ja pgvectorscale on kirjutatud Rust keeles. pgvectorscale lisab StreamingDiskANN tüüpi indeksi. pgai muudab vektorite kasutamisel põhinevate süsteemide loomise lihtsamaks. Esimeses versioonis saab OpenAI poolt arvutatavaid vektoreid laadida otse andmebaasis, ilma, et peaks selle jaoks kirjutama eraldi andmebaasivälise programmi. Samuti saab otse andmebaasist kasutada OpenAI Chat Completion rakendusliidest, mis on mõeldud vestlusrobotite ning virtuaalsete assistentide loomiseks. Momijan (2024) demonstreerib PostgreSQLi põhjal masinõppe algoritmi realiseerimist. Treeningandmete ja kaalude registreerimiseks luuakse tabelid. Masinõppe algoritmi realiseerimiseks luuakse funktsioone (plperl protseduurses keeles), mida kasutatakse päringutes.   Näiteks selle kohta, kuidas andmebaasisüsteemi on sisseehitatud tehisaru süsteemide loomiseks vajalikud võimalused, on Oracle viimastesse põlvkondadesse lisandunud masinõppe tugi (In-database machine learning).    Veel üheks näiteks on Oracle 23ai lisandunud Select AI funktsionaalsus (Gubar, 2023 ja 2024), mis võimaldab esitada Oracle Autonomous Database pilvepõhise andmebaasi suhtes päringuid kasutades loomulikku keelt (inimkeelt), kusjuures võib ka kasutada teisi keeli kui inglise keel. Süsteem kasutab suurt keelemudelit, mis moodustab kasutaja inimkeelse päringu põhjal SQL lause. Süsteemiga saab pidada vestlust (esitada jätkuküsimusi), mis tähendab, et süsteem oskab arvestada eelnevalt küsitud küsimustega. Muutmaks vestlussüsteemide loomine arendajatele võimalikult lihtsaks on täiendatud SQL keelt. Päringu vastus on SQL tabel. Oracle SQL toetab nüüd lauset kujul.   SELECT AI [täpsustus, mida tagastada] Inimkeelne küsimus;   Näide:   SELECT AI  Millised on 5 kõige suurema ostude arvuga kaupa, mis tulid turule peale 2020. aastat;   [täpsustus, mida tagastada] chat – ära küsi andmeid andmebaasist, vaid lase suurel keelemudelil vastus genereerida. narrate – genereeri andmete põhjal sõnaline vastus. showsql – näita genereeritud SQL lauset. runsql – käivita genereeritud SQL lause (vaikimisi).   Sellist SQL lauset võib näiteks käivitada SQL Developeris või luua selle põhjal  Oracle APEX veebirakendus.   Süsteem on loodud sellisena, et toetada erinevaid suuri keelemudeleid ning kasutaja saab valida, millist nendest kasutada.   Funktsionaalsuse kasutamiseks tuleb paketis DBMS_CLOUD_AI oleva protseduuri create_profile abil kirjeldada profiil, kus määratakse ära AI pakkuja, suur keelemudel ning see, kas peetakse vestlust. Profiili rakendamiseks sessiooni käigus tuleb käivitada paketis DBMS_CLOUD_AI olev protseduur set_profile.   PostgreSQLi maailmas on näiteks avatud lähtekoodiga pgml laiendus, mille andmebaasi lisamisel tekivad sinna erinevaid tehisaru aspekte realiseerivad funktsioonid. See on osa tasulisest pilvepõhisest PostgresML platvormist, mis põhineb PostgreSQL andmebaasisüsteemil. PostgresML realiseerib andmebaasisisese masinõppe (In-database machine learning).   pgml lisatavad funktsioonid võimaldavad teha masinõpet ja kasutada suuri keelemudeleid. Suurte keelemudelitega seotud funktsioonid: chunk – dokumendi tükeldamine osadeks. embed – vektori genereerimine etteantud teksti alusel. transform – teksti genereerimine suure keelemudeli poolt. Integratsioon HuggingFace keskkonnaga, et sealt mudeleid alla laadida. See keskkond pakub suure hulga eeltreenitud mudeleid. transform_stream – teksti genereerimine suure keelemudeli poolt ning tulemuse väljastamine voogedastusena, portsude kaupa. tune – peenhäälestamine.   Masinõppega seotud funktsioonid: train – mudeli treenimine (mudeli saab luua erinevate regressiooni, klassifitseerimise ja klasterdamise algoritmide abil). predict – ennustamine (kasutamine). deploy – rakendamine. load_dataset – andmete laadimine.   Teiste sõnadega ei pea masinõppeks või teksti genereerimiseks andmeid kuhugi liigutama ning selle algatamiseks piisab SELECT lausete käivitamisest.   Tehisaru andmebaasisüsteemi teenistuses   Tehisaru kasutamine andmebaasisüsteemi enese ülesannete täitmiseks on kasutusel ise hakkamasaavate andmebaasisüsteemide korral nagu Oracle Autonomous Database. Selline süsteem võiks õppida (kasutada masinõpet) süsteemi toimimise põhjal. Scopus AI genereeritud kokkuvõtte kohaselt võivad sellised süsteemid kasutada masinõpet erinevate ülesannete jaoks. Töökoormuse prognoosimine: masinõppe mudelid ennustavad tulevast töökoormust, võimaldades andmebaasisüsteemil ressursside kasutust ettevalmistada ja optimeerida. Käitumise modelleerimine: masinõpet kasutatakse, et ennustada süsteemi käitumist eri konfiguratsioonide ja töökoormuste korral. See aitab hinnata võimalike muudatuste mõju ilma neid otseselt läbi tegemata (läbitegemine võib olla kallis). Meetmete planeerimine: masinõppe algoritmid otsustavad mineviku tulemuslikkuse andmete ja prognoositud tulemuste põhjal, millised on parimad tegevused näiteks indeksite valiku ja päringute optimeerimise juures. Konfiguratsiooni häälestamine: masinõpet kasutatakse süsteemi juhtparameetrite väärtuste iseseisvaks muutmiseks. Enesekontroll ja diagnoosimine: masinõpet kasutatakse süsteemi jõudluse jälgimiseks, kõrvalekallete tuvastamiseks ja probleemide automaatseks diagnoosimiseks, tagamaks süsteemi tõhususe ning stabiilsuse.   Geneetiline algoritm on Darwini evolutsiooniteoorial ja loomulikul valikul põhinev optimeerimismeetod. Seda kasutatakse selliste probleemide lahendamiseks, kus optimaalset lahendust ei ole tavapäraste meetoditega lihtne leida. Geneetilisi algoritme peetakse tehisaru algoritmideks. PostgreSQL kasutab geneetilist algoritmi kõige sobivama tabelite ühendamise järjekorra leidmiseks, selleks, et suure hulga tabelite ühendamisel ei peaks kõikvõimalikke erinevaid ühendamise järjekordi läbi kaaluma. Kandidaatide (ühendamise järjekordade) sobivuse hindamiseks arvutatakse ühendamise maksumus. "Geneetiline algoritm heidab kõrvale kõige vähem sobivad kandidaadid. Seejärel luuakse uued kandidaadid, kombineerides sobivamate kandidaatide geene – st  kasutades juhuslikult valitud osi teadaolevatest madala kuluga ühendamisjärjestustest, et luua uusi järjestusi, mida saab kaaluda. Seda protsessi korratakse, kuni on kaalutud etteantud arv ühendamisjärjestusi; seejärel kasutatakse otsingu käigus leitud parimat järjestust lõpliku plaani koostamiseks." (PostgreSQL)Andmebaasiga seotud ülesannete lahendamineNäiteid Teksti alusel SQL lause genereerimine SQL lause alusel selle kirjelduse genereerimine **Märksõnad:** tehisintellekt, artificial intelligence, machine learning, masinõpe, ML, transformer ## Küsimus: Kuidas saada juurdepääs Microsoft's Azure Dev Tools for Teaching keskkonnale? **Vastus:** Tallinna Tehnikaülikooli üliõpilastel on juurdepääs Azure Dev Tools for Teaching keskkonnale, kust nad saavad allalaadida mitmesugust Microsofti arendustarkvara, sh MS SQL Server andmebaasisüsteem. Selle keskkonna varasem nimi oli Microsoft Imagine. NB! Varem ülikooli kaudu saadud Microsoft Imagine kontod enam ei toimi. Tuleb teha uus konto järgneva juhendi alusel. Tehke endale Microsofti juures (uus) konto, kus Te ei kasuta @ttu.ee ja @taltech.ee laiendiga meiliaadressi. Konto loomiseks minge: https://signup.live.com. Konto tegemise käigus saate sisestatud meiliaadressile kirja, kus on kinnituskood, mille peate konto tegemise lõpetamiseks sisestama. Kui Teil on varasemast selline konto, siis uut pole vaja teha. Sisenege loodud konto abil: https://azureforeducation.microsoft.com/devtools Sisselogimise järel palutakse Teil kinnitada enda seos ülikooliga, sisestades enda ülikooli meiliaadress (@taltech.ee). Saate enda ülikooli meiliaadressile kirja, kus peate kinnitamiseks klõpsama lingil. Selle kirja lugemiseks minge: https://mail.taltech.ee Kiri tuleb aadressilt maccount@microsoft.com ning algab niimoodi nagu on näidatud teatele lisatud failis. Minge aadressile: https://azureforeducation.microsoft.com/devtools ja logige oma uue kontoga sisse. Tarkvara saab allalaadida valikust Software. Juurdepääs keskkonnale peaks kehtima seni, kuni ülikool maksab litsentsid ja kuni inimene on ülikooliga seotud. **Märksõnad:** Microsoft Azure, Microsoft Imagine, MS SQL Server ## Küsimus: Kuna avastasime, et meie grupil juhtus kodutöö versioonidega mingi viga ja kuhugi kadus parandatud kitsendustega versioon, siis hakkasin hiljem mõtlema, et kuidas edaspidi selliseid vigu vältida. Kas meie kodutöö raames on võimalik versioonihaldamiseks mingit versioonihalduse tarkvara kasutada, nt GitHub vms? **Vastus:** See ei ole kohustuslik, kuid on täiesti võimalik ja minu arvates hea mõte.Tallinna Tehnikaülikooli informaatika õppekavade üliõpilased kasutavad paljudes oma õppekava ainetes GitLabi ning seda kasutatakse ka bakalaureusetöö tegemisel. See on kättesaadav kõigile üliõpilastele, sest sisselogimine on Uni-IDga. Avaleht: https://gitlab.cs.ttu.ee/Alustamise juhend: https://pydoc.pages.taltech.ee/setup/git_ttu.htmlProjektihaldus GitLabis: https://projectdoc.pages.taltech.ee/Tean, et mitmed minu juhendatud üliõpilased on seda kasutanud nii lõputööde kui ka aineprojektide jaoks. Küsimuses mainitud GitHub sobiks muidugi samuti. **Märksõnad:** GitHub, GitLab, Git ## Küsimus: Kus relatsioonilist mudelit peale andmebaaside veel kasutatakse? **Vastus:** Relatsiooniline mudel kirjeldab ühte võimalikku viisi, kuidas andmeid andmebaasides organiseerida ning kuidas neid seal kasutada saab ja seega on relatsioonilise mudeli rakendusvaldkonnaks ikkagi andmebaasid.Samas on see mudel, selle väljatöötamine ja selle põhjal loodud andmebaasikeeled andnud kindlasti inspiratsiooni erinevateks teadus- ja arendustöödeks. Andmemudelite ajalugu algas enne relatsioonilist mudelit, kuid koos relatsioonilise mudeliga saadi aru vajadusest selliste mudelite kirjeldus ka ilmutatult kirja panna. Siin on hea näide, kuidas seda lühidalt ja selgelt teha. Kui mudel on ilmutatult kirja pandud, siis on seda võimalik palju paremini analüüsida ning järjekindlamalt ja täpsemalt realiseerida. Andmestruktuuride normaliseerimise teooria (see on väga läbitöötatud relatsioonilise andmemudeli korral kuid rakendub ka teistele andmemudelitele) on andnud inspiratsiooni normaliseerimise teooria väljatöötamiseks programmikoodi kohta ja laiemalt üldse mistahes liiki süsteemide kohta (normaliseeritud süsteemide teooria - lugege pikemalt siit, peatükist 6). Relatsiooniline mudel ja andmetüübid on ortogonaalsed, st relatsiooniline mudel seab väga vähe nõudeid/piiranguid tüüpidele, mida saab kasutada relatsioonilises andmebaasis näiteks atribuutide või parameetrit tüüpidena. Tüüpide loomise keerukus SQLis on pannud mõtlema, milline võiks olla sobiv andmetüüpide süsteem ja kuidas oleks õige tüüpe pärimise kaudu luua. Eesmärgiks oleks süsteem, kus rakenduse ja andmebaasisüsteemi vahel ei oleks nii põhimõttelisi erinevusi, et nende koostööle sundimiseks oleks vaja mingit ORM-i laadset vahekihti. Relatsioonilise mudeli põhjal loodud reaalne andmebaasikeel - SQL - on vaatamata oma puudustele inspiratsiooniks paljudele uue põlvkonna (NoSQL) andmebaasisüsteemidele deklaratiivse andmebaasikeele väljatöötamise seisukohast. Näiteid: CQL N1QL SPARQL PGQL ## Küsimus: Kust saab infot PostgreSQLis kasutusel oleva SQL mägimurraku e dialekti kohta? **Vastus:** Andmekäitluskeele lausete osas (SELECT, INSERT, UPDATE, DELETE, MERGE) soovitan vaadata seda slaidikomplekti. Seal on lisaks võrdluseks välja toodud, kuidas selliseid ülesandeid saaks lahendada Oracles. Slaidikomplekt keskendub lausekonstruktsioonidele, mida MS Access ei paku.SQL koodi, mida saab käivitada MS Accessis, saab 99%-l juhtudest muudatusteta või pisimuudatustega käivitada ka PostgreSQLis. Kuid PostgreSQL (ja Oracle ja teised serveri andmebaasisüsteemid) pakuvad lisaks täiendavalt veel suure hulga keelekonstruktsioone. Nii et näiteks kui MS Accessis saaks ülesande lahendamiseks kirjutada 5 erinevat SQL lauset, siis PostgreSQLis 10+ erinevat lauset.Internetis leiab keskkondi, mis pakuvad võimaluse veebilehitseja vahendusel lahendada erinevaid PostgreSQL kasutamise ülesandeid - vt SEE ja SEE. ## Küsimus: Kust saada infot andmebaasisüsteemi PostgreSQL kasutamise kohta? **Vastus:** (kasutajanimi: SIS2 ja parool: SIS2) SIIN on "Andmebaasid II" kodulehel olevad slaidid, mille teises osas räägitakse programmidest psql, pgAdmin ja phpPgAdmin, mille kaudu on võimalik andmebaasisüsteemiga suhelda. Samuti tuuakse näiteid PostgreSQLis võimalike SQL lausete ja PostgreSQL kasutamiseks mõeldud programmide funktsionaalsuste kohta. psql on serveris olev käsurea põhine programm. pgAdmin on kasutaja arvutis asuv graafilist kasutajaliidest pakkuv programm ning phpPgAdmin on veebipõhine graafilist kasutajaliidest pakkuv programm.SIIN on eelnevaga sarnast infot pakkuv materjal dokumendi kujul. PostgreSQLile on pühendatud selle esimene peatükk.SIIN on Sharepointi keskkonnas olevad videod PostgreSQL kasutamise kohta. Osad nendest on hääletud ekraanivideod, kuid on ka pikemaid häälega videoid sh "Andmebaasid II" neljanda praktikumi lindistus, kus rääkisin PostgreSQLi kasutamisest (psql'i kaudu).Programme, mille kaudu töötada PostgreSQL andmebaasiga (hallata andmebaasi, käivitada päringuid) on väga palju. Nende hulka kuuluvad ka universaalsed programmid nagu näiteks DBeaver ja DbSchema, mille abil saaks kasutada paljude erinevate andmebaasisüsteemide abil loodud andmebaase. SIIN on nende kasutamis kohta video.Mis puudutab seda, mida head saab PostgreSQLis teha, siis "Andmebaasid I" õppeaine seisukohalt pakuvad esmajärjekorras huvi andmekäitluskeele laused (andmete otsimise ja muutmise laused). Nende võimaluste kohta on väga mahukas slaidikomplekt SIIN. Seal on nii PostgreSQL kui Oracle koodinäited ja keskendutakse SQLi võimalustele, mida lihtsamad ja ainult põhivõimekusi pakkuvad süsteemid nagu MS Access ei paku. Mis puudutab erinevaid andmebaasiobjekte, mida PostgreSQLis saab luua (baastabelid, vaated, domeenid, arvujada generaatorid, rutiinid, trigerid, jne), siis SIIN on nende kohta mahukad slaidikomplektid koos suure hulga koodinäidetega. Kõigis nendes räägitakse võrdlevalt nii PostgreSQList kui Oraclest.SIIN on ingliskeelne materjal PostgreSQL ja MS Access SQL mägimurraku erinevuste kohta. SIIN on näidete katsetamiseks mõeldud MS Access andmebaas ja SIIN on PostgreSQL kood selle andmebaasi loomiseks. PostgreSQL lauseid saaks katsetada näiteks DbFiddle keskkonnas.SIIN saab PostgreSQLi puudutavaid SQL ülesandeid onlainis lahendada. ## Küsimus: Mida teha, kui Horizoni virtuaalne töölaud ei tööta? **Vastus:** Võtke ise otse ühendust IT-kasutajatoega ja andke neile probleemist teada. See on IT-osakonna pakutav teenus ja õppejõud seda taaskäivitada ei saa. Muide, IT-teadukonna ja IT-osakonna nägemuses pole arvutiklassides arvuteid vaja, sest üliõpilased peaksid käima kohal oma arvutiga. Nende nägemuses on virtuaalne töölaud just see vahend, mis võimaldab üliõpilastel kasutada oma arvutis tarkvara, mida nad mingil põhjusel ei saa sinna ise installeerida. Seega on väga oluline, et nad oleksid operatiivselt kõigi selle töölaua probleemidega kursis.Kui virtuaalne töölaud Andmebaasid ei ole ajutiselt kättesaadav, siis kasutage töölauda ICT-Class. Ka seal on MS Access, Enterprise Architect ja Rational Rose.Samuti võib proovida arvutiklasside kaugkasutust. Juhendi leiab SIIT - kerige kõige lõppu. Juhendi kohaselt saab seda lahendust kasutada nii MacOs kui Linux operatsioonisüsteemiga arvutites. **Märksõnad:** virtual desktop ## Küsimus: Millega tuleks arvestada koostöökeskkondade kasutamisel? **Vastus:** Sellega, et tegemist on tarkvaraga mille on teinud inimesed. Inimesed on ekslikud ja tarkvaras on vigu. Murphy seaduste kohaselt löövad need välja kõige ootamatumates kohtades ja kõige ebasobivamal ajal. Siiski arvan, et nende keskkondade üldine kasu kaalub üles võimalikud probleemid. Järgnevalt kaks negatiivset kogemust üliõpilaste enda sõnadega.***************"OneDrive ühiselt projekti tegemine võib ahvatlev olla, aga tegelikult võib jamasid tekkida. Meil rollbackis onedrive mingi tundmatu vea tõttu projekti dokumendifaili 40 minuti võrra ning täielikult korruptis EA faili nii, et EA faili avades saime network errori, ning tegime põhimõtteliselt diagrammid nullid uuesti. Minu soov on, et mõnel tudengil tulevikus seda muret ei tekiks"***************Teatele lisatud failis on fragment kolme üliõpilase poolt ühistööna kirjutatud magistritööst. Töö käigus puutusid nad kokku Wordi dokumendi ühise täiendamise probleemidega ja kirjutasid lõpuks oma töösse sellest eraldi alajaotuse. ## Küsimus: Millised on andmebaasisüsteemide MS Access, PostgreSQL ja LibreOffice Base eelised ja puudused võrreldes üksteisega, rõhuga sellel, kuidas neid oleks õppimiseks kasutada? **Vastus:** Mõned omadused on sellised, mida võib vaadata nii hea kui halvana.MS AccessEelised SQL keele põhikonstruktsioonid on toetatud. SQL kood on enamasti väikeste muudatuste järel või üldse muutmata käivitatav ka teistes andmebaasisüsteemides, sh PostgreSQL. Integreeritud graafiline liides (Query Designer) SQL SELECT, INSERT, UPDATE ja DELETE lausete koostamiseks. Graafilisi liideseid SELECT lausete koostamiseks leiab väga paljudest programmidest, kui INSERT, UPDATE ja DELETE lausete koostamiseks väga väikesest arvust programmidest (nt MySQL jaoks dbForge). Integreeritud graafiline andmebaasi struktuuri vaatamise vaade. Võimalus tabelite disaini (struktuuri ja kitsendusi) muuta nii SQL lausete abil kui graafilise kasutajaliidese kaudu. Integreeritud andmebaasirakenduse tegemise keskkond - pole vaja seda eraldi installeerida. Andmebaasirakenduse tegemise keskkond on hea näide vähese programmeerimise vajadusega kiirprogrammeerimise keskkonnast. Palju asju saab teha visuaalselt ja viisarditega. Andmebaasirakenduse loomise kasutajakogemus on päris sarnane Oracle APEX arenduskeskkonna kasutamisele - see võimaldab luua Oracle andmebaasile veebirakendusi kirjutades ise koodi vähe või üldse mitte. Sobiv vahend ka suuremate organisatsioonide jaoks andmebaasi ja andmebaasirakenduse prototüübi tegemiseks. Sobiv vahend üksikisikute ja väga väikeste ettevõtete andmebaasi tegemiseks. Saab teha nii, et andmebaasirakendus on tehtud MS Accessis ja see kasutab ODBC andmeühenduse tehnoloogia abil serveris asuvat (nt PostgreSQL või MySQL) andmebaasi. Erinevates andmebaasisüsteemide populaarsuse indeksites (vt siia ja siia) endiselt ja jätkuvalt kõrgel kohal. StackOverflow 2023. aasta uuringu kohaselt kuulus ka MS Access kõige populaarsemate, imetletumate ja õppida soovitavate andmebaasisüsteemide valikusse - mitte küll kõige esimeste hulka, kuid arvestades, et andmebaasisüsteeme on üle 400, on ka esimese 20-30 hulgas päris hea koht, kus olla. Uuemad SQLi võimalused pole toetatud. Samas piiratud võimalustega keskkonnas MacGyveri moodi soovitud tulemus saavutada on SQLi põhikonstruktsioonidest arusaamise mõttes väga hea kool. Puudused Uuemad SQLi võimalused pole toetatud. SQL lausete kirjutamise ja käivitamise kasutajaliides on väga halva kasutatavusega - aga, saab kasutada varianti kirjutada ja käivitada SQL lauseid otse Notepad++ tekstiredaktorist. Tarkvara saab alla laadida: https://github.com/aneelm/NppDB Tasuline - aga, Tallinna Tehnikaülikooli üliõpilastele tasuta kättesaadav. Võimalik eelarvamuslik suhtumine osade spetsialistide poolt - ahh, see süsteem ei kõlba kuhugi. PostgreSQLEelised Populaarne - kõrge koht erinevates populaarsuse indeksites (vt siia ja siia) ja kasutusel paljudes organisatsioonides (nii ettevõtted kui riigiasutused). StackOverflow 2023. aasta uuringu kohaselt oli PostgreSQL kõige populaarsem andmebaasisüsteem nii kõigi vastajate kui ka professionaalsete arendajate seas. Sama uuringu järgi on PostgreSQL ka kõige rohkem kasutada soovitav ja kõige imetletum andmebaasisüsteem. Väga suur võimaluste hulk andmebaasi programmeerijatele. Hea vastavus SQL standardile, toetab ka uusimaid SQLi võimalusi. Tasuta. SQL lausete harjutamiseks pole vaja tarkvara installeerida ega serverile juurdepääsu küsida - saab kasutada DB Fiddle või SQL Fiddle keskkondi. Väga palju erinevaid programme (nii graafilise kasutajaliidesega kui käsurea-põhiseid), mille vahendusel saate töötada (kas enda või ülikooli) serveris oleva andmebaasiga, sh hallata tabeleid ja vaadata andmebaasi struktuuri. Rakenduse tegemise vahend pole andmebaasi mootoriga integreeritud - saab ise valida keele/keskkonna, milles andmebaasirakendust teha. Palju dokumentatsiooni, Internetis olevaid näiteid, foorumeid jms. Puudused Palju selliseid võimalusi, mis SQLi aluste õppimise kontekstis pole olulised ja sellest tulenev lisakeerukus. Väga palju erinevaid programme (nii graafilise kasutajaliidesega kui käsurea-põhiseid), mille vahendusel saate töötada serveris oleva andmebaasiga, sh hallata tabeleid ja vaadata andmebaasi struktuuri - lisatöö seoses nende seast valiku tegemisega ja installeerimisega. Leidub erinevaid programme, mille abil saab andmebaasipäringuid graafiliselt koostada, aga ka need tuleb endal installeerida ja läbi katsetada. Rakenduse tegemise vahend pole andmebaasi mootoriga integreeritud - tuleb ise valida keel/keskkond, milles andmebaasirakendust teha, see üles panna ja endale selgeks teha. LibreOffice BaseEelised Tasuta alternatiiv MS Accessile. Puudused Ebamugav kasutajaliides SQL lausete käivitamiseks. Mitte nii mugav võimalus andmebaasirakenduse (ekraanivormide) koostamiseks kui MS Accessis. LibreOffice Base kasutab andmebaasimootorina HSQLDB (HyperSQL) versiooni 1.8.See ei ole kõige uuem HSQLDB versioon ja seetõttu ei saa seal kasutada HSQLDB uusimaid võimalusi. Vähe dokumentatsiooni ja näiteid SQL dialekti kohta. HSQLDB 1.8 SQL dialekt. ## Küsimus: Millist töövahendit saaks kasutada PostgreSQL andmebaasi tabelitest graafilise kujutise (kas HTML, pildifail või midagi taolist) loomiseks? Tööriist võiks olla vabavaraline, joosta Linuxi masinal ning ideaalis olla kasutatav käsurealt (et saaks kasutada ka skriptide sees). **Vastus:** Kui Teil on andmete modelleerimise CASE vahend, siis see võib toetada pöördprojekteerimist (reverse engineering) olemasolevast andmebaasist.Leidub ka eraldi andmebaaside haldusvahendeid, mis sellist funktsionaalsust pakuvad. Tõstan esile: DBVisualizer DBeaver Mõlema puhul on probleemiks, et visualiseerimise tulemuses ei näidata UNIQUE kitsendusi, CHECK kitsendusi, indekseid, kitsenduste ja indeksite nimesid.DBVisualizeris ei näe lisaks ka NOT NULL kitsendusi. Samuti ei saa seal teha eraldi diagramme andmebaaside erinevate alamosade kohta. DBeaveris on eraldi diagrammide loomine võimalik (Project => ER Diagrams). Looge kõigepealt tühi diagramm ja lohistage (drag and drop) seejärel sinna valik tabelitest. Täpselt nagu kontseptuaalse andmemudeli puhul võiks iga registri kohta luua eraldi diagrammid.DBeaveris on võimalik peita diagrammil osade, kuid mitte kõikide tabelite veerud. Selleks tuleb valida tabelit esitav kast ja parempoolse hiireklahvi alt avanevast menüüst valida Show Attributes => Selected Entity => None. Nii saate registri kohta käival diagrammil peita registrisse mittekuuluvate tabelite seosed, näidates samas registrisse kuuluvate tabelite seoseid teiste registrite tabelitega. ## Küsimus: Mul on arvutiks Mac / minu arvutil on Linux operatsioonisüsteem. Millist tarkvara soovitate kasutada? **Vastus:** Jutt on tarkvarast, mis on seotud kahe põhilise selle aine tegevuste plokiga. SQLi harjutamine ja lõpuks (kui vaja) kontrolltöö tegemine. Võimalik on kasutada MS Accessi. Iseseisva töö projekti tegemine. Vaikimisi kasutame Enterprise Architect (12) või Rational Rose tarkvara. Need vaikimisi programmid töötavad Windowsil. EA14 näitel näen, et seda saab installeerida ka Maci, kuid see nõuab üsna palju lisatööd. Litsentsi taotlemine (bat failiga) on mõeldud just EA12 jaoks, st seda ei saa kasutada näiteks EA kodulehelt allalaaditud kõige viimasele EA versioonile litsentsi taotlemiseks.Variant 1 - kasutada arvutiklasside Windows arvuteid kaugkasutuse korras Juhendi leiab SIIT.   Variant 2 - kasutada alternatiivset tarkvaraSQLSQLi iseseisvaks harjutamiseks, lisapunkti ülesannete lahendamiseks ja kontrolltöö tegemiseks saab kasutada ka PostgreSQL või LibreOfficeBase andmebaasisüsteeme. PostgreSQL abil SQLi iseseisvaks harjutamiseks, lisapunkti ülesannete lahendamiseks ja kontrolltöö tegemiseks piisab DB Fiddle keskkonna kasutamisest, kuhu ei pea registreerima, ega sisse logima. PostgreSQL (16) on serveris apex2.taltech.ee, millele juurdepääsu küsimise kohta on info SIIN. LibreOffice Base kuulub avatud lähtekoodiga LibreOffice kontoripaketi koosseisu, mille allalaadimise koht on SIIN. Lisamaterjalide lehel (kasutajanimi: SIS2 ja parool: SIS2) on: SIIN SQL laused mõnede harjutamise andmebaaside loomiseks PostgreSQL jaoks. SIIN mõned harjutamise andmebaasid LibreOffice Base jaoks ning ka pisike MS Access ja LibreOffice Base võrdlus, Programmeerijatele, sh SQL lausete kirjutajatele mõeldud tekstiredaktorid: Notepad++ on saadaval Linuxile ja SciTe on saadaval nii Macile kui Linuxile.Andmebaasidega töötamiseks graafilist kasutajaliidest pakkuv DBeaver vahend on saadaval nii Macile kui Linuxile. Selle abil saab ühenduda ka teiste andmebaasisüsteemidega kui MS Access. Selliseid universaalseid programme on veel teisigi - vaata neid SIIT.Iseseisev tööKui tahate teha iseseisvat tööd töövihiku järgi, siis alternatiivse CASE tarkvara kasutamisel tuleb arvestada sellega, et Te ei saa kasutada etteantud diagrammi põhju, vaid need tuleb käsitsi nullist ise teha.Andmete modelleerimiseks soovitan kindlasti kasutada CASE vahendit, mis toetab andmete modelleerimist, mitte joonistusvahendit või andmete modelleerimise toeta CASE vahendit (nt ArgoUML).Andmete modelleerimist toetava CASE vahendi eelis on, et see suudab genereerida andmemudelist SQL koodi ja nii oluliselt suurendada Teie töö kvaliteeti ja tulemuslikkust.  SIIN on nimekiri mõnedest kasutaja arvutisse installeeritavatest tasuta CASE vahenditest ja SIIN on nimekiri mõnedest veebipõhistest tasuta CASE vahenditest.Iseseisva töö prototüüpi ei pea tegema MS Accessis nii et sellega muret ei ole. Saate näiteks kasutada PostgreSQLi, LibreOffice Base, MySQL jne. Variant 3 - üritada tööle saada WindowsInternetist leiab juhiseid. Panin siia stiilinäiteks ühe juhise Maci ja ühe Linuxi kohta. Azure Dev Tools for Teaching keskkonnast on võimalik saada Windows Server operatsioonisüsteem.Variant 4 - veel võimalusiInstalleerida EA12 oma Windowsi lauaarvutisse (tööl või kodus) ning taotleda litsentsi üle FortiClient VPNi. Tehes projekti rühmatööna saate tööd jaotada nii, et visuaalsete mudelite (diagrammide) loomisega tegelevad need projekti osalised, kellel on oma arvutis vajalik tarkvara.Kuna projekti tegemisel on võimalik kasutada töövihiku lahendust, kus suur osa diagrammidest on ette valmis tehtud, siis nende täiendamine ei võta liiga palju aega ja seda jõuab teha arvutiklassis. Arvutiklasse saab kasutada aine praktikumide ajal. Arvutiklass ICT-405 on vabakasutuses. **Märksõnad:** kaugkasutus, MSAccess, kaugtöölaud, remote desktop, vpn, kaug, kaugtöö ## Küsimus: PostgreSQL EXCLUDE kitsendus: millal seda kasutada ning miks ilmub see kõikides näidetes fraasi "EXCLUDE USING gist" kujul? **Vastus:** EXCLUDE on PostgreSQLi laiendus - SQL standard seda ette ei näe ja teised andmebaasisüsteemid seda ei paku. Kuid see on väga kasulik laiendus. See on UNIQUE kitsenduse üldistus selles mõttes, et unikaalsuse kontrollimisele saab kasutada väärtuste võrdlemiseks ka muid operaatoreid kui =. Näiteks saab selle abil andmebaasi tasemel deklaratiivsel viisil tagada, et tabelis esitatud ajaliste väärtuste perioodid ei oleks osaliselt ega täielikult kattuvad. Näiteks, kui isikule X on määratud roll Y ajaperioodiks 1. jaanuar 2021 kuni 31. detsember 2021, siis ei saa talle seda sama rolli määrata ajaperioodiks 1. märts 2021 kuni 1. juuni 2021 või 1. märts 2021 kuni 31. detsember 2022.  See on "kangem" unikaalsuse kontroll kui UNIQUE (isik_id, rolli_kood, alguse_aeg). EXCLUDE abil saaks kontrollida ka tavalist unikaalsust, kuid kontrolli töökiiruse (aeglasem kui tavalise UNIQUE kontroll) ja porditavuse (teistesse süsteemide ülekandmise) mõttes pole see hea lahendus. EXCLUDE kitsenduse abil saab realiseerida ka kontrolle, mida muidu tuleks teha (osaliselt) unikaalse indeksiga. Tõstutundetu unikaalsus. Näiteks kui tabeli Isik veerus e_meil on juba mingis väljas aadress 'kask@hot.ee', siis ei saa sinna tabelisse lisada aadressi 'Kask@hot.ee'. Osaline unikaalsus. Näiteks, aktiivses seisundis kaupade nimetused peavad olema unikaalsed. Kui kaup ei ole aktiivses seisundis, siis selle nimetus ei pea olema unikaalne. Unikaalsuse kitsenduse kontrollimise toetuseks loob PostgreSQL automaatselt B+ puu tüüpi indeksi (indeksitüübi nimeks on küll B-puu, kuid realisatsioon vastab B+ puule, sest viited ridadele on ainult puu lehtedes). Kujutage ette, mis juhtuks ilma indeksita - tabelis on miljon rida, tabelisse lisati uus rida, reas oleva väärtuse unikaalsuse kontrollimiseks tuleks süsteemil kõik need read läbi vaadata. Mida rohkem oleks tabelis ridu, seda rohkem tuleks kontrollimiseks tööd teha (andmeid lugeda) ja seda aeglasemaks muutuks kontrollimine. See, kui süsteemi töökiirus langeb, mida rohkem süsteemi kasutatakse, vastab töökiiruse antimustrile hüppelaud (ramp).Ka EXCLUDE kitsenduse toetuseks vajab andmebaasisüsteem indeksit. Arvestades võrdluseid, mida süsteem peab EXCLUDE kitsenduse täidetuse kontrollimiseks läbi viima, ei sobi B+ puu tüüpi indeks, vaid sobib indeks tüüpi GIST. SIIN on EXCLUDE kitsenduse kasutamise koodinäiteid. ## Küsimus: Saan MS Teamsi avamisel teate "Me ei saanud ühendust luua. Logi sisse ja proovime uuesti". Uuesti proovimine ei aita. Mida teha? **Vastus:** SIIN on tegevusjuhend, mida tasub proovida sellisest veast vabanemiseks. Credential manager = Mandaadihaldur. Sulgege Teams. Avage tegumihaldur (Ctrl+Alt+Del) ja lõpetage kõik MS Teamsi tegumid.%appdata%\Microsoft\teams saab kirjutada Windowsi otsingusse ja kataloog avatakse automaatselt. Peale kataloogi sisu kustutamist ja enne Teamsi uuesti sisselogimist võiks teha arvuti taaskäivituse. **Märksõnad:** MS Teams, kaug, kaugtöö --- # Teema: Õppekeskkond ## Küsimus: Kas ainel on koduleht ka Moodles? **Vastus:** Jah on.Kodulehe versioon Moodles: https://moodle.taltech.ee/course/view.php?id=33251Registreerumise võti: ITI0206_K2024Moodle lehele registreerijad näevad kursuse põhisündmuseid oma Moodle kalendris. Materjalid on Mauruse keskkonnas, kuid Moodle pakub ühe võimaliku juurdepääsutee nendele materjalidele ja soovi korral võib Moodle olla ÜKS JA AINUS koht, mille kaudu materjalideni liikumist alustate. Siiski peab ennast ka Mauruses registreerima, et materjalidele ligi pääseda. ## Küsimus: Kas iseseisva töö juhendis ja näiteprojektis on võimalik mugavalt erinevate alamosade vahel liikuda? **Vastus:** Jah on.Nendes pdf failides on järjehoidjad (bookmarks), mis võimaldavad dokumendis erinevate alamosade vahel hõlpsasti navigeerida. Kahjuks, sõltuvalt kasutatavast veebilehitsejast, ei ole see alati automaatselt esile tõstetud. Kui vaatate neid faile Firefoxi veebilehitsejas, siis on need järjehoidjad lehe vasakus servas kohe näha.Kui vaatate neid faile Chrome veebilehitsejas, siis tuleb lehe vasakust servast valida jaotis Dokumendi liigendus.Kui vaatate neid faile Edge veebilehitsejas, siis tuleb lehe vasakust ülaservast valida Sisukord.Kui vaatate neid faile Opera veebilehitsejas, siis tuleb lehe vasakust servast valida jaotis Document outline.Chrome, Edge ja Opera puhul tuleb kõige kõrgema taseme pealkirjale klõpsata, et näha selle all olevaid alampealkirju.Vastusele on lisatud illustreerivad pildid. **Märksõnad:** navigeerimine, järjehoidja ## Küsimus: Kuidas ennast kodulehele registreerida? **Vastus:** Lehele ligipääsemiseks tuleb ennast registreerida.Palun kasutage konto juures sellist meiliaadressi, millele saabuvaid kirju Te igapäevaselt jälgite. Sellele aadressile hakkab saabuma aine korralduslik ja muu info. Seda võib vaja minna õppejõul, et Teiega ühendust võtta. Kui kasutate https://maurus.ttu.ee keskkonda esmakordselt, siis valige õppeaine lehelt menüüst Üldist=> Lehele registreerumine. Täitke vorm ja vajutage nupule "Registreeri". Kui juba olete õpikeskkonnas mingile lehele registreerunud (vahet pole, kas üks või kümme aastat tagasi), siis valige Mauruse esilehel menüüst Üldist=>Minu konto ja lisage enda aktiivsete lehtede hulka: "Andmebaasid I (ITI0206) (kevad 2024)" Ärge unustage vajutada "registreeri". Kui olete unustanud parooli, siis SIIN saab seda nullida. Kui Te ei mäleta kasutajanime/meiliaadressi, siis pöörduge õppejõu poole! Vajadusel muutke meiliaadressi, et see oleks selline, millele saabuvaid kirju Te igapäevaselt jälgite. Registreerumise järel peate ootama kuni õppejõud Teie juurdepääsu õiguse kinnitab. Kinnitamise kohta saadab süsteem automaatselt meili.   ## Küsimus: Kuidas näha siin kodulehel õppeaine materjale nagu need oleks Moodles? **Vastus:** Valige Kiirvalik=> Nagu MoodlesKui meeldib, siis märkige see järjehoidjas õppeaine koduleheks. **Märksõnad:** Moodle, alternatiivne esitus ## Küsimus: Kus on kodulehel jooksvad tulemused? **Vastus:** Klõpsake Kiirvalik=>Hinneteleht (link on nähtav ainult siis, kui on avaldatavaid tulemusi). **Märksõnad:** punktid, lisapunktid, vahetest, vahetestid ## Küsimus: Kus on kodulehel loengute lindistused? **Vastus:** Valige menüüst Kiirvalik=>Lindistused/Loengud **Märksõnad:** loengud, loeng, lindistus, lindistused, salvestus, salvestused, video, videod ## Küsimus: Materjale on liiga palju! Kuidas tulla toime suure materjalide hulgaga? **Vastus:** Kõiki materjale ei pea sugugi lugema. Te saate valida kolme materjalide kasutamise taseme (õpiraja) vahel. Valige tase vastavalt oma huvidele ja eesmärkidele.Tase 1 Neile, kellele piisab "läbi saamisest". Loe ainult materjale: Kiirvalik => Tutvu igal juhul! Materjalid korralduse ja projekti kohta. SQL andmebaasikeele ning teooria kohta leiab materjali väga paljudest allikatest. Teooria testideks saab valmistuda harjutuskeskkonnas harjutades. Tase 2 Neile, kes soovivad õpiväljundid heatasemeliselt saavutada. Loe igal nädalal materjale:  Kiirvalik=>Nagu Moodles VÕI Kiirvalik=>Nädala materjalid (samad materjalid, erinevalt esitatud) Igal nädalala jaoks kõige olulisemad materjalid. Pööra tähelepanu ka materjalide juures olevatele seotud dokumentidele. Lisaks on iga nädala kohta välja toodud soovitavad tegevused seoses ainega (nädalate peale kokku moodustab õppimise tegevuskava). Tase 3 Neile, kes soovivad süveneda ja saada põhjalikke teadmisi. Lisaks nädala materjalidele lugege ka muid materjale (alajaotis Materjalid) ning kasutajatoe küsimusi ja vastuseid (Abi => Kasutajatugi). Nädala materjalide juures on viited seotud dokumentidele ja lähedastele materjalidele. Kasutage otsingut! Üks võimalik tulevik võib olla selline, kus õppeaines saab kasutada õppeaine materjalide alusel treenitud juturobotit, mis põhineb mõnel suurel keelemudelil. Kasutaja esitab küsimuse ja materjalide põhjal treenitud tarkvara annab vastuse. Selline robot aga vajab treenimiseks teksti, palju teksti. Sellel teemal kaitsti 2024. aasta kevadel ka juba üks informaatika lõputöö. Samas on oht, et selline liigne lootmine otsingusüsteemidele ja suurtele keelemudelitele viib mõttelaiskuseni, pealiskaudususeni ja oma võimete ning teadmiste ülehindamiseni. **Märksõnad:** Maurus, materjalid, kuidas õppida, õpirada, fail, failid ## Küsimus: Mida saab teha Mauruses, mida Moodles ei saa? **Vastus:** Järgmised võimalused on Mauruses, kuid puuduvad Moodles. Loodetavasti kiirem reageerimine funktsionaalsuse või kasutajaliidese muutmise soovidele. Üliõpilastele säilib juurdepääs õppeaine kodulehele ning seal olevatele materjalidele ka peale aine uue õpetamiskorra algust. Isegi kui koduleht on Mauruse pealehelt eemaldatud, pääseb sellele endiselt ligi kas otseviitega või läbi pealehelt avaneva Minu konto alajaotuse. Hakates uuel semestril õppeainet uuesti õpetama loon Mauruses uue kodulehe (vana säilib) ning saan sinna enda valikul vanalt kodulehelt informatsiooni kopeerida. Moodles seevastu on õppeaine uuel semestril õpetama hakkamisel esimeseks sammuks kõikide lehele registreerunud üliõpilaste kustutamine. Ka Mauruses saab õppijatelt võtta juurdepääsu õppeaine kodulehele, kuid see on õppejõu otsus, mitte keskkonnast tulenev paratamatus. Mauruses saab õppija igal ajal ise kustutada oma registreerimise õppeaine lehele või ka kogu konto (kustutatakse tema registreerimised kõikidele õppeaine lehtedele). Kustutatakse kõik andmed, sh kasutaja üleslaetud failid ja kasutaja tegevuste logi. Materjale saab kasutaja jaoks grupeerida mitmel erineval viisil. Selleks on kataloogide hierarhias paiknevatele. materjalidele pealisehitusena lisatud vaadete mehhanism (vt menüüd Vaated materjalidele), mis võimaldab materjale kasutaja jaoks erineval viisil grupeerida. Vaade Kiirvalik=>Nädalate kaupa võimaldab välja tuua konkreetsel õppenädalal kõige olulisemad materjalid. Sisuliselt on nädala vaade selle nädala tegevuskava. Üks ja sama materjal võib olla seotud mitme nädalaga. Arendajatel on lihtne vajadusel uusi vaateid lisada. Analoogia: Kui materjalide all olev kataloogide hierarhia on nagu hierarhiline dokument dokumendipõhises andmebaasis (nt MongoDB abil loodud), siis vaated materjalidele on nagu selle dokumendi põhjal loodud (mitte-materialiseeritud) vaated. MongoDB toetab selliste vaadete loomist alates versioonist 3.4. Üks vaade materjalidele on nende esitus nagu see oleks Moodles (Kiirvalik=>Nagu Moodles) - kursuse materjalid ja ka muu oluline info on ühel suurel lehel nädalate kaupa välja toodud. Üliõpilane saab tähistada materjale (märkida need lemmikuks) nii, et sellised materjalid on pärast kõik ühest kohast leitavad. Õppejõud saab esile tõsta, millised materjalid on kohustuslikud (peaks igal juhul lugema) ja milliseid võib aja või huvipuudusel lugemata jätta. Kohustuslikud materjalid on erinevates vaadetes ühtemoodi esile tõstetud ja on lisaks koondatud vaatesse Kiirvalik=>Tutvu igal juhul! Vaadete kasutamise eelis seisneb ka selles, et materjale ei ole vaja dubleerida. Sama materjal võib olla erinevates vaadetes. Miks see on õppija jaoks tähtis? Kui materjale on vaja täiendada/täiustada, siis õppejõud peab seda tegema ühes kohas. Sellega: tagatakse muudatuste võimalikult kiire tegemine (lugejani jõuab kõige viimane ja kõige täpsem info võimalikult kiitesti), välditakse olukorda, kus samast materjalidest on õppekeskkonna erinevates osades mittekooskõlalised koopiad. Näiteks moodulis 1 on materjal, mis ütleb, et kontrolltööks tuleb lugeda A ja B kuid moodulis 2 on materjal, mis ütleb, et kontrolltööks tuleb lugeda A, B, C ja D. NB! Samad eelised on vaadetel ja andmete dubleerimise vältimisel ka andmebaaside maailmas. Kasutaja saab vaadata (alajaotus Isiklik) enda kõige viimati vaadatud faile või enda kõige rohkem vaadatud faile ja niimoodi leida kiiresti üles materjali, mida ta kunagi on juba vaadanud. Kasutajatel on võimalus teha otsing üle aine sisu kirjelduse, materjalide metaandmete, tegevuskava, teadete (v.a isiklikud teated), kasutajatoe küsimuste/vastuste, mõistete, viidete, tähaegade, ülesannete (kuid mitte nende vastused) ja vastuvõtuaegade. Näen, et otsingut kasutatakse palju. Süsteemis kogutud info tehtud otsingute kohta annab õppejõule võimaluse materjalide annotatsioone täiendada, et samasuguse otsingu tulemused oleksid edaspidi täpsemad. Materjalidele ja kasutajatoe küsimustele/vastustele saab lisada põhjaliku annotatsiooni, mida kasutaja vaikimisi ei näe, kuid mida kasutatakse eelmises punktis nimetatud otsingus. Võimalus panna välja suurel hulgal individuaalseid projektide ettenäitamise aegu (st üliõpilased ei pea tulema kaitsmise sessiooni alguseks kohale ja seal elavas järjekorras ootama). Võimalus tagada, et projekti mitmekesi tegijad, ei saaks broneerida mitu ettenäitamise aega ja välistada sellest tulenev ebaõiglus nende suhtes, kes teevad projekti üksinda. Kasutajatugi ning võimalus seal olevaid korduvaid küsimusi avalehele kinnitada ning küsimusi/vastuseid kõigile üliõpilastele meilile saata (sh korduvalt). Võimalus muuta avalehel näidatavate korduvate küsimuste järjekorda ning hulka. Võimalus neid küsimusi esile tõsta. Võimalus valida, millised teated saadetakse üliõpilasele meilile ja milliseid mitte (vähem ebaolulisi meile). Võimalus valida, milliste kalendri sündmuste meeldetuletused ainele registreerunute meilile saata ja millised mitte. Nii üliõpilasel kui õppejõul on võimalik saada kiiresti ülevaade, millisele teadmiste kontrollile on veel vabu kohti ja millisele mitte. See on väga oluline olukorras, kus on väljas näiteks 10 SQL kontrolltöö või vahetesti aega või 50-100 projekti näitamise aega. Üliõpilane ei saa sama tüüpi teadmiste kontrollile olla samaaegselt mitmekordselt registreeritud. See aitab tagada, et vabu kohti ei hõivataks ilmaasjata ning et neid jätkuks suuremale hulgale soovijatele. Õppejõul on võimalus saata meeldetuletus kõigile üliõpilastele, kes mingit tüüpi teadmiste kontrollile ei ole veel registreerunud (on selle unustanud või mäletavad ekslikult, et registreerisid, kuid tegelikult ei teinud seda). Kui projekt on arvestatud ja üliõpilane paneb ennast uuesti projekti näitamisele kirja või unustab varem tehtud registreerimise tühistada, siis saan päringuga selle üles leida ja operatiivselt sellise registreerimise tühistada. Vabad ettenäitamise ajad on oluline ning projektide näitamiste tippajal paljudele huvi pakkuv ressurss. Õppejõud saab kasutajate jaoks materjale ja katalooge esile tõsta nii, et tulemus tõepooles ülejäänud materjalidest ja kataloogidest visuaalselt eristub. Saab teha nii, et lingi alusel materjali (faili) allalaadides ei pea kasutaja ennast tuvastama - teiste sõnadega materjali saavad kasutada kõik, kes teavad linki. Võimalik loengu otseülekande toimumise ajal seda kodulehe avalehel automaatselt esile tõsta. Eesti- ja ingliskeelse terminoloogiaga mõistete sõnastik, mis on integreeritud materjalidega ja pakub täiendavaid märksõnu mille alusel otsing leiab üles olulisi/vajalikke materjale. Üliõpilane saab vaadata sõnapilve materjalide juures kasutatud märksõnadest, mis pakub kõrgtaseme ülevaate materjalide temaatikast. Üliõpilased ja õppejõud näevad, millised materjalid on lugemata ja kuidas edeneb üliõpilastel materjalidega tutvumine võrreldes teiste üliõpilastega. Üliõpilane saab hinnata (skaalal 1-5) abiinfo keskkonnas esitatud küsimuste vastuseid. Kui õppejõud näeb, et mõnda vastust on halvasti hinnatud, siis ta saab seda parandada. Integratsioon Mauruse testide tegemise keskkonnaga, mis võimaldab testide harjutamise juures näidata harjutajatele valesti vastatud testiküsimuse juures viidet materjalidele, kust saab infot küsimuse valdkonna ja õige vastuse kohta. Annan igaks juhuks ka teada, et Mauruses ei salvestata paroole avatekstina. **Märksõnad:** Moodle, e-õpe, e-tugi,e-kursus ## Küsimus: Miks on nii, et Mauruse testikeskkond näitab, et vastamise lõpetamiseni on veel aega, kuid tegelikult on aeg täis? **Vastus:** Arvuti kell jääb maha. Siin kirjeldatakse selle mõningaid põhjuseid Windowsi korral. Sarnane probleem esineb ka Mac arvutites. ## Küsimus: Millisel viisil saab esitada soove selle kohta, kuidas muuta andmebaaside õppeaine kodulehed Moodles ja Mauruses paremini kasutatavaks ja materjalid kergemini ülesleitavaks? **Vastus:** Soovid saab kirja panna SIIA (anonüümselt). Ma olen sealt saanud häid ideid, mille alusel olen kodulehti ja materjale parandanud. Tänan juba ette konstruktiivsete ettepanekute eest! **Märksõnad:** tagasiside, Maurus, anonüümne, kasutatavus, funktsionaalsus, Moodle ## Küsimus: Mulle ei meeldi üldse, kuidas õppejõud Mauruse keskkonnas minu tegemisi jälgib. Kuida kommenteerite? **Vastus:** Ajastu vaim ongi selline, et inimene jätab igal sammul ennast maha jälgi andmetena ning keegi kuskil kogub ja otsustab midagi nende andmete põhjal.Õpingutest rääkides, siis ülikool on väga huvitatud üliõpilaste edukast ja õigeaegsest lõpetamisest, sest sellest sõltub riigi poolne rahastus. Õpianalüütika on maailmas oluline uurimus- ning arendusteema (vt näitena doktoritööd) ning sellel teemal on ka meie ülikoolis kaitstud mitmeid lõputöid (nt SEE, SEE ja SEE). Selles vallas teeb suurt tööd Ago Luberg ja tema juhendamisel arendatavad süsteemid on seotud Moodlega ning võimaldavad Moodlesse kogutud andmeid paremini esitada ja analüüsida. Ka Moodles on õppejõul ülevaade sellest, mida iga konkreetne kasutaja (õppija) on materjalidega seoses teinud (vt lisatud pilti).Kindlasti ei jälgi ma materjalide kasutust igapäevaselt ning materjalide kasutamine pole hindamiskriteerium. Aines kohustuslikke materjale on võrreldes kodulehel oleva üldiste materjalide hulgaga väikene osa ja need materjalid puudutavad korraldust ning projekti tegemist. Siiski, kui märkan, et pikema perioodi jooksul pole üliõpilane kodulehte kasutatud, siis tunnen huvi, kas tal on õppimisel mingid takistused/probleemid ja kuidas saaksin aidata neid lahendada.Mauruses saate vaadata infot enda tegemiste kohta kodulehelt SIIT. Kui kustutate peale semestri lõppu oma registreerimise kodulehele, siis kustutatakse ka need andmed. ## Küsimus: Soovin Teamsis vaadata praktikumi lindistust, kuid saan teate 404 NOT FOUND. Kuidas ma saan vaadata praktikumide lindistusi? **Vastus:** Teamsi lindistused lähevad meeskonnaga seotud kataloogi alamkataloogi Recordings. Peale lindistamist muudan faili nime arusaadavamaks ning lisan annotatsiooni. Kuna faili nimi muutub, siis Teamsi kanalis olev link enam ei tööta.Praktikumide lindistuste vaatamiseks tuleb valida õppeaine kodulehelt:Kiirvalik=> Praktikumide lindistusSee viib õigesse kataloogi. Kataloogi minnes on iga lindistuse faili juures näha ka annotatsioon (märksõnad selle kohta, millest räägiti). **Märksõnad:** Teams, Sharepoint, lindistus, salvestus, lindistused, salvestused