Teema 10. Loogiline disain. CASE

Similar documents
Praktikumi ülesanne nr 4

UML keel. Keel visuaalseks modelleerimiseks. Ajalugu ja skeemide nimekiri

Arvutiklassi broneerimise veebirakendus. Eesti koolidele. Tallinna Ülikool. Informaatika Instituut. Bakalaureusetöö. Autor: Raimo Virolainen

SADAMA VASTUVÕTUSEADMETE VÄIDETAVATEST PUUDUSTEST TEAVITAMISE VORM FORM FOR REPORTING ALLEGED INADEQUACIES OF PORT RECEPTION FACILITIES

Ehitisintegreeritud fotoelektriliste päikesepaneelide tootlikkus ja majanduslik tasuvus Eesti kliimas aastal 2011

VALGE SÄRK PÕHIKANGAS TWO FOLD

Elektrituuliku seisundi reaalajajälgimissüsteem ja selle rakendused

Väiketuulikute ja päikesepaneelide tootlikkuse ja tasuvuse võrdlus

Elekter päikesest Eestis aastal Andri Jagomägi, Ph.D. Tallinna Tehnikaülikool Materjaliteaduse Instituut

KALEV SPA ELEKTRIVARUSTUSE LAHENDAMINE KOLME SISENDI BAASIL

Naabrireeglid klassifitseerimisel

jõudlusega ning vähendab võrra.

MADALA TASEME JUHTKONTROLLERI ARENDUS ISEJUHTIVALE SÕIDUKILE

Rehvitemperatuuri mõõtesüsteem võistlusautole FEST14

Praktiline juhend biotsiidimääruse kohta

Excel Tallinna Ülikool

Tarkvaraprotsessi küpsuse hindamise ja arendamise võimalusi Capability Maturity Model i näitel

EMG SIGNAALITÖÖTLUSPLOKK JUHTIMISRAKENDUSTEKS

PUBLITSEERIMISKESKUS. Kasutusjuhend

KÕRGEPINGE-IMPULSSTRAFO TOITEALLIKA JA KÕRGEPINGEMUUNDURIGA TESTMOODULI PROJEKTEERIMINE ESS-I PROOTONIKIIRENDILE

VÄLJALASKESÜSTEEMI PROJEKTEERIMINE ÜKSIKKORRAS VALMISTATUD SÕIDUKILE

GB Instruction for use EE Kasutusjuhend BA11.31PB/PDEE POWERTEX Shackle PBSB/PBSP/PDSB/PDSP

K ägu. Eesti Bioloogia ja Geograafia Õpetajate Liidu toimetised

GB Instruction for use EE Kasutusjuhend! UMPLM EE. POWERTEX Permanent Lifting Magnet model PLM

Tartu Ülikool Germaani, romaani ja slaavi filoloogia instituut KÜTTE, VENTILATSIOONI JA ÕHUKONDITSIONEERIMISE INGLISE-EESTI SELETAV SÕNASTIK

ETTEVÕTTE VÄÄRTUSE KUJUNEMINE LÄHTUVALT VALITUD STRATEEGIAST AS i IMPREST NÄITEL

Mahu- ja kuluarvestus käsitöönduslikus palkehituses

LOGO. Eesti Arengukoostöö ja Humanitaarabi

Deceleration measurement system used for measuring vehicle braking parameters Master s Thesis

3. MAJANDUSSTATISTIKA

This document is a preview generated by EVS

Tuleohutuspaigaldiste ja päästevahendite rakendamise juhend haiglatele ja hooldekodudele

E-dok. Tarkvara kasutamise käsiraamat. Versioon: E-DOK OÜ E-dok OÜ 1

EESTI MAAÜLIKOOL Tehnikainstituut. Ago Ütt-Ütti

CO 2. heitkoguste vähendamisele suunatud projektid KYŌTO PROTOKOLL

Rakendustarkvara: R. Sügis 2017, 4. praktikum

MUUDETUD juunis Kõik õigused kaitstud WADA

EUROOPA KAUBAMÄRGI JA DISAINI INFOKIRI

AIP Supplement for Estonia

TALLINNA TEHNIKAÜLIKOOL Infotehnoloogia teaduskond IDK40LT Ilja Kudrjavtsev IAPB JÄRELTURU ELEKTRILINE DIFERENTSIAALILUKK AUTO ABS PÕHJAL Bakala

Head lapsevanemad! Aasta 2009 hakkab läbi saama ning peagi on kätte jõudmas jõuluaeg ja aasta lõpp. Jõuluaeg on kindlasti meelespidamise

Väga tõhusad väikese energiakuluga

AWD18E CORDLESS DRILL AKUTRELL

Kaitseväe Ühendatud Õppeasutused Taktika õppetool

Kinnituselemendid ja ühendustehnika. Kvaliteet, mida saab usaldada

MOTOSPORDIKOMPLEKS PROJEKT AINES IDU INFOSÜSTEEMIDE STRATEEGILINE ANALÜÜS. Tallinna Tehnikaülikool Informaatikainstituut

TOITESÜSTEEMI TÄIUSTAMINE RAHA SÄÄSTMISEKS

Elektripaigaldise auditi juhendmaterjal

Geograafilise päritolu ennustamine geeniekspressiooni ja geneetilise varieeruvuse abil

Ohutuskaartide ja kokkupuutestsenaariumide juhend

This document is a preview generated by EVS

Tartu Ülikool Psühholoogia osakond. Margit Tamm. Algklasside õpilaste verbaalsete võimete hindamine. Individuaalse ja grupitestimise võrdlus

LIITREAALSUSE RAKENDAMINE ÜLDHARIDUSKOOLI ÕPPETÖÖS: VÕIMALUSED JA KITSASKOHAD Magistritöö

ZAZ 1102 TAURIA TAGAVEDRUSTUSE KINEMAATIKA MUUTMINE

SISSEJUHATUS Aruande alused Käesoleva aruande koostamise aluseks on kehtima hakanud riigivaraseaduse (edaspidi RVS) 99 lõikest 1 tulenev ko

ATS3000/4000 Juhtpaneel. Kasutusjuhend

Eesti Haigekassa DRG piirhinna ja piiride arvutamise metoodika hindamine

Elektrisüsteemi bilansi tagamise (tasakaalustamise) eeskirjad

Tabelarvutus LibreOffice Calc-iga

PICAXE trükkplaatide koostamine

JÄRELTULIJALIJA e. Küsimustele vastab direktor Sirje Kautsaar

KOVTP kaardirakendus Kasutusjuhend. Versioon 1.0

KESKMOOTORIGA RALLIAUTO TAURIA RESTAUREERIMINE SISSELASKETRAKT

LISA 1. SILUMINE. e) Kanname andmed tabelisse L1.1 ja liidame kokku:

B 90 R Adv DOSE Bp Pack

EESTI STANDARD EVS-EN 25199:1999. Tsentrifugaalpumpade tehnilised andmed. Klass II Technical specifications for centrifugal pumps - Class II

Tarbimise juhtimine tootmisettevõttes kasutades DMAIC ja Six-Sigma metoodikaid

PFEIFER-i keermestatud tõstesüsteem PFEIFER SEIL- UND HEBETECHNIK GMBH

Eestikeelne kasutusjuhend

EUROOPA ÜHENDUSTE KOMISJON. Ettepanek NÕUKOGU OTSUSE

Cold rolled narrow steel strip for heat treatment - Technical delivery conditions - Part 3: Steels for quenching and tempering

TOOTMISPROTSESSI ARENDUS ABB AS AJAMITE JA TAASTUVENERGIASEADMETE TEHASE NÄITEL

SA Säästva Eesti Instituut/ Stockholmi Keskkonnainstituudi Tallinna keskus NATURA HINDAMISE PRAKTIKAST JA KVALITEEDIST 2010.

ABB AS Nutikad laolahendused ABB-s Üldsegi mitte pilves

C4.1. Elektripaigaldus- ja kasutusjuhend

Efektiivne energiatootmine GE Jenbacher biogaasimootoritega

Elektribusside laadimissüsteemide tasuvus- ja tundlikkusanalüüs

dotsent, tellimustöö vastutav täitja, TTÜ elektroenergeetika instituut doktorant, nooremteadur, TTÜ elektroenergeetika instituut

This document is a preview generated by EVS

Elektripaigaldise auditi juhendmaterjal

INGLISE-EESTI SELETAV TAKISTUSSÕIDUSÕNASTIK

Talendi valik ja arendamine spordis

LYRA. Loob rahuliku keskkonna. Air Climate Solutions

AUTOVARUOSAD JA -TEHNIKA 1. VĀKS

This document is a preview generated by EVS

EESTI STANDARD EVS-EN :2008

Petrol snow thrower. Petrol snow thrower SPT GB Original instructions EE. Algupärase kasutusjuhendi tõlge

Kodune biodiisli valmistamine ja kasutamine Uurimistöö

Vaheseinte ehitamine, kasutades helineelduvaid kivivillaplaate

Kanepibetoonsegude tutvustus ja katsetamine Eesti kliimas

Madis Pääbo MOOTORI SIMULATSIOON JA TURBOÜLELAADIMISSÜSTEEMI PROJEKTEERIMINE BMW M50-M54 MOOTORITELE

TÜ EESTI MEREINSTITUUT. Avamere tuuleparkide rajamisega Loode- Eesti rannikumerre kaasnevate keskkonnamõjude hindamine PROGRAMM

This document is a preview generated by EVS

Raudteealased rakendused. Rattapaarid ja pöördvankrid. Rattapaarid. Tootenõuded KONSOLIDEERITUD TEKST Railway applications - Wheelsets and bogies -

KESKMOOTORIGA RALLIAUTO TAURIA PLASTKOORIKU RENOVEERIMINE

III. (Ettevalmistavad aktid) EUROOPA KESKPANK

SPORTLIK VABAVÕITLUS EESTIS

EESTI STANDARD EVS-EN 15355:2008

GB Instruction for use EE Kasutusjuhend BA11.50PRSJEE POWERTEX Rigging Screw model PRSJ/PRSE

This document is a preview generated by EVS

Transcription:

Teema 10. Loogiline disain. CASE Sisukord 1 Eesmärgid... 3 2 Disain... 3 3 Andmebaasi loogiline disain... 4 3.1 Kontseptuaalse andmemudeli teisendamine... 5 3.2 SQL-andmebaasi kirjelduse esitamine... 6 3.3 Tabelite leidmine... 6 3.3.1 Tugev olemitüüp... 6 3.3.2 1:M binaarne seosetüüp... 7 3.3.3 Nõrk olemitüüp... 9 3.3.4 M:N binaarne seosetüüp... 9 3.3.5 1:1 binaarne seosetüüp... 12 3.3.6 Rekursiivne seosetüüp... 14 3.3.6.1 1:1 rekursiivne seosetüüp... 14 3.3.6.2 1:M rekursiivne seosetüüp... 16 3.3.6.3 M:N rekursiivne seosetüüp... 16 3.3.7 Üldistusseos... 17 3.3.7.1 Variant 1 {Optional; Or}... 18 3.3.7.2 Variant 2 {Mandatory; And}... 18 3.3.7.3 Variant 3 {Optional; And}... 20 3.3.7.4 Variant 4 {Mandatory; Or}... 21 3.3.8 Seosetüüp, mille aste on kahest suurem... 21 3.3.9 Välistav kaar... 22 3.3.9.1 Täieliku/tõelise kaare lahendus... 23 3.3.9.2 Kaare lõhkumise lahendus... 24 3.3.9.3 Ühise / üldise kaare lahendus... 24 3.3.10 Mitmeväärtuseline atribuut... 25 3.4 Kitsenduste kirjeldamine... 27 3.4.1 Võtmed... 28 3.4.2 Veergude kohustuslikus... 31 3.4.3 Viidete terviklikkuse tagamine... 31 3.4.4 Tuletisatribuudid... 35 3.4.5 Täiendavad kitsendused... 36 3.5 Tabelite disaini kvaliteedi hindamine ja parandamine... 37 3.6 Loogilise disaini andmemudeli näide... 38 3.7 Veel mõned soovitused... 40 3.7.1 Klassifikaatorite haldus... 40 3.7.2 Klassifikaatorite hoidmine SQL-andmebaasis... 41 3.7.3 Väärtuste puudumine... 45 3.7.4 Seisundite klassifikaator... 45 3.7.5 Vektorkodeerimine e. semantiline kodeerimine.... 47 3.7.6 Vaba teksti väljad... 49 4 Rakenduse loogiline disain... 50 4.1 Kasutajaliideste loogiline projekteerimine... 51 4.2 Transaktsioonide loogiline projekteerimine... 54 5 CASE vahendid... 55 5.1 CASE vahendi kasutamisest tulenev võimalik kasu... 55 5.2 Üldised nõuded CASE vahenditele... 55 5.3 Andmete modelleerimise CASE-vahendite üldiseloomustus... 61 1

5.4 Spetsiifilised nõuded andmete modelleerimiseks mõeldud CASE vahenditele... 62 5.5 Kuidas valida CASE vahendeid?... 62 6 Mõisted... 63 7 Kasutatud materjalid... 64

1 Eesmärgid Tutvustada disaini mõistet. Anda ülevaade andmebaasi ja teda kasutava rakenduse loogilisest disainist. Kirjeldada teisendusreegleid, mida kasutades saab leida olemi-suhte diagrammide abil esitatud kontseptuaalse andmemudeli põhjal SQL-andmebaasi loogilise disaini esialgse kirjelduse. Kirjeldada tabelitega seotud kitsenduste leidmise ja kirjeldamise põhimõtteid. Tutvuda CASE vahendite ja nende põhiliste omadustega. Kirjeldada, kuidas hoida andmebaasis klassifikaatorite andmeid. 2 Disain Analüüs on suunatud uuritava probleemi/valdkonna mõistmisele ning toimimistasemelisele modelleerimisele. Analüüsiprotsessi käigus toimuva modelleerimise käigus selgitatakse välja, kooskõlastatakse ning üldistatakse reaalse süsteemi erinevate osapoolte probleemid ja vajadused ning luuakse mudelid, mis kirjeldavad terviksüsteemi toimimist. Disainiks kõige üldisemas mõttes peetakse igasugust keskkonna kujundamist ja projekteerimist, kas üldiste arhitektuursete lahenduste või siis detailsete komponendilahenduste modelleerimise ja sünteesi kaudu. Terminit "disain" kasutatakse ka disaini protsessi tulemusena loodud kavandi tähistamiseks. Disaini objektiks ehk kujundatavaks keskkonnaks võib olla hoone/ehitis või selle osad, üksikud esemed, kuid samuti organisatsioon, selle infosüsteem, selle arhitektuur ja üksikud komponendid, tarkvara, andmebaas, kasutajaliides jne. Disaini eesmärgiks on saavutada valitud vahenditega lahendus, mis võimalikult täpselt rahuldab loodava süsteemiga seotud osapoolte (isikute ja organisatsioonide) nõudmisi. Nõudmised modelleeritakse analüüsiprotsessi tulemusena. Tarkvara- ja infosüsteemide kontekstis on disaini ülesandeks analüüsi etapis väljatoodud nõuetele vastavate loogiliste ja tehniliste lahenduste väljatöötamine. Selle eesmärgiks on kirjeldada süsteemi piisavalt täpselt, et seda saaks asuda ehitama. Disain kasutab analüüsi tulemust lähtepunktina vajalike arhitektuuri-, tarkvarajne. lahenduste tuletamiseks/sünteesiks. Analüüs mõistab probleemi ja disain esitab lahenduse. Analüüs nõuab eeskätt teadmisi rakendusvaldkonna (uuritav reaalne süsteem) kohta, disain aga nõuab teadmisi arvutite, arvutivõrkude ning tarkvara arhitektuuride alalt. Kuid kahtlemata tulevad analüütikule kasuks ka 3

teadmised disaini ja ehitamise kohta ning disainerile tulevad kasuks teadmised analüüsi ning projekteeritava süsteemi valdkonna kohta. Eristatakse loogilist ja füüsilist disaini. Loogiline disain tegeleb konkreetsest realisatsiooni- ja rakenduskeskkonnast sõltumatute, järelikult nende keskkondade jaoks spetsiaalselt optimeerimata lahenduste loomisega. Isotamm (1998) soovitab loogilise disaini tulemusena loodud mudelit nimetada rakendusmudeliks. Loogiline disain jaguneb: Andmebaasi loogiline disain, mille sisendiks on kontseptuaalne andmemudel. Sellele rakendatakse teisendusreeglid, et luua esialgne loogilise disaini andmemudel (loogiline andmemudel, andmebaasiskeemi kirjeldus). Loomulikult peab andmebaasi kavandaja selle esialgse mudeli üle vaatama ja tegema vajalikud parandused ning täiendused. Andmebaasi kasutava rakenduse loogiline disain, mille sisendiks on kasutusjuhtude kirjeldused ja andmebaasioperatsioonide lepingud. Tulemuseks on reaalsete kasutusjuhtumite kirjeldused, ekraanivormide pildid ja transaktsioonide spetsifikatsioonid. Füüsiline disain optimeerib / häälestab loogilise disaini lahendusi konkreetsete füüsiliste keskkondade jaoks, st. konkreetsete riist- ja tarkvara produktide jaoks. 3 Andmebaasi loogiline disain Tuletame meelde, et terminit "andmemudel" kasutatakse kahes erinevas tähenduses. Connolly ja Begg (2002) põhjal on andmebaasi loogiline disain protsess, mille käigus luuakse organisatsiooni loogiline andmemudel, mis põhineb mingil kindlal andmemudelil (nt. relatsiooniline mudel või SQL aluseks olev mudel), kuid mis on sõltumatu andmebaasisüsteemist või muudest füüsilise realisatsiooniga seotud kaalutlustest. Loogilise disaini alguses tuleb lõplikult otsustada, millise andmemudeli (näiteks relatsiooniline) põhjal kavatsetakse andmebaas luua. Käesolevas kursuses teeme me tutvust SQL-andmebaasi loogilise disainiga. Järelikult on valitud andmemudeliks SQLi aluseks olev andmemudel. Edaspidi kasutatakse SQLi termineid "tabel", "rida" ja "veerg". Kogu selle peatüki vältel kasutatakse terminit "tabel", et rääkida baastabelitest. Loogiline andmebaasi disain hõlmab. Loogilise andmemudeli koostamine. Andmebaasioperatsioonide loogiline projekteerimine. Loogiline andmemudel koostatakse kontseptuaalse andmemudeli põhjal. Erinevalt analüüsi tulemusena koostatud kontseptuaalsest andmemudelist, 4

nähakse nüüd iga olemitüübi taga konkreetset tabelit. Loogilise disaini tulemusena leitakse tabelite struktuur ja seotud kitsendused. Tabelid on soovitav viia viiendale normaalkujule ja kontrollida, et nad rahuldavad ortogonaalse andmebaasi disaini printsiipi. Lisaks hõlmab andmebaasi loogiline disain ka andmebaasioperatsioonide loogilist projekteerimist. Analüüsi käigus loodud andmebaasioperatsioonide lepinguid täiendatakse nii, et seal kasutataks tabelite ja veergude nimesid. Andmebaasioperatsioonide loogilise projekteerimise käigus tuleb kontrollida, kas kirjeldatud operatsioone on võimalik projekteeritud andmebaasi põhjal läbi viia. Andmebaasioperatsioon on andmete kasutamise elementaarteenus, mida andmebaas pakub selle poole pöörduvatele rakendustele. SQL-andmebaasi kasutamise korral võib andmebaasioperatsiooni või ka mitu üheskoos kasutatavat andmebaasioperatsiooni realiseerida ühe andmebaasiserveris talletatud rutiinina. SQL-andmebaasi loogilise disaini tegevused on: 1. Kontseptuaalse andmemudeli muutmine SQLi aluseks oleva andmemudeliga kokkusobimatute konstruktsioonide eemaldamine andmemudelist (valikuline võib, kuid ei pruugi teha). 2. Tabelite leidmine. 3. Võtmete kitsenduste kirjeldamine. 4. Tabelite disaini kvaliteedi hindamine ja parandamine. 5. Andmebaasioperatsioonide loogiline projekteerimine. 6. Disaini tulemuste ülevaatamine koos süsteemi tulevaste kasutajatega. Kontseptuaalsest andmemudelist esialgse loogilise andmemudeli leidmist on võimalik automatiseerida, sest eksisteerivad teisendusreeglid. 3.1 Kontseptuaalse andmemudeli teisendamine Connolly ja Begg (2002) märgivad, et soovi korral võib enne loogilise andmemudeli koostamise algust muuta lähtemudeliks olevat kontseptuaalset andmemudelit. Muutmise eesmärgiks on eemaldada kontseptuaalsest andmemudelist konstruktsioonid, mille põhjal loogilise andmemudeli elementide leidmine nõuab suhteliselt keerukat teisendust. Tegemist on mittekohustusliku ja ettevalmistava sammuga, mille tulemusena peaks esialgse loogilise andmemudeli leidmine lihtsustuma. Võimalikud tegevused. Eemaldada binaarsed mitu-mitu (M:N) seosetüübid. Eemaldada rekursiivsed mitu-mitu (M:N) seosetüübid. Eemaldada seosetüübid, kus osaleb kolm või rohkem olemitüüpi. Eemaldada mitmeväärtuselised atribuudid. 5

Binaarsete mitu-mitu (M:N) seosetüüpide eemaldamiseks luuakse uus olemitüüp ja kaks uut üks-mitu (1:M) seosetüüpi. Olemitüübiga OT seotud rekursiivse mitu-mitu (M:N) seosetüübi eemaldamiseks luuakse uus olemitüüp OT seos ja kaks uut üks-mitu (1:M) seosetüüpi olemitüüpide OT ja OT seos vahel. OT seos võimsus mõlema vaadeldava seosetüübi kontekstis on üks. Kolme või rohkemat olemitüüpi hõlmava seosetüübi eemaldamiseks luuakse uus olemitüüp ja seostatakse see 1:M seosetüüpide kaudu esialgses seosetüübis osalenud olemitüüpidega. Mitmeväärtuseliste atribuutide eemaldamiseks luuakse atribuudile vastav uus olemitüüp, mis on 1:M seosetüübi kaudu seotud olemitüübiga, millesse see atribuut enne kuulus. 3.2 SQL-andmebaasi kirjelduse esitamine SQLi tabelite ja võtmete kirjelduse esitamiseks võib kasutada järgnevat esitusviisi: Tabeli nimi (veergude nimekiri) Primaarvõti (primaarvõtme poolt hõlmatud veergude nimekiri) Alternatiivvõti (alternatiivvõtme poolt hõlmatud veergude nimekiri) Välisvõti (välisvõtme poolt hõlmatud veergude nimekiri) Viitab Tabeli nimi (primaar- või alternatiivvõtme poolt hõlmatud veergude nimekiri) Pange tähele, et veergude nimekirjad ei ole mitte looksulgudes vaid ümarsulgudes. See näitab, et SQL pöörab tähelepanu veergude järjekorrale tabelites ja võtmetes. 3.3 Tabelite leidmine Lihtsustatult öeldes hakkab üldjuhul igale olemitüübile vastama üks tabel. Järgnevaid teisendusreegleid kirjeldavad Connolly ja Begg (2002). Eeldame, et kontseptuaalne andmemudel on esitatud kasutades olemi-suhte diagramme ning olemitüüpide, atribuutide ja seosetüüpide kirjeldusi. Eeldame, et andmebaas plaanitakse luua SQL-andmebaasina. 3.3.1 Tugev olemitüüp Tugeva olemitüübi OT põhjal luuakse tabel T. Iga OT üheväärtuselise atribuudi põhjal lisatakse tabelisse T üks veerg. Veeru tüüp leitakse atribuudi tüübi põhjal. Olemitüübi atribuutide põhjal, mis on unikaalsed identifikaatorid, leitakse primaarvõtmed ja alternatiivvõtmed. 6

Amet ameti_kood : String nimetus : String Joonis 1 Olemitüübi näide. Joonis 1 esitatud olemitüübi põhjal leitakse baastabeli kirjeldus (edaspidi lihtsalt tabel): Amet (ameti_kood, nimetus) Primaarvõti (ameti_kood) Alternatiivvõti (nimetus) See, et ameti_kood ja nimetus on unikaalsed identifikaatorid, ei paista olemisuhte diagrammilt välja, kuid see informatsioon on dokumenteeritud kontseptuaalses andmemudelis. Juhul kui kontseptuaalses andmemudelis ei ole informatsiooni olemitüübi unikaalsete identifikaatorite kohta ja ka loogilise andmemudeli koostajad ei oska olemasolevate atribuutide põhjal võtmeid määrata, siis võib loodavas tabelis võtta kasutusele surrogaatvõtme. Järgnevas näites on selleks (amet_id). Amet (amet_id, ameti_kood, nimetus) Primaarvõti (amet_id) Sellise lahenduse probleemiks on, et andmebaasis võivad jääda jõustamata sisulise tähendusega võtmed (antud juhul (ameti_kood) ja (nimetus)). 3.3.2 1:M binaarne seosetüüp Amet ameti_kood : String nimetus : String töötamine 1 0..* Töötaja isikukood : String eesnimi : String perenimi : String sünniaeg : Date sugu : String elukoht : String Joonis 2 1:M binaarse seosetüübi näide. Joonis 2 esitab 1:M binaarse seosetüübi. 1:M tähendab, et tegemist on üksmitmele seosega. Iga töötaja töötab täpselt ühel ametikohal. Igal ametikohal töötab null või rohkem töötajat. Binaarne tähendab, et seosetüüp ühendab kahte olemitüüpi. Sellise seosetüübi abil ühendatud olemitüüpide põhjal luuakse eraldi tabelid. Ühte nendest tabelitest tuleb lisada välisvõtme veerud ja välisvõtme 7

kitsendus. Välisvõti tuleb paigutada tabelisse, millele vastava olemitüübi võimsus vaadeldava seosetüübi kontekstis on üks. Joonis 2 kohaselt töötab iga töötaja täpselt ühes ametis. Seetõttu tuleb lisada välisvõti olemitüübi Töötaja põhjal loodavasse tabelisse. Joonis 2 esitatud olemitüüpide ja seosetüüpide põhjal luuakse tabelid: Amet(ameti_kood, nimetus) Primaarvõti (ameti_kood) Alternatiivvõti (nimetus) Töötaja(isikukood, eesnimi, perenimi, sünniaeg, sugu, elukoht, ameti_kood) Primaarvõti (isikukood) Välisvõti (ameti_kood) Viitab Amet(ameti_kood) Miks on tabelis Töötaja välisvõtme veerg ameti_kood, aga mitte nimetus? Välisvõti peab viitama seotud tabeli kandidaatvõtmele (see tähendab, et seose loomiseks sobib nii ameti kood kui ka ameti nimetus), kuid levinud praktika on luua seos kasutades primaarvõtit. Välisvõtme ja seose loomiseks kasutatava kandidaatvõtme veergude andmetüübid peavad olema ühilduvad (ühte tüüpi). Kuna Töötaja osaluskohustus seosetüübis on kohustuslik (see tähendab, et iga töötaja peab olema seotud ühe ametiga, siis on tabeli Töötaja veerg ameti_kood kohustuslik veerg (sellele tuleb lisada NOT NULL kitsendus). Toote_klass toote_klassi_kood : Integer nimetus : String 0..1 0..* Toode toote_kood : String nimetus : String hind : Date Joonis 3 1:M binaarse seosetüübi näide. Joonis 3 kohaselt iseloomustab iga toodet null või üks toote klassi ja igasse toote klassi kuulub null või rohkem toodet. Joonis 3 esitatud olemitüüpide ja seosetüüpide põhjal luuakse tabelid: Toote_klass(toote_klassi_kood, nimetus) Primaarvõti (toote_klassi_kood) Alternatiivvõti (nimetus) Toode(toode_kood, nimetus, hind, toote_klassi_kood) Primaarvõti (toote_kood) Välisvõti (toote_klassi_kood) Viitab Toote_klass(toote_klassi_kood) Kuna olemitüübi Toode osaluskohustus seosetüübis on mittekohustuslik (see tähendab, et toode võib kuid ei pruugi olla seotud ühe toote klassiga), siis on tabeli Toode veerg toote_klassi_kood mittekohustuslik veerg (tabelis Toode olevas reas võib sellele veerule vastavas väljas väärtus puududa). 8

3.3.3 Nõrk olemitüüp Nõrga olemitüübi OT põhjal luuakse tabel T. Iga OT üheväärtuselise atribuudi põhjal lisatakse tabelisse T üks veerg. Veeru tüüp leitakse atribuudi tüübi põhjal. Primaarvõtit ei saa tabelis T enne määrata, kui on leitud T seosed teiste tabelitega. Tabeli T primaarvõti hõlmab välisvõtme veerge, mille abil luuakse seosed teiste tabelitega. Tellimus tellimuse_nr täitmise_aeg : Date 1 0..* Tellimuse_rida kogus : Integer hind : Currency 0..* 1 Toode toote_kood : String nimetus : String hind : Date Joonis 4 Olemi-suhte diagrammi näide. Joonis 4 esitatud diagrammil on tugevateks olemitüüpideks Tellimus ja Kaup ning nõrk olemitüüp on Tellimuse_rida. Tellimuse rida ei saa eksisteerida ilma tellimuseta, millesse see kuulub ja tooteta, mille tellimust see kirjeldab. Olemitüübi Tellimuse_rida põhjal loodud tabeli Tellimuse_rida primaarvõti hõlmab välisvõtme veerge, mille abil luuakse seos tabelitega Tellimus ja Toode. Tellimus (tellimuse_nr, täitmise_aeg) Primaarvõti (tellimuse_nr) Toode (toote_kood, nimetus, hind) Primaarvõti (toote_kood) Tellimuse_rida (tellimuse_nr, toote_kood, kogus, hind) Primaarvõti (tellimuse_nr, toote_kood) Välisvõti (tellimuse_nr) Viitab Tellimus (tellimuse_nr) Välisvõti (toote_kood) Viitab Toode (toote_kood) 3.3.4 M:N binaarne seosetüüp Mitu-mitmele binaarse seosetüübi põhjal, mis seob olemitüüpe OT1 ja OT2, tuleb luua vahetabel T. Selles tabelis peavad olema välisvõtme veerud, mille abil luuakse seosed OT1 ja OT2 põhjal loodud tabelitega. Tabeli T primaarvõti hõlmab eelnimetatud välisvõtme veerge ja võib vajadusel sisaldada täiendavaid veerge. 9

Õppejõud isikukood : String õpetamine 0..* 0..* Õppeaine ainekood : String Joonis 5 M:N binaarse seosetüübi näide. Joonis 5 kohaselt õpetab iga õppejõud nulli või rohkemat õppeainet. Iga õppeainet õpetab null või rohkem õppejõudu. Joonis 5 esitatud olemitüüpide ja seosetüüpide põhjal luuakse tabelid: Õppejõud (isikukood) Primaarvõti (isikukood) Õppeaine (ainekood) Primaarvõti (ainekood) Õpetamine (isikukood, ainekood) Primaarvõti (isikukood, ainekood) Välisvõti (isikukood) Viitab Õppejõud (isikukood) Välisvõti (ainekood) Viitab Õppeaine (ainekood) Seosetüüp võib olla modelleeritud eraldiseisva olemitüübina. Õppejõud isikukood : String õpetamine 0..* 0..* Õppeaine ainekood : String Õpetamine alguse_aeg : Date lõpu_aeg : Date Joonis 6 Sidemeklassi näide. Joonis 6 paiknev sidemeklass esitab täiendava kitsenduse, mille kohaselt võib iga õppejõud õpetada ühte ja sama õppeainet ainult üks kord. Seetõttu luuakse Joonis 6 esitatud olemitüüpide ja seosetüüpide põhjal tabelid: Õppejõud (isikukood) Primaarvõti (isikukood) Õppeaine (ainekood) Primaarvõti (ainekood) Õpetamine (isikukood, ainekood, alguse_aeg, lõpu_aeg) Primaarvõti (isikukood, ainekood) Välisvõti (isikukood) Viitab Õppejõud (isikukood) Välisvõti (ainekood) Viitab Õppeaine (ainekood) 10

Nagu näete, on tabelis Õpetamine primaarvõtmeks isikukoodi ja ainekoodi kombinatsioon. See tagab, et tabelis Õpetamine saab mistahes isikukoodi ja ainekoodi kombinatsioon olla maksimaalselt ühes reas. Õppejõud isikukood : String 1 0..* Õpetamine alguse_aeg : Date lõpu_aeg : Date 0..* 1 Õppeaine ainekood : String Joonis 7 Seosetüübi modelleerimine eraldi olemitüübina. Joonis 7 esitatud diagrammil kohaselt puudub kitsendus, et õppejõud võib õpetada õppeainet ainult üks kord. Seetõttu luuakse Joonis 7 esitatud olemitüüpide ja seosetüüpide põhjal tabelid: Õppejõud (isikukood) Primaarvõti (isikukood) Õppeaine (ainekood) Primaarvõti (ainekood) Õpetamine (isikukood, ainekood, alguse_aeg, lõpu_aeg) Primaarvõti (isikukood, ainekood, alguse_aeg) Välisvõti (isikukood) Viitab Õppejõud (isikukood) Välisvõti (ainekood) Viitab Õppeaine (ainekood) Nagu näete, hõlmab tabeli Õpetamine primaarvõti nüüd ka veergu alguse_aeg. Seetõttu on võimalik registreerida ühe õppejõu mitmekordsed õppeaine õpetamised, juhul kui need alanud erinevatel aegadel. Kui tabelit Õpetamine on kavas siduda mõne teise tabeliga, siis võib tabelis Õpetamine võtta kasutusele surrogaatvõtme, et vältida liitvälisvõtme tekkimist. Lihtvälisvõti hõlmab ühte veergu ning liitvälisvõti hõlmab rohkem kui ühte veergu. Õpetamine (õpetamine_id, isikukood, ainekood, alguse_aeg, lõpu_aeg) Primaarvõti (õpetamine_id) Alternatiivvõti (isikukood, ainekood, alguse_aeg) Välisvõti (isikukood) Viitab Õppejõud (isikukood) Välisvõti (ainekood) Viitab Õppeaine (ainekood) Kommentaar (õpetamine_id, tekst, lisamise_aeg) Primaarvõti (õpetamine_id, lisamise_aeg) Välisvõti (õpetamine) Viitab Õpetamine (õpetamine_id) Oletame, et soovime hakata registreerima õpetamiste kohta kommentaare. Tabelis Õpetamine on veerg õpetamine_id surrogaatvõtme veerg. Tabelis Kommentaar on välisvõti lihtvõti. Kui välisvõti on lihtvõti, siis see lihtsustab võrreldes liitvälisvõtmega päringute tegemist ja vähendab andmemahte. 11

Liitvälisvõtmete kasutamise muudab keerukamaks ka asjaolu, et SQL lubab välisvõtme deklareerimisel määrata, kui suures ulatuses peab välisvõtme väärtus vastama seotud tabeli kandidaatvõtme väärtusele. Võimalikud määrangud on MATCH SIMPLE (vaikimisi määrang), MATCH FULL ja MATCH PARTIAL. Määrang omab sisulist mõju, kui välisvõti on liitvõti ja välisvõtme poolt hõlmatud veerud on mittekohustusliku (seal on lubatud NULLid). Kui kasutate liitvälisvõtit soovitame kasutades määrangut MATCH FULL. Sellisel juhul peab tabelis olev välisvõtme väärtus olema kas täiesti määramata (kõikidele välisvõtme veergudele vastavates väljades on NULLid) või võrduma seotud tabeli mõne kandidaatvõtme väärtusega. MATCH SIMPLE ja MATCH PARTIAL võimaldavad kasutada tabelites välisvõtme väärtuseid, mis ainult osaliselt vastavad mõne seotud tabeli kandidaatvõtme väärtusele. 3.3.5 1:1 binaarne seosetüüp Juhul kui tegemist on seosetüübiga, mille osaluskohustus on mõlemas otsas kohustuslik, siis luuakse seosetüübis osalevate olemitüüpide põhjal üks tabel. Tabeli primaarvõti leitakse ühe olemitüübi unikaalse identifikaatori põhjal. Ülejäänud unikaalsete identifikaatorite põhjal leitakse alternatiivvõtmed. Juhul, kui kahe olemitüübi vahel on lisaks 1:1 seosetüübile ka 1:M seosetüüp, siis luuakse ikkagi kaks eraldi tabelit. Leping lepingu_nr : Integer kehtivuse_algus : Date 1 koostatakse 1 Arve arve_nr : Integer summa : Currency tasumistähtaeg : Date +koostamise alus Joonis 8 1:1 binaarse seosetüübi näide. +koostamise tulemus Joonis 8 kohaselt koostatakse iga lepingu alusel täpselt üks arve ja iga arve koostatakse täpselt ühe lepingu alusel. Joonis 8 esitatud olemitüüpide ja seosetüüpide põhjal luuakse tabelid: Leping (lepingu_nr, kehtivuse_algus, arve_nr, summa, tasumistähtaeg) Primaarvõti (lepingu_nr) Alternatiivvõti(arve_nr) Juhul kui tegemist on seosetüübiga, mille osaluskohustus on ühes otsas kohustuslik ja teises otsas mittekohustuslik, siis luuakse seosetüübis osalevate olemitüüpide põhjal kaks eraldi tabelit. Seose loomiseks vajalikud välisvõtme veerud tuleb lisada tabelisse, millele vastava olemitüübi jaoks on vaadeldav seosetüüp kohustuslik. 12

Leping lepingu_nr : Integer kehtivuse_algus : Date 1 koostatakse 0..1 Arve arve_nr : Integer summa : Currency tasumistähtaeg : Date +koostamise alus Joonis 9 1:1 binaarse seosetüübi näide. +koostamise tulemus Joonis 9 kohaselt koostatakse iga lepingu alusel null või üks arvet ja iga arve koostatakse täpselt ühe lepingu alusel. Joonis 9 esitatud olemitüüpide ja seosetüüpide põhjal luuakse tabelid: Leping (lepingu_nr, kehtivuse_algus) Primaarvõti (lepingu_nr) Arve (arve_nr, lepingu_nr, summa, tasumistähtaeg) Primaarvõti(arve_nr) Alternatiivvõti (lepingu_nr) Välisvõti (lepingu_nr) Viitab Leping (lepingu_nr) Pange tähele, et tabelisse Arve lisatud välisvõtme veerud kuuluvad ka alternatiivvõtmesse. Tabeli Arve veerule lepingu_nr tuleb SQL-andmebaasis lisada unikaalsuse kitsendus (UNIQUE), et iga lepinguga saaks siduda maksimaalselt ühe arve. Tabeli Arve veerule lepingu_nr tuleb SQL-andmebaasis lisada kohustuslikkuse kitsendus (NOT NULL), et igal arvel oleks seotud leping. Lahendi valiku tingib soov vältida tabelite veergudes NULLide kasutamist. Kui lisada tabelisse Leping välisvõtmena veerg arve_nr, siis: Tabelis Leping võib mõnes reas arve number puududa. Eeldame, arve tekib peale lepingu sõlmimist ja registreerimist. Uue arve registreerimisel tuleb lisada rida tabelisse Arve ja muuta rida tabelis Leping (et luua seos arve ja lepingu vahel). Kui tabelis Arve on välisvõtmena veerg lepingu_nr, siis piisab rea lisamisest tabelisse Arve. Juhul kui tegemist on seosetüübiga, mille osaluskohustus on mõlemas otsas mittekohustuslik, siis kummagi olemitüübi põhjal luuakse eraldi tabel. Välisvõti tuleks lisada sellesse tabelisse, millesse lisatakse andmed hiljem. Kui pole informatsiooni tabelitesse andmete lisamise järjekorra kohta, siis on vaba valik, kumma olemitüübi alusel loodud tabelisse välisvõti lisada. Juhime tähelepanu, et välisvõti läheb ainult ühte nendest tabelitest. SQL-andmebaasis tuleb välisvõtme poolt hõlmatud veergudele lisada unikaalsuse kitsendus, et tagada 1:1 seos. Samas peavad välisvõtme poolt hõlmatud veerud olema mittekohustuslikud. 13

Leping lepingu_nr : Integer kehtivuse_algus : Date 0..1 koostatakse 0..1 Arve arve_nr : Integer summa : Currency tasumistähtaeg : Date +koostamise alus Joonis 10 1:1 binaarse seosetüübi näide. +koostamise tulemus Joonis 10 kohaselt koostatakse iga lepingu alusel null või üks arvet ja iga arve koostatakse null või ühe lepingu alusel. Joonis 10 esitatud olemitüüpide ja seosetüüpide põhjal luuakse tabelid: Leping (lepingu_nr, kehtivuse_algus) Primaarvõti (lepingu_nr) Arve (arve_nr, lepingu_nr, summa, tasumistähtaeg) Primaarvõti(arve_nr) Välisvõti (lepingu_nr) Viitab Leping (lepingu_nr) Kui leping luuakse üldjuhul enne arvet, siis tuleks välisvõti paigutada olemitüübi Arve põhjal loodud tabelisse. (lepingu_nr) ei ole tabelis Arve alternatiivvõti, sest võib leiduda arveid, mille korral lepingu number ei ole teada. Samas peab tabelis Arve olema loodud veerule lepingu_nr unikaalsuse kitsendus, sest iga leping saab olla seotud maksimaalselt ühe arvega. 3.3.6 Rekursiivne seosetüüp Rekursiivse seosetüübi mõlemas otsas on sama olemitüüp (OT) (erinevates rollides). Rekursiivse seosetüübi korral luuakse olemitüübi OT põhjal üks tabel T. Rekursiivne seosetüüp kontseptuaalses andmemudelis näitab, et andmebaasis soovitakse hoida andmeid mingit tüüpi hierarhiate või võrkstruktuuri moodustavate seoste kohta. 3.3.6.1 1:1 rekursiivne seosetüüp Isik isikukood : String perenimi : String +jälgija 1 1 +jälgitav Joonis 11 1:1 rekursiivse seosetüübi näide. Kui seosetüübi osaluskohustus on mõlemas otsas kohustuslik, siis tuleb: 14

lisada tabelisse T välivõti, mis võib omada ainult sama tabeli primaarvõtme väärtuseid. Välisvõtme veergudele tuleb anda nende tähendust täpsemalt kirjeldav nimi. Välisvõtme veergude nimed peavad erinema primaarvõtme veergude nimedest, sest tabelis ei tohi olla ühenimelisi veerge. Veergude nimetamisel võib kasutada rollide nimesid, mis kirjeldavad olemitüübi rolli seosetüübi kontekstis. välisvõtme poolt hõlmatud veerud moodustavad ka alternatiivvõtme. Joonis 11 kohaselt on igal isikul täpselt üks jälgija, kes tema tegevusi jälgib ja täpselt üks jälgitav kelle tegevusi isik ise jälgib. Joonis 11 esitatud olemitüübi ja seosetüübi põhjal luuakse järgnev tabel: Isik (isikukood, perenimi, jälgija) Primaarvõti (isikukood) Alternatiivvõti (jälgija) Välisvõti (jälgija) Viitab Isik(isikukood) Isik isikukood : String perenimi : String +juhendatav 0..1 +juhendaja 0..1 Joonis 12 1:1 rekursiivse seosetüübi näide. Kui seosetüübi osaluskohustus on mõlemas otsas mittekohustuslik, siis tuleb seosetüübi põhjal luua tabel, milles on kaks välisvõtit. Joonis 12 kohaselt on igal isikul null või üks juhendajat ja null või üks juhendatavat (keda see isik ise juhendab). Joonis 12 esitatud olemitüübi ja seosetüübi põhjal luuakse järgnevad tabelid: Isik (isikukood, perenimi) Primaarvõti (isikukood) Juhendamine (juhendaja, juhendatav) Primaarvõti (juhendaja) Alternatiivvõti (juhendatav) Välisvõti (juhendaja) Viitab Isik(isikukood) Välisvõti (juhendatav) Viitab Isik(isikukood) Primaarvõti peab hõlmama kas veergu juhendaja või juhendatav. Õigupoolest on see näide olukorrast, kus on raske ühte võtit teisele eelistada ja primaarseks kuulutada. Kui seosetüübi osaluskohustus on ühes otsas kohustuslik ja teises otsas mittekohustuslik, siis tuleb valida üks eelnevalt väljapakutud kahest lahendusest. 15

3.3.6.2 1:M rekursiivne seosetüüp Üks-mitmele rekursiivse seosetüübi korral lisatakse tabelisse T välisvõti, mis võib omada ainult sama tabeli primaarvõtme väärtuseid. Välisvõtme veergudele tuleb anda nende tähendust täpsemalt kirjeldav nimi. Isik isikukood : String perenimi : String +juhendatav 0..* +juhendaja 0..1 Joonis 13 1:M rekursiivse seosetüübi näide. Joonis 13 kohaselt on igal isikul null või üks juhendajat ning null või rohkem juhendatavat. Joonis 13 esitatud olemitüübi ja seosetüübi põhjal luuakse järgnev tabel: Isik (isikukood, perenimi, juhendaja) Primaarvõti (isikukood) Välisvõti (juhendaja) Viitab Isik(isikukood) 3.3.6.3 M:N rekursiivne seosetüüp Mitu-mitmele rekursiivse seosetüübi korral luuakse seosetüübi põhjal tabel, milles on kaks välisvõtit. Isik isikukood : String perenimi : String +juhendatav 0..* +juhendaja 0..* Joonis 14 M:N rekursiivse seosetüübi näide. Joonis 14 kohaselt on igal isikul null või rohkem juhendajat ja null või rohkem juhendatavat. Joonis 14 esitatud olemitüübi ja seosetüübi põhjal luuakse järgnevad tabelid: 16

Isik (isikukood, perenimi) Primaarvõti (isikukood) Juhendamine (juhendaja, juhendatav) Primaarvõti (juhendaja, juhendatav) Välisvõti (juhendaja) Viitab Isik(isikukood) Välisvõti (juhendatav) Viitab Isik(isikukood) 3.3.7 Üldistusseos Isik isikukood : String eesnimi : String perenimi : String sünniaeg : Date elukoht : String Üliõpilane üliõpilaskood : String Töötaja 0..* 1 Amet ameti_kood : Integer nimetus : String Joonis 15 Üldistusseose näide. Joonis 15 kohaselt on üliõpilane isik ja töötaja on isik. Isik on ülatüüp ning Üliõpilane ja Töötaja tema alamtüübid. Üldistusseosega seotud olemitüüpide põhjal tabelite leidmisel tuleb võtta arvesse üldistusseosega seotud kitsendused. Lisaks võib võtta arvesse üla- ja alamtüüpide atribuutide ja seosetüüpide arvud. Järgnevad disaini soovitused põhinevad ainult üldistusseosega seotud kitsendustel ning need pakkusid välja Connolly ja Begg (2002). Kõikide järgnevate üldistusseose põhjal tabelite leidmise näidete korral tuleb luua tabel Amet. Selle tabeli kirjeldust järgnevates näidetes ei korrata. Amet (ameti_kood, nimetus) Primaarvõti (ameti_kood) Alternatiivvõti (nimetus) 17

3.3.7.1 Variant 1 {Optional; Or} Osaluskohutus: {Optional}. Iga ülatüüpi kuuluv olem ei pea kuuluma mõnda alamtüüpi. Näiteks võib leiduda isikuid, kes ei ole ei üliõpilased ega töötajad. Kuuluvus: {Or}. Iga ülatüüpi olem võib kuuluda maksimaalselt ühte alamtüüpi. Näiteks iga isik võib olla kas üliõpilane või töötaja, aga mitte mõlemat korraga. Kokkuvõtlikult, iga ülatüüpi kuuluv olem kuulub nulli või ühte alamtüüpi. Variandi 1 puhul soovitavad Connolly ja Begg (2002) luua ülatüübile vastav tabel, mis sisaldab ülatüübi atribuutidele vastavaid veerge. Iga alamtüüpi kohta tuleb luua üks tabel, mis sisaldab vastava alamtüübi atribuutidele vastavaid veerge. Alamtüüpide põhjal loodud tabelitesse tuleb lisada välisvõtme veerud, et luua seos ülatüübi põhjal loodud tabeliga. Need veerud on ühtlasi ka primaarvõtme veerud. Joonis 15 esitatud olemitüüpide ja seosetüüpide põhjal luuakse tabelid: Isik (isikukood, eesnimi, perenimi, sünniaeg, elukoht) Primaarvõti (isikukood) Üliõpilane (isikukood, üliõpilaskood) Primaarvõti (isikukood) Alternatiivvõti(üliõpilaskood) Välisvõti (isikukood) Viitab Isik(isikukood) Töötaja (isikukood, ameti_kood) Primaarvõti (isikukood) Välisvõti (isikukood) Viitab Isik(isikukood) Välisvõti (ameti_kood) Viitab Amet (ameti_kood) SQL-andmebaasisüsteemi pakutavate vahenditega (deklaratiivsed kitsendused, trigerid) tuleb tagada, et iga isiku andmeid saab registreerida maksimaalselt ühes alamtüüpide põhjal loodud tabelis. Pakutud variant võimaldab registreerida andmed isikute kohta, kes pole ühtegi alamtüüpi, tabelis Isik. Kui isik on mõnda alamtüüpi, siis registreeritakse tema andmed tabelis Isik ja lisaks veel ühele alamtüübile vastavas tabelis. 3.3.7.2 Variant 2 {Mandatory; And} Osaluskohutus: {Mandatory}. Iga ülatüüpi olem peab kuuluma ka mõnda alamtüüpi. Näiteks isik peab olema kas üliõpilane või töötaja. Kuuluvus: {And}. Iga ülatüüpi olem võib kuuluda mitmesse alamtüüpi. Näiteks isik võib olla korraga nii üliõpilane kui ka töötaja. 18

Kokkuvõtlikult, iga ülatüüpi kuuluv olem kuulub ühte või rohkemasse alamtüüpi. Variandi 2 puhul soovitavad Connolly ja Begg (2002) luua ülatüübi ja sellega seotud alamtüüpide põhjal ühe tabeli: Loodava tabeli nimi tuletatakse ülatüübi nimest. Loodav tabel sisaldab nii ülatüübi, kui ka kõigi alamtüüpide atribuutidele vastavaid veerge. Kõik alamtüüpide atribuutide põhjal leitud veerud peavad olema mittekohustuslikud. See tähendab, et nendele vastavates ridade väljades võivad väärtused puududa. Iga alamtüübi kohta lisatakse tabelisse kohustuslik (NOT NULL kitsendusega) tõeväärtuse tüüpi veerg, milles olev väärtus näitab, kas ülatüüpi olem kuulub vastavasse alamtüüpi. Selliste veergude nimed tuletatakse alamtüüpide nimedest. Joonis 15 esitatud olemitüüpide ja seosetüüpide põhjal luuakse tabel: Isik (isikukood, eesnimi, perenimi, sünniaeg, elukoht, üliõpilaskood, ameti_kood, on_üliõpilane, on_töötaja) Primaarvõti (isikukood) Välisvõti (ameti_kood) Viitab Amet (ameti_kood) Üliõpilaskoodi ei saa näiteks primaarvõtmeks ega alternatiivvõtmeks valida, sest kõik selles tabelis registreeritavad isikud ei pruugi olla üliõpilased ja neil ei ole üliõpilaskoodi. SQL-andmebaasisüsteemi pakutavate vahenditega (deklaratiivsed kitsendused, trigerid) tuleb tagada, et iga tabelis Isik oleva rea puhul on vähemalt ühes alamtüübi määramiseks mõeldud veerule (antud juhul on_üliopilane, on_töötaja) vastavas väljas väärtus TRUE. Esitatud lahenduse negatiivseks küljeks on mittekohustuslike veergude tekkimine tabelisse Isik. Seega on tabeli kasutajad sunnitud kokku puutuma NULLidega ja SQLi kolmevalentse loogikaga. Soovitame sellises olukorras kasutada hoopis varianti nr. 1. Lisaks tuleb andmebaasis jõustada kitsendus, et iga ülatüüpi olem peab kuuluma ühte või rohkemasse alamtüüpi. Kui iga ülatüüpi olem peab kuuluma ka kõikidesse alamtüüpidesse, siis võib ka kasutada lahendust, mille kohaselt luuakse eraldi tabel nii ülatüübi kui ka iga alamtüübi põhjal. Alamtüüpidest tekkinud tabelid ühendatakse välisvõtme kaudu ülatüübist tekkinud tabeliga. Välisvõtme veerud lisatakse ülatüübi põhjal loodud tabelisse. Need välivõtme veerud kuuluvad ka alternatiivvõtmetesse. Joonis 15 esitatud olemitüüpide ja seosetüüpide põhjal luuakse sellisel juhul tabelid: Üliõpilane (üliõpilaskood) Primaarvõti (üliõpilaskood) 19

Töötaja (töötaja_id, ameti_kood) Primaarvõti (töötaja_id) Välisvõti (ameti_kood) Viitab Amet (ameti_kood) Isik (isikukood, eesnimi, perenimi, sünniaeg, elukoht, üliõpilaskood, töötaja_id) Primaarvõti (isikukood) Alternatiivvõti (üliõpilaskood) Alternatiivvõti (töötaja_id) Välisvõti (üliõpilaskood) Viitab Üliõpilane (üliõpilaskood) Välisvõti (töötaja_id) Viitab Töötaja (töötaja_id) Veel üks variant on kasutada sama tabelite struktuuri kui {Optional; Or} korral koos kitsendusega, mis kontrolliks, et isiku andmed on vähemalt ühes tabelis alamtüübile vastavate tabelite seas. 3.3.7.3 Variant 3 {Optional; And} Osaluskohutus: {Optional}. Iga ülatüüpi kuuluv olem ei pea kuuluma mõnda alamtüüpi. Näiteks võib leiduda isikuid, kes ei ole ei üliõpilased ega töötajad. Kuuluvus: {And}. Iga ülatüüpi olem võib kuuluda mitmesse alamtüüpi. Näiteks isik võib olla korraga nii üliõpilane kui ka töötaja. Kokkuvõtlikult, iga ülatüüpi kuuluv olem kuulub nulli või rohkemasse alamtüüpi. Variandi 3 puhul soovitavad Connolly ja Begg (2002) luua kaks tabelit. Üks nendest sisaldab ülatüübi atribuutidele vastavaid veerge. Teine sisaldab kõikide alamtüüpide atribuutidele vastavaid veerge. Kõik alamtüüpide atribuutide põhjal leitud veerud peavad olema mittekohustuslikud. Tabelite nimed tuleb tuletada ülatüübi nimest. Lisaks lisatakse alamtüüpide põhjal loodud tabelisse iga alamtüübi kohta kohustuslik (NOT NULL kitsendusega) tõeväärtuse tüüpi veerg, milles olev väärtus näitab, kas ülatüüpi olem kuulub vastavasse alamtüüpi. Selliste veergude nimed tuletatakse alamtüüpide nimedest. Alamtüüpide põhjal loodud tabelisse tuleb lisada välisvõtme veerud, et luua seos ülatüübi põhjal loodud tabeliga. Need veerud on ühtlasi ka primaarvõtme veerud Joonis 15 esitatud olemitüüpide ja seosetüüpide põhjal luuakse tabelid: Isik (isikukood, eesnimi, perenimi, sünniaeg, elukoht) Primaarvõti (isikukood) Isiku_detail (isikukood, üliõpilaskood, ameti_kood, on_üliõpilane, on_töötaja) Primaarvõti (isikukood) Välisvõti (isikukood) Viitab Isik(isikukood) Välisvõti (ameti_kood) Viitab Amet (ameti_kood) 20

Sellise lahenduse negatiivseks küljeks on mittekohustuslike veergude tekkimine tabelisse Isiku_detail. Seega on tabeli kasutajad sunnitud kokku puutuma NULLidega ja SQLi kolmevalentse loogikaga. Soovitame sellises olukorras kasutada hoopis sama tabelite struktuuri kui {Optional; Or} korral. 3.3.7.4 Variant 4 {Mandatory; Or} Osaluskohutus: kohustuslik: {Mandatory}. Iga ülatüüpi olem peab kuuluma ka mõnda alamtüüpi. Näiteks isik peab olema kas üliõpilane või töötaja. Kuuluvus: {Or}. Iga ülatüüpi olem võib kuuluda vaid ühte alamtüüpi. Näiteks iga isik võib olla kas üliõpilane või töötaja, aga mitte mõlemat korraga. Kokkuvõtlikult, iga ülatüüpi kuuluv olem kuulub täpselt ühte alamtüüpi. Variandi 4 puhul soovitavad Connolly ja Begg (2002) luua iga alamtüübi kohta eraldi tabeli, mis sisaldab nii ülatüübi atribuutidele vastavaid veerge, kui ka vastava alamtüübi atribuutidele vastavaid veerge. Tabelite nimed tuletatakse alamtüüpide nimedest. Ülatüübi põhjal eraldi tabelit ei looda. Joonis 15 esitatud olemitüüpide ja seosetüüpide põhjal luuakse tabelid: Üliõpilane (isikukood, eesnimi, perenimi, sünniaeg, elukoht, üliõpilaskood) Primaarvõti (isikukood) Alternatiivvõti (üliõpilaskood) Töötaja (isikukood, eesnimi, perenimi, sünniaeg, elukoht, ameti_kood) Primaarvõti (isikukood) Välisvõti (ameti_kood) Viitab Amet (ameti_kood) SQL-andmebaasisüsteemi pakutavate vahenditega (deklaratiivsed kitsendused, trigerid) tuleb tagada, et ühe ja sama isiku andmeid ei sisestataks erinevatesse alamtüüpide põhjal loodud tabelitesse. Vastasel juhul ei ole täidetud ortogonaalse andmebaasi disaini printsiip. Järgnev soovitus ei tulene üldistusseosega seotud kitsendustest kui kontseptuaalses andmemudelis on ülatüübi tasemel seosetüübid (näiteks seosetüüp, mille üks osaline on Isik), siis võiks ikkagi kaaluda sama tabelite struktuuri kasutamist kui {Optional; Or} korral näiteks luua eraldi tabelid Isik, Töötaja ja Üliõpilane. 3.3.8 Seosetüüp, mille aste on kahest suurem Seosetüüpi, mille aste on kahest suurem, võib esitada luues seosetüübi põhjal olemitüübi. Sellisel juhul saame kasutada binaarseid seosetüüpe ning tabelite leidmiseks saame kasutada binaarsete seosetüüpide kohta antud soovitusi. 21

Isik isikukood : String 1 Projekt projekti_kood : Integer 1 0..* Osalemine alguse_aeg : Date lõpu_aeg : Date 0..* 0..* 1 Roll rolli_kood : Integer Joonis 16 Ternaarse seosetüübi esitamise näide. Joonis 16 kohaselt osalevad isikud projektides mingites rollides. Olemitüüp Osalemine esitab seosetüüpi, mille aste on kolm. Joonis 16 esitatud olemitüüpide ja seosetüüpide põhjal luuakse tabelid: Isik (isikukood) Primaarvõti (isikukood) Projekt (projekti_kood) Primaarvõti (projekti_kood) Roll (rolli_kood) Primaarvõti (rolli_kood) Osalemine (isikukood, projekti_kood, rolli_kood, alguse_aeg, lõpu_aeg) Primaarvõti (isikukood, projekti_kood, rolli_kood, alguse_aeg) Välisvõti (isikukood) Viitab Isik (isikukood) Välisvõti (projekti_kood) Viitab Projekt (projekti_kood) Välisvõti (rolli_kood) Viitab Roll (rolli_kood) 3.3.9 Välistav kaar Joonis 17 kohaselt peab iga lepingu rida olema seotud kas teenuse või kaubaga, aga ei saa olla korraga seotud mõlemaga. Vastavate seosetüüpide kaarepoolses otsas asub olemitüüp Lepingu_rida. Kaarega seotud seosetüüpide realiseerimiseks on andmebaasi kavandajal erinevaid võimalusi. 22

Leping lepingu_kood : Integer solmimise_kp : Date 1 1..* Lepingu_rida kogus : Integer hind : Currency 0..* {XOR} 0..* 0..1 Kaup kauba_kood : Integer nimi : String hind : Currency kogus_laos : Integer 0..1 Teenus teenuse_kood : Integer nimi : String hind : Currency Joonis 17 Välistava kaare näide. 3.3.9.1 Täieliku/tõelise kaare lahendus Täieliku/tõelise kaare lahenduse korral toimitakse järgnevalt: Iga kaarega hõlmatud seosetüübi kohta tekitatakse eraldi mittekohustuslik veergude hulk seosetüübi kaarepoolses otsas asuva olemitüübi põhjal loodavas tabelis. Need veerud on ühtlasi ka välisvõtme veerud. Kaare loogika (ühes reas tohivad olla väärtused vaid ühele eelnimetatud veergude hulgale vastavates väljades) tuleb realiseerida kasutades SQL-andmebaasisüsteemi pakutavaid vahendeid (deklaratiivsed kitsendused, trigerid). Joonis 17 esitatud olemitüüpide ja seosetüüpide põhjal luuakse tabelid: Leping (lepingu_kood, solmimise_kp) Primaarvõti (lepingu_kood) Teenus (teenuse_kood, nimi, hind) Primaarvõti (teenuse_kood) Kaup (kauba_kood, nimi, hind, kogus_laos) Primaarvõti (kauba_kood) Lepingu_rida (rea_kood, teenuse_kood, kauba_kood, lepingu_kood, kogus, hind) Primaarvõti (rea_kood) Välisvõti (teenuse_kood) Viitab Teenus(teenuse_kood) Välisvõti (kauba_kood) Viitab Kaup(kauba_kood) Välisvõti (lepingu_kood) Viitab Leping(lepingu_kood) 23

Nagu näete, on tabelis Lepingu_rida kaks välisvõtit, mille abil luuakse vastavalt seos tabelitega Kaup ja Teenus. Tabelis Lepingu_rida peavad veerud teenuse_kood ja kauba_kood olema mittekohustuslikud. (rea_kood) on surrogaatvõti. SQL-andmebaasisüsteemi pakutavate vahenditega (deklaratiivsed kitsendused, trigerid) tuleb tagada, et igal lepingul on vähemalt üks rida. 3.3.9.2 Kaare lõhkumise lahendus Kaare lõhkumise lahenduse korral luuakse iga kaarega hõlmatud seosetüübi kohta eraldi tabel. Sellise lahenduse kasutamine on eelistatum, sest ei teki tabeleid kus on lubatud NULLid nagu täieliku/tõelise kaare lahenduse puhul. Tänu sellele pole tabelites Teenuse_lepingu_rida ja Kauba_lepingu_rida vaja primaarvõtme veergu rea_kood, vaid saame kasutada liitvõtit (tuletage meelde olemi terviklikkuse reeglit) Joonis 17 esitatud olemitüüpide ja seosetüüpide põhjal luuakse tabelid: Leping (lepingu_kood, solmimise_kp) Primaarvõti (lepingu_kood) Teenus (teenuse_kood, nimi, hind) Primaarvõti (teenuse_kood) Kaup (kauba_kood, nimi, hind, kogus_laos) Primaarvõti (kauba_kood) Teenuse_lepingu_rida (teenuse_kood, lepingu_kood, kogus, hind) Primaarvõti (teenuse_kood, lepingu_kood) Välisvõti (teenuse_kood) Viitab Teenus(teenuse_kood) Välisvõti (lepingu_kood) Viitab Leping(lepingu_kood) Kauba_lepingu_rida (kauba_kood, lepingu_kood, kogus, hind) Primaarvõti(kauba_kood, lepingu_kood) Välisvõti (kauba_kood) Viitab Kaup(kauba_kood) Välisvõti (lepingu_kood) Viitab Leping(lepingu_kood) SQL-andmebaasisüsteemi pakutavate vahenditega (deklaratiivsed kitsendused, trigerid) tuleb tagada, et igal lepingul on vähemalt üks rida. 3.3.9.3 Ühise / üldise kaare lahendus Ühise/üldise kaare lahenduse korral lisatakse seosetüübi kaarepoolsest otsast tekitatud tabelisse kaks uut kohustuslikku veergu. Nendele veergudel vastavate väljade väärtused: Seosetüübi teises otsas oleva tabeli nimi. 24

Sama tabeli primaarvõtme väärtus (kui primaarvõtmed on unikaalsed üle kõigi kaarega hõlmatud seosetüübiga seotud tabelite, võib tabelite nimede jaoks mõeldud veeru ära jätta). Leping (lepingu_kood, solmimise_kp) Primaarvõti (lepingu_kood) Teenus (teenuse_kood, nimi, hind) Primaarvõti (teenuse_kood) Kaup (kauba_kood, nimi, hind, kogus_laos) Primaarvõti (kauba_kood) Lepingu_rida (rea_kood, element, tüüp, kogus, hind, lepingu_kood) Primaarvõti (rea_kood) Alternatiivvõti (lepingu_kood, element, tüüp) Välisvõti (lepingu_kood) Viitab Leping(lepingu_kood) kauba_kood nimi hind kogus_laos K_1 Sony teler 5000 5 K_2 Panasonicu teler 4500 3 K_3 Samsungi teler 4700 10 teenuse_kood nimi hind K_1 Pakkimine 50 T_2 Kojuvedu 150 rea_kood element tüüp kogus hind lepingu_ kood 1 K_1 K 2 10000 1 2 K_1 T 1 50 1 3 K_2 K 1 4500 2 Tabeli Lepingu_rida veerus tüüp on kas väärtus "T" (nagu teenus) või "K" (nagu kaup). Veergude element ja tüüp puhul tuleb programmeerida kontrollprogrammid, mis tagavad viidete terviklikkuse reeglite täidetuse. Kuna see on töömahukas (ja suureneb vigade tegemise võimalus), siis soovitame ühise/üldise kaare lahendusest hoiduda. 3.3.10 Mitmeväärtuseline atribuut Mõnikord proovivad SQL-andmebaasi kavandajad luua mitmeväärtuselise atribuudi põhjal niinimetatud veergude grupi. 25

Vaatame selle kohta näidet. Igal töötajal on null või rohkem telefoninumbrit, millele helistades saab töötajaga kontakti võtta. Oletame, et olemitüübis Töötaja on mitmeväärtuseline atribuut telefon. Järgnevalt on esitatud võimalik tabel, mis sellise olemitüübi põhjal loogilise disaini käigus leitakse. Nagu näete, on tabelis telefonide andmete registreerimiseks veerud telefon1, telefon2 ja telefon3. Töötaja (isikukood, perenimi, telefon1, telefon2, telefon3) Primaarvõti (isikukood) Sellise tabeli kasutamine pole hea lahendus (Celko, 2000). Mõned küsimused, mida võib endale esitada: Mis saab siis, kui töötajal on vähem kui kolm telefoninumbrit? Me võime kasutada mõnele veerule vastavates väljades NULLe, kuid siis tekivad probleemid, mis seotud SQLi kolmevalentse loogikaga. Mis saab siis, kui töötajal on rohkem kui kolm telefoninumbrit? Tuleb muuta tabeli struktuuri, lisades sinna näiteks uue veeru telefon4. Mis saab siis, kui on vaja andmebaasi täiendada ja hakata registreerima infot selle kohta, milliselt telefonilt saab inimest kergemini kätte ja milliselt raskemalt? Tabeli struktuuri tuleb muuta, lisades iga telefoni andmete hoidmiseks mõeldud veeru kohta tabelisse veel ühe veeru. Kitsenduste jõustamine on keeruline. Näiteks väga raske oleks jõustada kitsendust, et iga telefoninumber võib olla seotud ainult ühe töötajaga või ka kitsendust, et konkreetne telefoninumber tohib olla seotud konkreetse töötajaga ainult üks kord. Andmete otsimine nõuab keeruka ja mahuka süntaksiga päringute kasutamist. Näiteks olgu meil ülesanne: "Leidke kõik telefoninumbrid, mis algavad numbriga 6 ja isikud, kellega need telefoninumbrid on seotud". Ülesande lahendamiseks tuleb SQLis kirjutada järgnev hulgateoreetilise summa leidmise operaatorit kasutav päring: SELECT isikukood, perenimi, telefon1 AS telefon FROM Töötaja WHERE telefon1 LIKE '6%' UNION SELECT isikukood, perenimi, telefon2 AS telefon FROM Töötaja WHERE telefon2 LIKE '6%' UNION SELECT isikukood, perenimi, telefon3 AS telefon FROM Töötaja WHERE telefon3 LIKE '6%'; Mida rohkem on telefoni andmete hoidmiseks mõeldud veerge, seda mahukamaks see päring muutub. Kui lisandub uusi telefonide andmete registreerimiseks mõeldud veerge või mõni olemasolev veerg kustutatakse, siis tuleb muuta ka telefonide andmete otsimiseks mõeldud päringuid. 26

Parem lahendus oleks luua olemitüübi OT mitmeväärtuselise atribuudi alusel uus tabel. See sisaldab välisvõtmena ka olemitüübi OT alusel loodud tabeli primaarvõtmele vastavat veergu. Töötaja (isikukood, perenimi) Primaarvõti (isikukood) Telefon (isikukood, telefon) Primaarvõti (isikukood, telefon) Välisvõti (isikukood) Viitab Töötaja(isikukood) See disain on kergelt muudetav, kui muutuvad telefoninumbritega seotud reeglid. Kui kehtestatakse reegel, et igal töötajal on maksimaalselt üks telefoninumber, siis tuleb tabelis Telefon deklareerida unikaalseks (isikukood). Kui kehtestatakse reegel, et iga telefoninumber tohib olla seotud ainult ühe töötajaga, siis tuleb tabelis Telefon deklareerida unikaalseks (telefon). Mõlemal juhul tuleb muuta ka tabeli Telefon primaarvõtit, et vältida supervõtme deklareerimist (vt teema 5). Eelnevalt kirjeldatud otsinguülesande saab nende tabelite põhjal lahendada kasutades järgnevat ühendamise operaatori poole pöördumist sisaldavat SQL lauset. SELECT isikukood, perenimi, telefon FROM Töötaja INNER JOIN Telefon ON Töötaja.isikukood=Telefon.isikukood WHERE telefon LIKE '6%'; Seda lauset ei tule muuta vastavalt maksimaalsele töötajale lubatud telefonide arvule. Seda lauset sobib kasutada nii siis, kui töötajatel on maksimaalselt kaks telefoni kui ka siis, kui töötajatel on maksimaalselt kümme telefoni. SQLi viimastel aastatel tehtud laiendused (objekt-relatsioonilisuse omadused) võimaldavad tabelites kasutada veerge mis on konstrueeritud multihulga tüüpi (inglise keeles multiset) või konstrueeritud massiivitüüpi. Sellist tüüpi veergude kasutamine on samuti üheks võimaluseks, kuidas mitmeväärtuselisi atribuute andmebaasis realiseerida. 3.4 Kitsenduste kirjeldamine Samaaegselt tabelite kirjeldamisega, toimub loogilise andmebaasi disaini käigus andmebaasis jõustatavate kitsenduste kirjeldamine. Need kitsendused tulenevad kontseptuaalses andmemudelis kirjeldatud kitsendustest. Primaarvõtmed leitakse unikaalsete identifikaatorite põhjal. Unikaalsuse nõuded leitakse unikaalsete identifikaatorite põhjal. Välisvõtmed tulenevad seosetüüpidest. 27

Veergude kohustuslikkuse nõuded tulenevad unikaalsetest identifikaatoritest, seosetüüpidega seotud kohustuslikkuse nõuetest või täiendavatest kasutajate nõudmistest. Samuti tuleb loogilise disaini käigus uurida, kuidas jõustada andmebaasi kontseptuaalses andmemudelis kirjeldatud täiendavad kitsendused. Miks ikkagi kontrollida andmete kitsendustele vastavust andmebaasi tasemel? Vastavad kontrollid võiks ju kirjutada sisse loodavasse rakendusse. Andmete kitsendustele vastavuse kontroll ainult andmebaasi kasutavas rakenduses ei ole hea mõte: Kui andmebaasi hakkab kasutama uus rakendus, tuleb sellesse kitsenduste kontroll sisse kirjutada. Sellest tulenevalt: o Kui rakenduste arv suureneb, muutub ka raskemaks kitsenduste muutmine (muudatus tuleb sisse viia mitmesse kohta). o Arendaja peab tegema lisatööd, realiseerides kitsenduste kontrolli kasutades erinevaid keeli, mida rakenduste loomiseks kasutatakse. o Arendaja võib unustada kitsenduse kas täielikult, või realiseerida selle kontrolli osaliselt. Viimane tähendab, et kui kitsenduse kontroll on vajalik erinevates alamprogrammides, siis võib arendaja unustada realiseerida kontrolli mõnes sellises alamprogrammis. o Erinevates rakendustes või sama rakenduse erinevates osades võib arendaja oskamatusest või tähelepanematusest tulenevalt luua ühe ja sama reegli põhjal alamprogrammid, mis jõustavad erinevaid kitsendusi. o Ühe ja sama probleemi korduv lahendamine (kitsenduse jõustamiseks vajaliku koodi loomine) vähendab kokkuvõttes tööviljakust. Samas ei ole võimalik teha päringuid, et leida süsteemis jõustatud kitsendusi. Miks sellised päringud on vajalikud? Paljud kitsendused tulenevad ärireeglitest ja need reeglid võivad aja jooksul muutuda. Järelikult tuleb vastavad muudatused viia sisse ka tarkvarasüsteemi. Teisalt, kui kitsendus on loodud andmebaasis, siis selle kohta saab küsida päringukeele abil andmeid andmebaasisüsteemi poolt peetavast andmebaasi süsteemikataloogist. Kui andmete haldamine ei toimu läbi rakenduse (vaid näiteks läbi andmebaasi administreerimise programmi), siis ei kontrollita kitsendustest kinnipidamist. Näiteks pole rakenduses jõustatud kitsendustest abi, kui toimub andmete laadimine andmebaasi kasutades andmebaasi administreerimiseks mõeldud programme. Mõningate kitsenduste kontrolli võib dubleerida ka rakenduses, sest see võimaldab kasutajale anda kiirema tagasiside (parem kasutusmugavus) ning väldib vigaste andmete edastamist üle arvutivõrgu (võrgu koormuse vähendamine). Kui kitsendust ei õnnestu andmebaasi tasemel jõustada, tuleb seda igal juhul teha rakenduses, sest nagu vanasõnagi ütleb parem pool muna kui tühi koor. 3.4.1 Võtmed Võtme väärtus identifitseerib üheselt ühe tabeli rea. Olemitüübil võib olla mitu atribuutide hulka, mille väärtused identifitseerivad unikaalselt iga sellesse 28

tüüpi kuuluva olemi. Sellised atribuutide hulgad tuleks kontseptuaalses andmemudelis dokumenteerida kui unikaalsed identifikaatorid e. võtmed. Kontseptuaalses andmemudelis määratud unikaalsete identifikaatorite põhjal leitakse SQL-andmebaasi tabeleid kavandades kandidaatvõtmed. Üks kandidaatvõti valitakse primaarvõtmeks, ülejäänud kandidaatvõtmetest saavad alternatiivvõtmed. SQL-andmebaasis deklareeritakse tabeli primaarvõti kasutades PRIMARY KEY kitsendust. SQL-andmebaasis deklareeritakse tabeli alternatiivvõti kasutades UNIQUE kitsendust ja määrates kõik võtme poolt hõlmatud veerud kohustuslikeks. Vaikimisi on SQLis tabeli veerud mittekohustuslikud (nendele vastavates ridade väljades on lubatud NULLid). Millised on soovitavad võtme omadused? Tuttavlikkus kasutaja jaoks omab võtme väärtust tähendust. Lihtsus võimalikult lühike (andmemahu mõttes) ja koosneb võimalikult vähestest komponentidest. Stabiilsus ei muutu aja jooksul. Võtmete puhul võib eristad ainult andmebaasis tabeli ridade unikaalsuse tagamiseks mõeldud võtit e. surrogaatvõtit ja kasutajatele sisulist tähendust omavat võtit. Näiteks tabelis Töötaja on veergu töötaja_kood hõlmav võti surrogaatvõti, kui selle võtme väärtus on kasutusel ainult tabeli ridade unikaalsuse tagamiseks. Tabelis Töötaja on veergu töötaja_kood hõlmav võti sisulise tähendusega võti, kui selle väärtuseid kasutatakse töötajate eristamiseks ka väljaspool andmebaasi. Miks kasutada surrogaatvõtit? Surrogaatvõti on lihtne. See hõlmab ühte (tavaliselt täisarvu tüüpi) veergu. Füüsilise disaini seisukohalt on oluline, et surrogaatvõtme puhul on välisvõtmetest (primaarvõtme väärtus võib olla mõnes teises tabelis välisvõtme väärtus) ja primaarvõtmele indeksi loomisest tulenev andmemahtude suurenemine võimalikult väike. Surrogaatvõti on stabiilne. Kuna surrogaatvõtme väärtus ei oma kasutaja jaoks tähendust (ei ole tuttavlik), siis ei ole kasutajal vaja võtmeväärtuseid ka muuta ja seega ei pea andmebaasisüsteem muutma vastavaid väärtuseid välisvõtmete kaudu seotud tabelites. Surrogaatvõtme väärtuseid võib andmebaasisüsteem ise genereerida. SQL-andmebaasisüsteemidega seoses on probleemiks, et arvujada generaatoreid kirjeldati SQL standardis esmakordselt SQL:2003 standardi versioonis kaua aega peale standardi esimese versiooni ilmumist. Tulemuseks on, et erinevates andmebaasisüsteemides on unikaalsete arvude genereerimiseks erinevad võimalused ja käskude süntaks. Kontseptuaalses andmemudelis kirjeldatakse kasutajale sisulist tähendust omavad atribuudid. See tähendab, et kontseptuaalses andmemudelis ei 29

näidata surrogaatvõtmetele vastavaid atribuute. Vajadusel tuleb vastav võtmeveerg lisada tabeli kirjeldusse loogilise disaini käigus. Miks siiski eelistada surrogaatvõtmetele sisulisi võtmeid? Võib juhtuda, et kasutades surrogaatvõtmeid, unustatakse deklareerida unikaalsuse ja kohustuslikkuse kitsendused sisulise tähendusega atribuutide (näiteks isikukood, üliõpilaskood, auto registrinumber) põhjal loodud veergudele. Sellisel juhul on võimalik andmebaasis registreerida korduvaid andmeid ning tekib andmete liiasus. Näiteks, kui andmebaasisüsteem ei kontrolli tabelis Isik isikukoodi unikaalsust, siis on võimalik registreerida ühe ja sama isiku andmed mitmekordselt. Kokkuvõtlikud soovitused primaarvõtme valimiseks. 1. Kui tabelil on mitu kandidaatvõtit, mille väärtused omavad sisulist tähendust ja on lihtvõtmed, siis valida primaarvõtmeks nende seast järgmistele tingimustele vastav võti: Kõige stabiilsem väärtuste muutmine on kõige vähetõenäolisem. Kõige lihtsam sisaldab kõige vähem tekstisümboleid (tekstitüüpi veeru puhul) või on kõige väiksema maksimaalse väärtusega (arvutüüpi veeru puhul). Millest on kasutajal kõige lihtsam aru saada. 2. Kui tabelil on mitu kandidaatvõtit, mille väärtused omavad sisulist tähendust ning millest osa on lihtvõtmed ja osa liitvõtmed, siis valida primaarvõtmeks mõni lihtvõti, kasutades eelmises punktis nimetatud kriteeriume. 3. Kui tabeli kõik sisulist tähendust omavad kandidaatvõtmed on liitvõtmed, siis valida primaarvõtmeks liitvõti, kui see võti ei lähe välisvõtmeks mõne teise olemitüübi alusel loodavasse tabelisse. Vastasel juhul valida primaarvõtmeks surrogaatvõti. 4. Kui tuleb valida mitme liitvõtme vahel, siis lisakriteeriumiks on valida selline võti, kus osalevate veergude arv on minimaalne. 5. Kõigi primaarvõtmeks mitte valitud kandidaatvõtmed (alternatiivvõtmed) tuleb samuti andmebaasis deklareerida. 6. Kui kõikide tabelite primaarvõtmeks on surrogaatvõti, siis see viitab kergema vastupanu teed minekule. Disainiga pole viitsitud palju vaeva näha. 7. Ärge mõelge ise välja uusi võtmeid, mille väärtusesse on kodeeritud informatsioon. Toome näite probleemidest, mida sellise võtme kasutamine andmebaasi kavandajale tekitab. Eesti Vabariigi isikukoodis sisaldub informatsioon isiku soo ja sünniaja kohta. Andmebaasi kavandajal tekib paratamatult küsimus, kas tabelis on vaja lisaks isikukoodile registreerida sugu ja sünniaeg ka eraldi veergudes? Kui jah, siis tekib andmebaasis andmete liiasus ning tuleb tagada, et andmed ei oleks kunagi vastuolus (näiteks isikukoodi järgi on üks sünni aeg, aga sünni aja veerule vastavas väljas hoopis teistsugune). Tuleb saavutada kontrollitud andmete liiasus. Terviklikkuse reeglid isikukoodi kontrollimiseks (näiteks et avastada sisestamise näpuvigu) on keerukad. 30

Kui ei, siis kuidas korraldada päringute tegemine isikute kohta sünni aja ja soo järgi? Isikukoodi struktuuri muutudes võib olla vajadus muuta ka neid päringuid. Mõlemal juhul on vajalikud operaatorid, mis võimaldavad isikukoodi väärtusest eraldada isiku sünniaja ja soo andmed. 3.4.2 Veergude kohustuslikus SQLi tabelites on lubatud veerud, millele vastavates ridade väljades on lubatud NULLid (väärtuse puudumine). Öeldakse, et sellised veerud on mittekohustuslikud. Kui soovitakse keelata veerus NULLide kasutamine, siis tuleb seda SQL-andmebaasis eraldi deklareerida, kasutades NOT NULL kitsendust. Öeldakse, et veerud kus ei ole lubatud NULLide kasutamine, on kohustuslikud. Olemitüübi OT iga fakultatiivse üheväärtuselise atribuudi põhjal tuleb OT põhjal loodud tabelisse lisada mittekohustuslik veerg. Olemitüübi OT iga kohustusliku üheväärtuselise atribuudi põhjal tuleb OT põhjal loodud tabelisse lisada kohustuslik veerg. Olemitüübi OT iga mitmeväärtuselise atribuudi puhul tuleks luua eraldi tabel, kus kõik veerud on kohustuslikud (vt. peatükk 3.3.10 ). Juhul kui mitmeväärtuseline atribuut on kohustuslik, siis tuleb andmebaasis jõustada täiendav kitsendus, et iga OT põhjal loodud tabeli rida peab olema seotud vähemalt ühe reaga tabelis, mis on loodud mitmeväärtuselise atribuudi põhjal. 3.4.3 Viidete terviklikkuse tagamine SQL-andmebaasi loogilise disaini tulemusena tuleb leida tabelites olevad välisvõtmed. Loogilise disaini tulemusena tuleb iga välisvõtme puhul kindlaks määrata, kuidas peab andmebaasisüsteem reageerima, kui seoses selle välisvõtmega tekib andmetes vastuolu viidete terviklikkuse reegliga. Sellisel juhul võib andmebaasisüsteem viia läbi kompenseerivaid tegevusi. Vaatleme näitena järgnevaid tabeleid: Töötaja (isikukood, perenimi) Primaarvõti (isikukood) Telefon (isikukood, telefon) Primaarvõti (telefon) Välisvõti (isikukood) Viitab Töötaja(isikukood) Tabelid Töötaja ja Telefon on seotud välisvõtme kaudu. Öeldakse, et selle välisvõtme kontekstis on tabel Töötaja primaarne ja tabel Telefon sõltuv. Tabel, mis on ühe välisvõtme kontekstis primaarne võib olla teise välisvõtme kontekstis sõltuv ja vastupidi. Rekursiivse seosetüübi põhjal loodud tabeli korral on sama tabel korraga nii primaarne kui ka sõltuv. 31

Millal peab andmebaasisüsteem kontrollima andmete vastavust viidete terviklikkuse reeglile? Eeldame, et välisvõti loob seose primaarse tabeli primaarvõtmega. Lisatakse rida sõltuvasse tabelisse andmebaasisüsteem peab kontrollima, et välisvõtme väärtus oleks kas NULL (kui see on lubatud) või võrduks ühe primaarses tabelis oleva primaarvõtme väärtusega. Muudetakse välisvõtme väärtust sõltuvas tabelis andmebaasisüsteem peab kontrollima, et muutuse järel oleks välisvõtme väärtus kas NULL (kui see on lubatud) või võrduks ühe primaarses tabelis oleva primaarvõtme väärtusega. Kustutatakse rida primaarsest tabelist selleks, et vältida viidete terviklikkuse reegliga vastuolus olevate andmete jõudmist andmebaasi, saab SQL standardi kohaselt kasutada SQL-andmebaasisüsteemis järgmisi strateegiaid: NO ACTION andmebaasisüsteem ei ürita viidete terviklikkuse viga kompenseerida ning vea tekkimise tulemusena lükkab andmebaasisüsteem andmemuudatuse tagasi. NO ACTION on vaikimisi strateegia, mida rakendatakse, kui andmebaasi looja pole strateegiat määranud. RESTRICT andmebaasisüsteem ei luba primaarses tabelis rida kustutada, kui leidub vähemalt üks selle reaga seotud rida sõltuvas tabelis. Kokkuvõttes annavad NO ACTION ja RESTRICT sama tulemuse. CASCADE primaarses tabelis rea kustutamine tingib seotud ridade kustutamise sõltuvas tabelis. CASCADE strateegiat on sobilik kasutada siis, kui olemi-suhte diagrammil on vastavate olemitüüpide vahel kompositsioon või üldistusseos. SET NULL primaarses tabelis rea kustutamine tingib vastavate välisvõtme väärtuste kustutamise sõltuvas tabelis. SET NULL strateegiat saab kasutada siis, kui välisvõtme veerud on mittekohustuslikud. SET DEFAULT primaarses tabelis rea kustutamine tingib vastavate välisvõtme väärtuste asendamise vaikimisi väärtustega sõltuvas tabelis. SET DEFAULT strateegiat saab kasutada siis, kui välisvõtme veergudel on määratud vaikimisi väärtused. Peale vaikimisi väärtusega asendamist peavad andmed rahuldama viidete terviklikkuse reeglit. Järelikult peab primaarses tabelis olema rida, milles olev primaarvõtme väärtus langeb kokku sõltuvas tabelis välisvõtme veergudele deklareeritud vaikimisi väärtustega. Muudetakse primaarse tabeli primaarvõtme väärtust selleks, et vältida viidete terviklikkuse reegliga vastuolus olevate andmete jõudmist andmebaasi, saab SQL standardi kohaselt kasutada SQLandmebaasisüsteemis järgmisi strateegiaid: NO ACTION andmebaasisüsteem ei ürita viidete terviklikkuse viga kompenseerida ning vea tekkimise tulemusena lükkab andmebaasisüsteem andmemuudatuse tagasi. NO ACTION on vaikimisi strateegia, mida rakendatakse, kui andmebaasi looja pole strateegiat määranud. RESTRICT andmebaasisüsteem ei luba primaarse tabeli reas primaarvõtme väärtust muuta, kui leidub vähemalt üks selle reaga seotud 32

rida sõltuvas tabelis. Kokkuvõttes annavad NO ACTION ja RESTRICT sama tulemuse. CASCADE primaarse tabeli reas primaarvõtme väärtuse muutmine tingib vastavate välisvõtme väärtuste muutmise sõltuvas tabelis olevates seotud ridades. CASCADE strateegiat on mõistlik kasutada, kui primaarvõti on sisulise tähendusega võti. Sellisel juhul võib andmebaasi kasutajatel tekkida vajadus selle võtme väärtuseid muuta. SET NULL primaarse tabeli reas primaarvõtme väärtuse muutmine tingib vastavate välisvõtme väärtuste kustutamise sõltuvas tabelis olevates seotud ridades. SET NULL strateegiat saab kasutada siis, kui välisvõtme veerud on mittekohustuslikud. SET DEFAULT primaarse tabeli reas primaarvõtme väärtuse muutmine tingib vastavate välisvõtme väärtuste asendamise vaikimisi väärtustega sõltuvas tabelis olevates seotud ridades. SET DEFAULT strateegiat saab kasutada siis, kui välisvõtme veergudel on määratud vaikimisi väärtused. Peale vaikimisi väärtusega asendamist peavad andmed rahuldama viidete terviklikkuse reeglit. Järelikult peab primaarses tabelis olema rida, milles olev primaarvõtme väärtus langeb kokku sõltuvas tabelis välisvõtme veergudele deklareeritud vaikimisi väärtustega. Millised andmemuudatused ei tekita ühe vaadeldava välisvõtme kontekstis andmetesse vastuolu viidete terviklikkuse reegliga? Kustutatakse rida sõltuvast tabelist. Lisatakse uus rida primaarsesse tabelisse. Siinkohal tuletame aga veelkord meelde, et tabel mis on ühe välisvõtme kontekstis primaarne tabel võib olla teise välisvõtme kontekstis sõltuv tabel ja vastupidi. Andmebaasisüsteem peab andmete muudatuse kitsendustele vastavuse kontrollimisel arvestama kõigi välisvõtmetega. Vaatleme järgnevalt näiteid eelnevalt kirjeldatud strateegiate kohta. Nendes näidetes on SQLi tabelite ja võtmete kirjeldusi täiendatud viidete terviklikkuse kontrolli strateegia kirjeldusega. Näide 1: Töötaja (isikukood, perenimi) Primaarvõti (isikukood) Telefon (isikukood, telefon) Primaarvõti (telefon) Välisvõti (isikukood) Viitab Töötaja(isikukood) ON UPDATE CASCADE ON DELETE CASCADE Rea kustutamisel tabelist Töötaja, kustutatakse seotud read tabelist Telefon. Isikukoodi muutmisel tabelis Töötaja, muudetakse see isikukood automaatselt ka tabelis Telefon. Näide 2: Töötaja (isikukood, perenimi) Primaarvõti (isikukood) 33

Telefon (isikukood, telefon) Primaarvõti (telefon) Välisvõti (isikukood) Viitab Töötaja(isikukood) ON UPDATE NO ACTION ON DELETE NO ACTION Töötaja (isikukood, perenimi) Primaarvõti (isikukood) Telefon (isikukood, telefon) Primaarvõti (telefon) Välisvõti (isikukood) Viitab Töötaja(isikukood) ON UPDATE RESTRICT ON DELETE RESTRICT Rea kustutamisel tabelist Töötaja, ei luba andmebaasisüsteem rida kustutada, kui sellega on seotud üks või rohkem rida tabelis Telefon. Kui kustutataval real ei ole ühtegi seotud rida tabelis Telefon, siis lubab andmebaasisüsteem selle rea kustutada. Isikukoodi muutmisel tabelis Töötaja, ei luba andmebaasisüsteem isikukoodi muuta, kui muudetav rida on seotud ühe või rohkema reaga tabelis Telefon. Kui muudetaval real ei ole ühtegi seotud rida tabelis Telefon, siis lubab andmebaasisüsteem selles reas isikukoodi muuta. Näide 3: Töötaja (isikukood, perenimi) Primaarvõti (isikukood) Telefon (isikukood, telefon) Primaarvõti (telefon) Välisvõti (isikukood) Viitab Töötaja(isikukood) ON UPDATE SET NULL ON DELETE SET NULL Rea kustutamisel tabelist Töötaja, kustutatakse tabeli Telefon veerust isikukood selle töötaja isikukoodid. Isikukoodi muutmisel tabelis Töötaja, kustutatakse tabeli Telefon veerust isikukood selle töötaja isikukoodid. Näide 4: Töötaja (isikukood, perenimi) Primaarvõti (isikukood) Telefon (isikukood, telefon) Primaarvõti (telefon) Välisvõti (isikukood) Viitab Töötaja(isikukood) ON UPDATE SET DEFAULT ON DELETE SET DEFAULT Rea kustutamisel tabelist Töötaja, asendatakse tabelis Telefon selle töötaja isikukood veerule isikukood deklareeritud vaikimisi väärtusega. Isikukoodi muutmisel tabelis Töötaja, asendatakse tabelis Telefon selle töötaja isikukood veerule isikukood deklareeritud vaikimisi väärtusega. 34

Soovitusi kompenseerivate tegevuste valikuks. Kasutage ON UPDATE CASCADE, kui primaarse tabeli primaarvõti on sisulise tähendusega võti, mille väärtuseid kasutatakse ka väljaspool andmebaasi. Sellise võtme väärtused võivad muutuda, ehki ilmselt mitte väga sageli. Näiteks isikukoodi võib olla vaja muuta peale soovahetusoperatsiooni. Kasutage ON DELETE CASCADE, kui kontseptuaalses andmemudelis on välisvõtmele vastav seosetüüp kas kompositsioon või üldistusseos. 3.4.4 Tuletisatribuudid Tuletisatribuudi puhul võib luua tabelid/veerud samade põhimõtete alusel, mis ülejäänud atribuutide korral. Kuid tuletisatribuutide puhul tuleb lisaks jõustada andmebaasis kitsendused, mis tagavad, et mistahes sellise atribuudi väärtus on kooskõlas andmetega, mille põhjal see väärtus on leitud. Oletame, et olemitüübis Töötaja oli tuletisatribuut telefonide_arv, mille alusel loodi veerg telefonide_arv tabelisse Töötaja. Veerus telefonide_arv olev väärtus näitab telefoninumbrite arvu, millele helistades on võimalik töötajaga kontakteeruda. Loomulikult saaksime selle arvu ka teada kui teeksime päringu tabeli Telefon põhjal. Töötaja (isikukood, perenimi, telefonide_arv) Primaarvõti (isikukood) Telefon (isikukood, telefon) Primaarvõti (telefon) Välisvõti (isikukood) Viitab Töötaja(isikukood) Näiteks ei tohi olla võimalik, et tabelis Töötaja on andmed, mille kohaselt on töötajal isikukoodiga K1 telefoninumbrite arv 2, samas kui päring tabeli Telefon põhjal annab töötaja K1 telefoninumbrite arvuks 3. Samuti tuleb luua programmid, mis muudavad tuletisatribuudi põhjal loodud veerus olevat väärtust juhul, kui muutuvad andmed mille alusel see väärtus on leitud. Näiteks kui kustutatakse rida tabelist Telefon, peab vastava töötaja telefoninumbrite arv vähenema ühe võrra. Sellise ülesande lahendamiseks võib kasutada andmebaasis trigereid. Kui sellised kontrollid on täies mahus loodud, siis öeldakse, et andmebaasis on kontrollitud andmete liiasus. Kui selliseid kontrolle ei ole või need on ebapiisavad, siis on andmebaasis kontrollimatu andmete liiasus. Andmete liiasusest andmebaasis ei ole alati võimalik hoiduda ja see pole ka vajalik. Kuid igasugune andmete liiasus andmebaasis peaks olema kontrollitud. Tuletatud väärtuste andmebaasis hoidmine võib muuta mõne päringu koostamise kiiremaks ning võimaldada sellele kiiremini vastus saada. Samas tuleb andmebaasi loomisel rohkem vaeva näha, et vältida vastuoluliste andmete andmebaasi sattumist. Veel üks võimalus tuletisatribuudi realiseerimiseks on võtta kasutusele vaade. Näiteks eeltoodud näite korral tuleks luua (baas)tabel Töötaja kus on veerud isikukood ja perenimi. Lisaks tuleb tabelite Töötaja ja Telefon põhjal luua vaade, milles on veerud isikukood, perenimi ja telefonide_arv. 35

3.4.5 Täiendavad kitsendused Kontseptuaalses andmemudelis on paljud keerukamad kitsendused pandud kirja tekstilise spetsifikatsioonina. Selliste kitsenduste põhjal tuleb lõpuks valmivas andmebaasis luua deklaratiivsed kontrollkitsendused või protseduursed kontrollprogrammid, mis ei lase nende kitsenduste vastu eksivaid andmeid registreerida. Milliseid võimalusi pakub SQL täiendavate kitsenduste realiseerimiseks deklaratiivsete kitsendustena? SQL-andmebaasis võib mõningate täiendavate kitsenduste jõustamiseks kasutada tabeli CHECK kitsendusi Taoline kitsendus on seotud baastabeliga ning selle kirjelduse oluline osa on otsingutingimus (inglise keeles search condition). Kui andmebaasis on loodud tabeliga T seotud CHECK kitsendus, siis ei luba andmebaasisüsteem lisada tabelisse T ühtegi rida, mille korral on nimetatud otsingutingimuse hindamise tulemus FALSE. Kui rea puhul on otsingutingimuse hindamise tulemus TRUE või UNKNOWN (tuletage meelde, et SQL kasutab kolmevalentset loogikat), siis ei takista see kitsendus rea tabelisse lisamist. Näiteks juhul kui tabeli Isik veerus sugu on võimalikud lubatud väärtused 0, 1, 2 ja 9, siis võib selle kitsenduse kontrolliks deklareerida tabeli loomise lauses: CHECK (sugu IN (0, 1, 2, 9)) Kui üritame registreerida isikut kelle soo kood on 1, siis on otsingutingimuse hindamise tulemus TRUE. Kui üritame registreerida isikut kelle soo kood on määramata (NULL), siis on otsingutingimuse hindamise tulemus UNKNOWN. Kui üritame registreerida isikut kelle soo kood on 3, siis on otsingutingimuse hindamise tulemus FALSE ning andmebaasisüsteem ei luba sellist rida tabelisse. Kontseptuaalses andmemudelis võivad mitmed kitsendused olla formuleeritud kujul Kui p Siis q kui on täidetud tingimus p, siis peab olema täidetud ka tingimus q. Date (2007) märgib, et selle kitsenduse võib esitada implikatsiooni sisaldava loogikaavaldisena p => q millega loogiliselt samaväärne avaldis on:(not p) OR q. Taolist avaldist võib kasutada tabeli CHECK kitsenduses. Oletame, et tabelis Isik on veerud isikukood ja sugu. Veerus isikukood tuleb registreerida Eesti Vabariigi isikukood. Tabelis Isik on andmete liiasus, sest isikukoodi esimese numbri järgi on võimalik kindlaks teha millisest soost on isik. Selleks, et vältida vastuoluliste andmete sattumist andmebaasi, tuleb jõustada kitsendused: o Kui isikukoodi esimene number kuulub hulka {1, 3, 5, 7, 9}, siis peab isiku soo tähis olema 1. o Kui isikukoodi esimene number kuulub hulka {0, 2, 4, 6, 8}, siis peab isiku soo tähis olema 2. Esimese kitsenduse täidetuse kontrollimiseks kasutatav CHECK kitsendus võib olla järgmine. CHECK (NOT (substring(isikukood, 1, 1) IN ('1','3','5', '7', '9')) OR (sugu=1)); Kitsenduses kasutatakse isikukoodist esimese märgi eraldamiseks funktsiooni substring. Funktsiooni poole pöördumisel on vasakult esimeseks argumendiks 36

veeru nimi. Selles veerus on stringid mille alamstringe otsitakse. Teine argument näitab mitmes stringi märk on otsitava alamstringi esimene märk ning kolmas argument on alamstringi kuuluvate märkide arv. Kuidas saaks seda protsessi automatiseerida? Ideaalne andmebaasi projekteerimiseks kasutatav CASE vahend võimaldaks igast mudelisse kirja pandud kitsendusest genereerida automaatselt kitsenduse kontrolliks mõeldud programmikoodi (näiteks CHECK kitsenduste deklaratsioone ja trigereid). See aga eeldab kitsenduse formaalset kirjeldamist, kasutades mingit spetsiaalkeelt, mis ei pruugi olla lihtsam võrreldes programmeerimiskeelega milles see kitsendus realiseeritakse. Kui kitsendus on kirja pandud tavakeeles, siis ei oska tarkvara sellest programmikoodi genereerida. Teine probleem on, et erinevates andmebaasisüsteemides on võimalused taoliste kitsenduste jõustamiseks erinevad ja koodigeneraatorist tuleb iga andmebaasisüsteemi jaoks luua oma versioon. Lisaks on tänapäeva SQL-andmebaasisüsteemides väga piiratud võimalused deklaratiivsete kitsenduste loomiseks. Võib öelda, et mudelis kirjeldatud kitsendustest koodi genereerimine on eesmärk, mille poole liigutakse, kuid mis senimaani pole lõplikult lahendatud. 3.5 Tabelite disaini kvaliteedi hindamine ja parandamine Peale seda, kui kontseptuaalse andmemudeli põhjal on leitud esialgne loogiline andmemudel, tuleb leitud tabelitele rakendada normaliseerimise protseduuri (vt. teema 9). Tabelid on soovitav viia viiendale normaalkujule. Samuti tuleb tabelite struktuuri ja andmebaasis jõustatud kitsendusi vajadusel parandada nii, et tabelid vastaksid ortogonaalse andmebaasi disaini printsiibi nõudmistele (vt. teema 9). Normaliseerimine ja ortogonaalse disaini printsiibi põhimõtete rakendamine aitab vähendada andmebaasis andmete liiasust ja andmete liiasusest tulenevaid andmete muutmise anomaaliaid. 37

3.6 Loogilise disaini andmemudeli näide Esitame järgnevalt loogilise andmemudeli võimaliku ülesehituse näite. Esitame UMLi klassidiagrammi baasil koostatud loogilise andmemudeli diagrammi (vt. Joonis 18). Kastid sellel tähistavad tabeleid. Iga tabeli kohta esitatakse diagrammil nimi ja selles olevate veergude nimed ning nende andmetüübid. PK tähendab, et veerg on hõlmatud primaarvõtme (primary key) poolt. NN tähendab, et veerg on kohustuslik (not null). FK tähendab, et veerg on hõlmatud välisvõtme (foreign key) poolt. Mitteidentifitseeriv (inglise keeles non-identifying) seos tähendab antud juhul, et õpingukava seisundi koodi ei ole vaja kasutada, et identifitseerida õpingukavasid. Seega tabelis Opingukava olev välisvõtme veerg opingukava_seisundi_liik_r_kood, mille abil luuakse seos tabeliga Opingukava_seisundi_liik_R, ei ole hõlmatud tabeli Opingukava primaarvõtme poolt. Lisaks esitame tabelite spetsifikatsioonid (vt. Tabel 1 Tabel 3). Joonis 18 Loogilise andmemudeli diagrammi näide. Tabel 1 Tabelite spetsifikatsioon. Tabeli nimi Kuuluvus registrisse Millise olemitüübi, atribuudi või seosetüübi põhjal on loodud? Opingukava Õpingukavade register Olemitüüp: Õpingukava Opingukava_seisundi_liik_R Klassifikaatorite register Olemitüübid: Õpingukava_seisundi_liik, Klassifikaator 38

Tabel 2 Tabeli Opingukava_seisundi_liik_R veergude spetsifikatsioon. Veeru nimi Tüüp Välja Võimalikud Vaikeväärtus Kohustuslik pikkus väärtused opingukava_ täisarv Jah seisundi_liik_r_kood nimetus tekst 70 Jah kirjeldus tekst 1000 Jah Primaarvõti (opingukava_seisundi_liik_r_kood) Alternatiivvõti (nimetus) Tabel 3 Tabeli Opingukava veergude spetsifikatsioon. Veeru nimi Tüüp Välja Võimalikud Vaikeväärtus Kohustuslik pikkus väärtused opingukava_id täisarv Automaatselt Jah genereeritav täisarv, samm=1 matrikli_nr tekst 6 Jah semester_id täisarv Jah opingukava_ täisarv 1 Jah seisundi_liik_r_ kood Kui tabelisse lisatakse uus rida, siis vaikimisi seotakse see Õpingukava esimese loomisjärgse seisundiga. tyypopingukava_id täisarv Ei ajapikenduse_lopp kuupäev Ei Primaarvõti (opingukava_id) Alternatiivvõti (matrikli_nr, semester_id) Välisvõti (matrikli_nr) Viitab Yliopilane(matrikli_nr) ON UPDATE CASCADE Välisvõti (semester_id) Viitab Semester(semester_id) Välisvõti (opingukava_seisundi_liik_r_kood) Viitab Opinguava_seisundi_liik_R(opingukava_seisundi_liik_R_kood) ON UPDATE CASCADE Välisvõti (tyypopingukava_id) Viitab Tyypopingukava(tyypopingukava_id) Järelliide "_R" tabeli nimes Opingukava_seisundi_liik_R tähendab, et tegemist on klassifikaatori tabeliga (R nagu "reference data"). Välisvõtmega seotud vaikimisi määrangud, mis kirjeldavad reaktsiooni viidete terviklikkuse reegli rikkumisele, on ON UPDATE NO ACTION ja ON DELETE NO ACTION (vt. peatükk 3.4.3 ). Tabeli Opingukava_seisundi_liik_R veerus opingukava_seisundi_liik_r_kood on klassifikaatori arvulised väärtused, mida kasutatakse ka väljaspool andmebaasi. On võimalik, et seda koodi on vaja muuta. Seetõttu kasutame välisvõtte deklareerimisel määrangut ON UPDATE CASCADE. Miks ei kasuta me sama välisvõtme puhul määrangut ON DELETE CASCADE? Kujutlege, et keegi kustutab kogemata mõne 39

õpingukava seisundi liigi klassifikaatori väärtuse. See võiks põhjustada sadade või tuhandete õpingukavade andmete kustutamise. Samas on nii Õpingukava kui ka Õpingukava_seisundi_liik tugevad olemitüübid ja õpingukava ei sõltu eksistentsiaalselt õpingukava seisundi liigist. Käesolevas näites oleme tabelite ja veergude nimedest eemaldanud täpitähed. SQL-andmebaasisüsteemid seavad piiranguid selliste tähtede kasutamisele andmebaasiobjektide nimedes. Taolise tähtede asenduse võib teha loogilise disaini käigus, kuid selle võib jätta ka füüsilise disaini ülesandeks, kui on teada täpne kasutatav andmebaasisüsteem. 3.7 Veel mõned soovitused Järgnevalt antakse soovitusi, mida tasub SQL-andmebaaside kavandamisel arvesse võtta. 3.7.1 Klassifikaatorite haldus Vabariigi valitsuse 9. oktoobri 2003. a määruse nr. 255 Klassifikaatorite süsteemi kehtestamine kohaselt on klassifikaator "riigi või kohaliku omavalitsuse andmekogus kasutatav ühetüübilisi objekte teatud tunnuse või tunnuste hulga alusel liigitav ja üheselt identifitseeriv tähistuseeskiri." Tegelikult võib olla vaja klassifikaatoreid kasutada mistahes andmebaasides. Seega võime öelda, et klassifikaator on andmebaasis kasutatav ühetüübilisi objekte teatud tunnuse või tunnuste hulga alusel liigitav ja üheselt identifitseeriv tähistuseeskiri. Teisiti öeldes on klassifikaatorid "mistahes andmed, mida kasutatakse andmebaasis teiste andmete liigitamiseks või andmebaasis olevate andmete seostamiseks väljaspool organisatsiooni vastutusala oleva informatsiooniga." (Chisholm, 2000). Infosüsteem peab võimaldama klassifikaatorite haldust. Klassifikaatorite haldamise allsüsteem on infosüsteemi oluline administratiivne allsüsteem. Koos infosüsteemi väljatöötamisega leitakse ka vajalikud klassifikaatorid ning määratakse kindlaks nende esialgne väärtuste hulk. Need andmed kantakse uude loodavasse andmebaasi esimeses järjekorras. Seejärel saab hakata sisestama andmeid, mida need klassifikaatorid iseloomustavad. Tavakasutajad ei saa ise klassifikaatoreid lisada ja muuta. Klassifikaatorite haldamine toimub spetsiaalselt väljatöötatud eeskirja kohaselt ning selleks on oma vastutavad töötajad, kes vastutavad klassifikaatorite õigsuse eest ning volitatud töötajad, kes reaalselt andmebaasi klassifikaatorite andmeid haldavad (praktikas võib tegu olla ühtede ja samade isikutega). Klassifikaatori muutmise aluseks võib olla klassifikaatori kasutaja ettepanek või vastava rahvusvahelise alusklassifikaatori muutumine. Klassifikaatorid võivad olla ulatuselt rahvusvahelised, regionaalsed, riigisisesed või organisatsioonisisesed. Näited rahvusvahelistest klassifikaatoritest on: riikide klassifikaator ISO 3166 Codes (Countries). Näiteks on standardi kohaselt Eesti Vabariiki tähistav kahetäheline kood "EE" (Chisholm, 2000). 40

valuutade klassifikaator ISO 4217 Codes (Currencies). Näiteks on standardi kohaselt Eesti krooni tähistav 3-täheline kood "EEK" ja numbriline kood 233 (Chisholm, 2000). soo klassifikaator ISO 5218 Codes (Human Sexes) Täheühend ISO tähistab rahvusvahelist standardiseerimisega tegelevat organisatsiooni International Organization for Standardization. Statistikaameti kodulehelt (http://www.stat.ee/klassifikaatorid) on võimalik leida andmed Eestis kasutatavate majanduslike klassifikaatorite kohta. Enamik nendest on loodud tõlke või riigisisese versioonina rahvusvaheliste klassifikaatorite alusel. Kui erinevates süsteemides on kasutusel samasugused klassifikaatorid (samasuguste võimalike väärtustega), siis lihtsustab see tunduvalt nende süsteemide vahel andmete vahetamist ja nendest süsteemidest pärit andmete integreerimist (näiteks andmeaitades). Klassifikaatorid on seega nagu ühine keel, mis võimaldavad erinevatel süsteemidel üksteisest aru saada. Seega, kui hakatakse looma organisatsioonile infosüsteemi, siis tuleks kasutada maksimaalselt rahvusvahelisi ja riigisiseseid klassifikaatoreid, selle asemel, et jalgratast leiutada ning töötada organisatsioonisiseseks kasutamiseks välja klassifikaator, mis tegelikult on juba olemas. Vabariigi valitsuse 9. oktoobri 2003. a määruse nr. 255 Klassifikaatorite süsteemi kehtestamine sätestab, et "Riigi- ja kohaliku omavalitsuse asutused on kohustatud nende poolt hallatavates andmekogudes kasutama andmekogude riiklikus registris registreeritud klassifikaatoreid. Muude andmekogude puhul on klassifikaatorite kasutamine soovituslik." 3.7.2 Klassifikaatorite hoidmine SQL-andmebaasis Kuidas hoida klassifikaatoreid SQL-andmebaasis? Soovitav on luua iga klassifikaatori kohta eraldi tabel. Iga klassifikaatori väärtuse kohta võiks selles tabelis olla vähemalt tekstiline või numbriline kood, koodile vastav inimesele mõistetav nimetus ja väärtuse vabas vormis tekstiline kirjeldus. Struktuuri järgi võib klassifikaatoreid liigitada lineaarseteks (ühe tasemega) ja hierarhilisteks (mitme tasemega ja puustruktuuri moodustav). Hierarhilise klassifikaatori väärtuste hoidmiseks vajaliku tabeli loomisel lähtuge juhistest 1:M rekursiivse seosetüübi põhjal tabeli loomise kohta (vt. peatükk 3.3.6.2 ). Vaatleme näitena tabeleid, mida on vaja lepingute andmete hoidmiseks. Iga leping on mingit liiki. Esitame järgnevalt lepingu liikide koodid ning neile vastavad nimetused (tegemist ei ole ametliku klassifikaatoriga, vaid näitega). 1 Ostuleping 2 Müügileping 3 Tööleping 4 Kindlustusleping 5 Tarneleping 41

Igal lepingul on hetkel kehtiv seisund. Need seisundid leitakse lepingu seisundidiagrammilt. Esitame järgnevalt lepingute seisundite liikide koodid ning neile vastavad nimetused (tegemist ei ole ametliku klassifikaatoriga, vaid näitega). 1 Koostamisel 2 Kinnitamisel 3 Kinnitatud 4 Peatatud 5 Tühistatud 6 Arhiveeritud Nii lepingu liikide klassifikaator kui ka lepingu seisundi liikide klassifikaator on lineaarne klassifikaator. Sellise klassifikaatori väärtuse unikaalseks identifikaatoriks klassifikaatori piires on nii kood kui ka nimetus. Andmebaasis võiks luua tabelid: Lepingu_liik_R (lepingu_liik_r_kood, nimetus, kirjeldus) Primaarvõti (lepingu_liik_r_kood) Alternatiivvõti (nimetus) Lepingu_seisundi_liik_R (lepingu_seisundi_liik_r_kood, nimetus, kirjeldus) Primaarvõti (lepingu_seisundi_liik_r_kood) Alternatiivvõti (nimetus) Leping(leping_id, sõlmimise_kuupäev, kehtivuse_alguse_aeg, kehtivuse_lõpu_aeg, kirjeldus, liik, kehtiv_seisund) Primaarvõti (leping_id) Välisvõti (liik) Viitab Lepingu_liik_R (lepingu_liik_r_kood) ON UPDATE CASCADE Välisvõti (kehtiv_seisund) Viitab Lepingu_seisundi_liik_R (lepingu_seisundi_liik_r_kood) ON UPDATE CASCADE Millised on klassifikaatorite tabelite kasutamise eelised? Miks mitte lisada tabelisse Leping veerud, kus kasutaja saab vabas vormis tekstina panna kirja andmed lepingu liigi ja lepingu seisundi kohta. Andmebaasi kasutava rakenduse kasutajaliideses saab kasutajale näidata nimekirja klassifikaatori väärtustest. Kasutaja ei saa teha omaloomingut ning registreerida lepinguid, mis on olematut liiki või on olematus seisundis. Klassifikaatori väärtuse koodiga seotud nimetus ja kirjeldus muudavad selle koodi lõppkasutajale arusaadavaks. Ühesuguste klassifikaatorite kasutamine erinevates süsteemides, muudab nendes süsteemides olevate andmete üheskoos kasutamise lihtsamaks. Klassifikaatorite väärtuseid ei maksa sisse kodeerida rakendusprogrammi, sest klassifikaator võib muutuda (näiteks lisanduvad uued väärtused) ning see nõuaks ka rakenduse ümberkirjutamist. Mõnikord üritatakse hoida kõikide klassifikaatorite väärtuseid ühes tabelis. Soovitame sellisest lahendusest hoiduda. Vaatleme järgnevalt kahte 42

võimalikku lahendust, kuidas hoida SQL-andmebaasis klassifikaatorite andmeid. Organisatsioonis töötavad töötajad, kes on mingist soost ja saavad palka mingis valuutas. Iga valuuta kehtib käesoleval ajahetkel nullis või rohkemas riigis ning igas riigis kehtib käesoleval ajahetkel üks või rohkem valuutat. Üheks võimalikuks lahenduseks on kasutada universaalset klassifikaatorite tabelit (kutsume seda Lahendus 1) (vt. Joonis 19). Lisaks tuleb luua tabel Klassifikaatori_seos, et registreerida võimalikke seoseid klassifikaatorite väärtuste vahel (näiteks seosed riikide ja valuutade vahel). Iga klassifikaatori väärtus on mingit liiki. Ka klassifikaatori liik on klassifikaator (vaadake välisvõtme veergu klassifikaatori_liik_id tabelis Klassifikaator, mis viitab sama tabeli primaarvõtmele). Klassifikaatori ja Klassifikaatori_seose vahel on identifitseeriv seos (inglise keeles identifying relationship), sest klassifikaatorite väärtuste vahelise seose identifitseerimiseks on vaja kasutada klassifikaatorite väärtuste identifikaatoreid. Tabeli Klassifikaatori_seos primaarvõti hõlmab välisvõtme veerge, mille abil luuakse seos tabeliga Klassifikaator. Tabelile Klassifikaatori_seos vastav olemitüüp on nõrk olemitüüp. Veergudes, mille nime järelliide on "_ingl_k" hoitakse ingliskeelseid nimetusi ja kirjeldusi, mis võivad pärineda rahvusvahelisest klassifikaatorist. Teiseks lahenduseks on luua iga klassifikaatori (Sugu, Riik, Valuuta) kohta eraldi tabel (kutsume seda Lahendus 2) (vt. Joonis 20). Tootaja tootaja_kood : INTEGER perenimi : VARCHAR(50) palk : DECIMAL(10, 2) klassifikaator_sugu_id : INTEGER klassifikaator_palk_id : INTEGER 0..* 0..* <<Non-Identifying>> 1 <<Non-Identifying>> 1 Klassifikaatori_seos klassifikaator_1_id : INTEGER klassifikaator_2_id : INTEGER klassifikaator_seose_liik_id : INTEGER 0..* <<Identifying>> 0..* 0..* 1 <<Identifying>> 1 1 Klassifikaator klassifikaator_id : INTEGER tekstiline_kood : VARCHAR(10) tekstiline_kood_2 : VARCHAR(10) numbriline_kood : INTEGER klassifikaatori_liik_id : INTEGER nimetus : VARCHAR(100) nimetus_ingl_k : VARCHAR(100) kirjeldus : VARCHAR(1000) kirjeldus_ingl_k : VARCHAR(1000) 1 0..* <<Non-Identifying>> <<Non-Identifying>> Joonis 19 Universaalne klassifikaatorite tabel. 43

Sugu_R numbriline_kood : SMALLINT nimetus : VARCHAR(50) nimetus_ingl_k : VARCHAR(50) kirjeldus : VARCHAR(1000) kirjeldus_ingl_k : VARCHAR(1000) <<Non-Identifying>> 1 0..* Tootaja tootaja_kood : INTEGER perenimi : VARCHAR(50) sugu_numbriline_kood : SMALLINT valuuta_tekstiline_kood : CHAR(3) palk : DECIMAL(10, 2) Riik_R tekstiline_kood_2 : CHAR(2) tekstiline_kood_3 : CHAR(3) numbriline_kood : SMALLINT nimetus : VARCHAR(50) nimetus_ingl_k : VARCHAR(50) kirjeldus : VARCHAR(1000) kirjeldus_ingl_k : VARCHAR(1000) 1 <<Identifying>> 1..* <<Identifying>> 0..* 1 <<Non-Identifying>> 0..* 1 Valuuta_R tekstiline_kood : CHAR(3) numbriline_kood : SMALLINT symbol : VARCHAR(2) nimetus : VARCHAR(50) nimetus_ingl_k : VARCHAR(50) kirjeldus : VARCHAR(1000) kirjeldus_ingl_k : VARCHAR(1000) Riigi_valuuta valuuta_r_tekstiline_kood : CHAR(3) riik_r_tekstiline_kood_2 : CHAR(2) Joonis 20 Eraldi klassifikaatorite tabelid. Miks eelistada universaalset klassifikaatorite tabelit (Lahendus 1)? Lahendus võib tunduda "paindlikum", sest jooksvalt saab lisada uusi klassifikaatoreid ilma andmebaasi struktuuri muutmata. Andmebaasi loomisel tuleb teha vähem tööd, sest sõltumata klassifikaatorite arvust tuleb luua kaks tabelit. Miks eelistada lahendust, mille kohaselt luuakse iga klassifikaatori kohta eraldi tabel (Lahendus 2)? Erinevatel klassifikaatoritel on erinevad atribuudid. Lahenduse 1 korral tekib tabel kus on palju NULLe. Koodidele saab jõustada täiendavaid deklaratiivseid kitsendusi. Näiteks tabelis Riik_R veerus tekstiline_kood_3 olev väärtus peab alati koosnema kolmest tähemärgist. Välisvõtmete poolt hõlmatud veergudes, mille abil luuakse seosed klassifikaatorite tabelitega, on kasutajale sisulise tähendusega väärtused. Näiteks Lahendus 1 korral on tabeli Tootaja veerus klassifikaator_palk_id täisarv, millele vastavat klassifikaatori väärtuse koodi ja nimetust peab otsima tabelist Klassifikaator. Samas Lahendus 2 korral on tabeli Tootaja veerus valuuta_tekstiline_kood sisulise tähendusega väärtus (valuuta kood). Päringud on lihtsamad. Näide: Leia töötaja koodid ja nende soo numbrilised koodid. Lahenduse 1 korral oleks päring: 44

SELECT tootaja_kood, Klassifikaator.numbriline_kood AS sugu_numbriline_kood FROM Tootaja INNER JOIN Klassifikaator ON Tootaja.klassifikaator_sugu_id=Klassifikaator.klassifikaator_id; Lahenduse 2 korral oleks päring: SELECT tootaja_kood, sugu_numbriline_kood FROM Tootaja; Näide: Leia riikide 2-tähelised tekstilised koodid ja eestikeelsed nimed. Lahenduse 1 korral oleks päring: SELECT Kl.tekstiline_kood AS tekstiline_kood_2, Kl.nimetus FROM Klassifikaator Kl INNER JOIN Klassifikaator AS Kl2 ON Kl.klassifikaatori_liik_id=Kl2.klassifikaator_id WHERE Kl2.nimetus='Riik'; Lahenduse 2 korral oleks päring: SELECT tekstiline_kood2, nimetus FROM Riik_R. Võib väita, et päringute lihtsustamiseks saab lahenduse 1 korral luua erinevate klassifikaatorite jaoks vaated (virtuaalsed tabelid). Kuid miks siis üldse luua ühine baastabel? 3.7.3 Väärtuste puudumine Hoiduge nii palju kui võimalik NULLidest ridade väljades. Kasutage spetsiaalseid väärtuseid, et registreerida väärtuse puudumist ning selle põhjuseid. Klassifikaatorite puhul võib selleks kasutada spetsiaalseid klassifikaatori väärtuseid (vt. Tabel 4). Lepingu liigi koodi 6 tuleb kasutada, kui registreeritakse andmed lepingu kohta, mille liik on teada, kuid see liik ei kuulu teadaolevate liikide hulka. Lepingu liigi koodi 7 tuleb kasutada, kui registreeritakse andmed lepingu kohta mille liik ei ole teada. Tabel 4 Lepingu liikide klassifikaatori võimalikud väärtused. lepingu_liik_r_kood nimetus 1 Ostuleping 2 Müügileping 3 Tööleping 4 Kindlustusleping 5 Tarneleping 6 Muu leping 7 Lepingu liik teadmata 3.7.4 Seisundite klassifikaator Kasutage seisundite andmete registreerimiseks seisundite klassifikaatoreid. Oletame, et soovite hoida andmebaasis andmeid tellimuste kohta. Süsteemianalüüsi käigus on koostatud tellimuse seisundidiagramm (vt. Joonis 21). 45

Koostamisel Klient loobub tellimusest Kustutatud Klient esitab tellimuse[ tellimusel vähemalt üks rida; igas reas kogus suurem kui 0 ] Esitatud Kliendihaldur veendub tellimuse korrektsuses ja täidetavuses Kliendihaldur avastab, et klient on esitanud valeandmeid või tellimust pole võimalik täita Kinnitatud Klient ei tasu tähtajaks tellimuse eest Tühistatud Klient tasub tellimuse eest Tasutud Tellitud kaup viiakse kliendlile kohale Täidetud Joonis 21 Tellimuse seisundidiagramm. Iga tellimuse kohta peab olema võimalik andmebaasis olevate andmete põhjal kindlaks teha, millises seisundis see tellimus parajasti viibib. Millised tabelid võimaldavad kõige paremini seda eesmärki saavutada? Halvem lahendus on luua tabel: Tellimus(tellimuse_nr, on_koostamisel, on_esitatud, on_kinnitatud, on_tasutud, on_täidetud, on_tühistatud, on_kustutatud) Primaarvõti (tellimuse_nr) Veerud, mille eesliide on "on_" on tõeväärtuse tüüpi. Iga selline veerg vastab ühele seisundile, milles tellimus võib viibida. Kui tabelis Tellimus olevas reas on sellisele veerule vastavas väljas väärtus TRUE, siis selle rea poolt esitatav tellimus on vastavas seisundis. Sellise disaini probleemid on: Seisundite hulga muutumisel tuleb muuta tabeli struktuuri Tabeliga Tellimus seoses on vajalikud kitsendused, mis takistavad ebakorrektsete andmete sattumist andmebaasi. Näiteks tellimus ei saa olla samal ajal koostamisel ja kustutatud. Järelikult ei tohi tabelis Tellimus olla ühtegi rida kus on_koostamisel=true ja on_kustutatud=true. Parem lahendus on luua tabelid: Tellimuse_seisundi_liik_R(tellimuse_seisundi_liik_R_kood, nimetus, kirjeldus) Primaarvõti (tellimuse_seisundi_liik_r_kood) Alternatiivvõti (nimetus) 46

Tellimus (tellimuse_nr, tellimuse_seisundi_liik_r_kood) Primaarvõti (tellimuse_nr) Välisvõti (tellimuse_seisundi_liik_r_kood) Viitab Tellimuse_seisundi_liik_R(tellimuse_seisundi_liik_R_kood); Tellimuse_seisundi_liik_R on seisundite klassifikaatori tabel. Andmed, mida lisada tabelisse Tellimuse_seisundi_liik_R leitakse tellimuse seisundidiagrammi põhjal. Seisundidiagramm määrab ka lubatud seisundi üleminekud. Näiteks Joonis 21 kohaselt on lubatud otsene üleminek seisundist koostamisel seisundisse esitatud. Samas ei ole lubatud otsene üleminek seisundist koostamisel seisundisse tasutud. Andmebaasis tuleks luua kitsendused, mis piiravad lubatud andmemuudatusi tabelis Tellimus. Üheks lahenduseks oleks luua tabel kus registreeritakse lubatud seisundi üleminekud. Samuti tuleb luua trigerid, mis käivituvad andmete muutmisel tabelis Tellimus ning mille abil kontrollitakse (tabelis Lubatud_tellimuse_seisundi_muutus olevate andmete põhjal), kas tellimuse seisundi muutus on lubatud või mitte. Juhul kui toimub mittelubatud seisundi üleminek, siis triger katkestab andmemuudatuse. Lubatud_tellimuse_seisundi_muutus(algseisund, lõppseisund) Primaarvõti (algseisund, lõppseisund) Välisvõti (algseisund) Viitab Tellimuse_seisundi_liik_R(tellimuse_seisundi_liik_R_kood) Välisvõti (lõppseisund) Viitab Tellimuse_seisundi_liik_R(tellimuse_seisundi_liik_R_kood); Sellise tabeli kasutamise korral pole vaja seisundidiagrammi muutumisel hakata trigerit ümber kirjutama, vaid tuleb muuta andmebaasis seisundimuudatuste kirjeldusi (tabelis Lubatud_tellimuse_ seisundi_muutus). 3.7.5 Vektorkodeerimine e. semantiline kodeerimine. Vektorkodeerimine tähendab, et suur hulk informatsiooni koondatakse ühte stringi, kusjuures igas stringi positsioonis oleval sümbolil on oma tähendus. Näiteid vektorkodeerimise kasutamise kohta: isikukood õppeaine kood ülikoolis lõputöö kood ülikoolis Näide: EV Isikukood Esimene number määrab sünni sajandi ja isiku soo. Numbrid 2-7 määravad isiku sünni kuupäeva. 8-10 number on järjenumber ühel ja samal päeval sündinuile. Üheteistkümnes number on kontrollnumber, mis arvutatakse standardis toodud eeskirja kohaselt. Üheks sellise kodeerimise puuduseks on asjaolu, et mingil hetkel võib tekkida vajadus seda kodeeringut muuta. 47

Esimene number: 1 19. sajandil sündinud mees 2 19. sajandil sündinud naine 3 20. sajandil sündinud mees 4 20. sajandil sündinud naine 5 21. sajandil sündinud mees 6 21. sajandil sündinud naine 7 22. sajandil sündinud mees 8 22. sajandil sündinud naine 9 23. sajandil sündinud mees 0(?) 23. sajandil sündinud naine 24 -ndal sajandil tekib probleem. Tuleb muuta koodi. Isikukoodi põhjal saab teada inimese sünniaja ja soo. Tekib küsimus, milliseid veerge peaks sisaldama isikute kohta käiv tabel. Nii veerg isikukood, kui ka veerud sünniaeg ja sugu. Tekib andmete liiasus. Tuleb kirjutada kontrollprotseduurid, mis kontrolliksid et isikukoodi põhjal leitavad sünniaeg ja sugu on samad kui veergudes sünniaeg ja sugu. Ainult veerg isikukood. Päringutes sünniaja ja soo põhjal tuleb hakata kasutama funktsioone. See muudab päringu formuleerimise keerukamaks. Funktsioonid tuleb ümber kirjutada, kui isikukoodi struktuuri peaks muudetama. Mis saab siis, kui mingil hetkel otsustakse riigi poolt taolisest "intelligentsest" isikukoodist loobuda? Mis saab inimestest, kellel pole isikukoodi (välismaalased, illegaalid)? Näide: Lõputöö kood TTÜ-s koostatakse järgmiste reeglite kohaselt (juhend kinnitatud rektori 20.04.2006 käskkirjaga nr 57): Lõputöö kood koosneb seitsmest sümbolist, milleks on numbrid ja tähed. Koodi esimesed kolm sümbolit tähistavad struktuuriüksust (õppetool, lektoraat, asutus), kus lõputöö tehti. Struktuuriüksus määratakse lõputöö juhendaja järgi. Koodi neljas sümbol tähistab lõputöö liiki, mis on üks järgnevatest: o 2 diplomiõppe lõputöö o 3 rakenduskõrgharidusõppe lõputöö o 4 3+2 õppekavade süsteemi bakalaureuseõppe lõputöö o 5 4+2 õppekavade süsteemi bakalaureuseõppe lõputöö o 6 inseneriõppe lõputöö o 7 3+2 õppekavade süsteemi magistriõppe lõputöö o 8 4+2 õppekavade süsteemi magistriõppe lõputöö o 9 doktoritöö o 0 õpetajakoolituse lõputöö Koodi viies kuni seitsmes sümbol on kõikidel lõputöödel 0LT. Näiteks, kui tegemist on 3+2 õppekava bakalaureuseõppe lõputööga, mille juhendaja on TTÜ Informaatikainstituudi, infosüsteemide õppetooli töötaja, siis oleks lõputöö kood IDU40LT. Näide: Oletame, et on vaja registreerida kauba andmeid, sealhulgas kauba kategooria. Iga kaup kuulub nulli või rohkemasse kategooriasse. Igasse kategooriasse kuulub null või rohkem kaupa. 48

Kaup(kauba_kood, nimetus, kogus, kategooria) Primaarvõti (kauba_kood) Süsteemianalüüs näitab, et praegusel hetkel on teada viis kaupade kategooriat. Tabeli Kaup veerus kategooria on lubatud sisestada fikseeritud pikkusega string (pikkusega viis märki), mis koosneb 0-dest ja 1-dest. Iga positsioon stringis tähistab ühte kategooriat. Kui sellel positsioonil on väärtus "1", siis kaup on antud kategoorias, ning kui positsioonis on väärtus "0" siis kaup ei ole antud kategoorias. Näiteks string "11010" näitab, et kaup on kategooriates "A", "B" ja "D". Kaup ei kuulu kategooriasse "C" ja "E". Vektorkodeerimise puudused. Ilma dekodeerimise algoritmi teadmata on need andmed kasutajale kasutud. Andmete kasutamiseks mõeldud rakendus peaks need andmed "tõlkima" kasutajale arusaadavale kujule. Selliste andmete alusel otsimine ja päringu tulemuste sorteerimine võib nõuda funktsioonide kasutamist. See välistab omakorda paljudes andmebaasisüsteemides indeksi kasutamise otsingu läbiviimisel. Kodeeringu muutumine nõuab andmebaasi muutmist. Võib olla vajalik muuta veeru pikkust ja sellega seotud kontrollkitsendusi (näiteks kitsendust, mis kontrollib, et igas positsioonis võib olla vaid väärtus 0 ja 1). Samuti tuleb muuta kodeerimiseks ja dekodeerimiseks kasutatavaid programme ning võib olla vaja muuta kodeeritud andmeid kasutavaid programme. Kui kood on ametlikult kasutusele võetud, siis peab seda kasutama. Kuid ärge ise sarnaseid koode välja mõelge (vaadake kolmandat näidet). 3.7.6 Vaba teksti väljad Üheks andmebaasides kohatavaks probleemiks on vabas vormis teksti sisestamist võimaldavate veergude liigne kasutamine. See viitab süsteemianalüüsi puudulikkusele. Mõnikord võib algajailt andmebaasi programmeerijailt kuulda väidet, et juhul kui kasutajatel tekivad täiendavad nõudmised andmebaasi salvestatavate andmete osas, siis võib need andmed salvestada vabas vormis kommentaarina. See ei ole hea lahendus, sest selliste andmete põhjal on võimatu teha täpseid päringuid. Kujutlege, et andmebaasis on registreeritud kommentaarid: Kommentaar1: "Arve kirjutati välja 21.01.2002. Arve maksti 25.01.2002" Kommentaar2: "Arve loodi 21. märts 2002. Arve tasutud 25.04.2002" Kommentaar3: " Arve tasutud 12.01.2003 Arve loodud: 21. märts 03. " Kommentaar4: " Tühistatud 12.01.2004" Kommentaar5: "2003-01-22 otsustati, et klient võib tasuda arve eest kahes osas" 49

Kuidas siit andmebaasikeele päringuga leida arve maksmise kuupäev või arve loomise ja maksmise aja vaheline intervall päevades? Andmebaasi projekteerimise käigus peab püüdma maksimaalselt tulevasi nõudmisi andmetele ette näha. Kui siiski tekib vajadus täiendavate andmete salvestamise järgi, siis tuleb andmebaasi struktuuri ja kitsendusi täiendada, et võimaldada uute andmete registreerimist. 4 Rakenduse loogiline disain Andmebaasi projekteerimine eeldab ka andmebaasi kasutavate/uuendavate rakenduste projekteerimist (disaini). Andmebaasi rakendustena vaatame praegu lihtsaid registri tüüpi rakendusi, mis realiseerivad elementaarseid andmete registreerimise ja päringu protsesse (teenuseid). Viimaseid käsitleme andmebaasiliidestena. Andmebaasiliides koosneb kasutajaliidesest (nt. leheküljed, ekraanivorm, trükis) ning kasutajaliidese (sündmuste) kaudu käivitatavatest andmebaasi transaktsioonidest. Andmebaasi transaktsioonid on andmebaasi operatsioonide jadad. Lihtsa registritüüpi rakenduse kihid: Kasutajaliides Transaktsioonid Andmebaasi operatsioonid Andmed Andmebaasiliides Joonis 22 Tarkvarasüsteemi kihiline arhitektuur. Tarkvarasüsteemide kihtide kohta lugege näiteks raamatut: Fowler, M. Patterns of Enterprise Application Architecture. Addison Wesley Professional, 2002. 560 p. Registri tüüpi rakenduse loogiline disain sisaldab: Kasutajaliideste loogiline projekteerimine. Kasutajaliidese kaudu tehtud tegevuste käivitatavate transaktsioonide projekteerimine. Üks transaktsioon võib koosneda mitmest andmebaasioperatsioonist. Andmebaasioperatsioonid võib realiseerida andmebaasis loodud salvestatud protseduuridena. Rakendus koosneb erinevatest töökohtadest, mida kasutavad mingi pädevusala liikmed oma töö-ülesannete läbiviimiseks. 50

4.1 Kasutajaliideste loogiline projekteerimine Kasutajaliidese loogilise projekteerimise käigus koostatakse reaalsete kasutusjuhtude kirjeldused. Soovitus! Reaalsete kasutusjuhtude kirjeldusi on mõtet koostada vaid kõige olulisemate ja kriitilisema tähtsusega kasutusjuhtude kohta. Koostamine ja muutmine on üsnagi töömahukas. Kasutajaliidest loogiline projekteerimine toimub loogiliste töökohtade kaupa. Reaalne kasutusjuht kirjeldab süsteemi kasutamise protsessi konkreetselt, disainitaseme täpsusega, ekraanivormi väljade täitmise tasemel. Pööratakse tähelepanu sisend/väljund tehnoloogiatele. Näiteks kui kasutatakse graafilist kasutajaliidest, siis sisaldab reaalse kasutusjuhu kirjeldus süsteemi kasutaja ja süsteemi omavahelise suhtluse kirjeldust, kusjuures viidatakse kasutajaliidese elementidele, mida selle käigus kasutatakse. Reaalse kasutusjuhu tekstikirjeldus sisaldab samu komponente kui detailanalüüsis. Erinevus seisneb selles, et kirjeldatakse kasutajaliidese elementide kasutamist ja selle tulemusel käivituvad transaktsioonid. Selleks, et saaks luua reaalsete kasutusjuhtude mudelit, peavad olema loodud analüüsitaseme kasutusjuhud. Reaalsed kasutusjuhud on kasulikud juhul, kui arendajad või klient nõuavad väga detailset kasutajaliidese kirjeldust enne seda kui alustatakse realiseerimist. Kasutajaliidese disainimise käigus mõelge läbi navigatsioonisüsteem. Välisvõtmete väärtuse valiku realiseerimiseks kasutatakse liitbokse (ingl. k. combo box), loendibokse (ingl. k. list box) või hüpikaknaid. Välisvõtmete väärtuste valik toimub üldjuhul nime järgi ka siis, kui seostavasse tabelisse kirjutatakse kood või number (ka pärast väärtuse valimist peab ekraanile jääma näha nimi, mitte number). Kasutajaliidese osad peavad olema omavahel loogiliselt seotud (näiteks tellimuste ja tellitud kaupade sisestamine). Kasutajaliidese disainimisel võib kasutada mustreid. Vaadake näiteks: Tidwell, J. COMMON GROUND:A Pattern Language for Human-Computer Interface Design [WWW] http://www.mit.edu/~jtidwell/interaction_patterns.html (02.05.2010) wu pattern language [WWW] http://www.trireme.com/wu/browse.htm (02.05.2010) 51

Näide: Joonis 23 Akna kujunduse diagramm. Joonis 23 esitab tegelikult aknakujunduse diagrammi. Aknakujunduse diagramm defineerib akna, kui osa süsteemi kasutajaliidesest. See esitab akna üldise väljanägemise, kuid ei pea sisaldama kõiki pisemaid detaile. Tegemist on prototüübiga. Selle võib joonistada mõne joonistusvahendi abil (nt. Visio) või võib kasutada ka prototüübi ekraanivormide pilte. Järgnevalt on esitatud fragment reaalse kasutusjuhu kirjeldusest. Kasutusjuht: Õpingukava koostamine Tüüp: Reaalne kasutusjuht Stsenaarium (tüüpiline sündmuste järjestus): 1. Üliõpilane alustab õpingukava koostamist. 2. Süsteem kontrollib kas üliõpilasel on õigus õpingukava esitamiseks (OP3.1). Õpingukava võib koostada või muuta semestri esimese kahe nädala jooksul või dekaani nõusolekul ka hiljem. 3. Süsteem kontrollib, kas üliõpilasel on juba loodud semestri õpingukava (OP3.2). Kui ei ole, siis loob uue õpingukava (OP3.3) ja registreerib õpingukava loomise sündmuse (OP0). 4. Süsteem väljastab õpingukava koostamise maketi (avab joonisel 19 näidatud ekraanivormi) koos üliõpilase nime ja üliõpilaskoodiga (väli D), 52

käesoleva semestriga (väli E) ja õpingukava hetke seisundiga (väli G) (OP3.4). 5. Üliõpilane otsib õppeainet (vajutab nupule K) (käivitub kasutusjuht õppeaine otsimine). 6. Üliõpilane lisab uue õppeaine õpingukavasse. 7. Süsteem kuvab õppeaine nime (väli N) ja õppeaine ainepunktide arvu (väli O) Samuti kuvatakse moodulite nimekirja (väli M) (OP3.5), kuhu õppeaine paigutada ja õppeainega antud semestril seotud piiranguid (väli J) (OP3.6). Mõned soovitused kasutajaliidese disaini jaoks: Arusaadavad pealkirjad. Süsteemi seisund peab olema nähtav. Navigeerimine süsteemis peab olema lihtne. Väljad tuleb loogiliselt grupeerida. Järjekindel terminoloogia ja lühendite kasutamine. Vältida akna ülekuhjamist kasutajaliidese elementidega. Vältida aknas liiga suure kasutamata ruumi jätmist. Järjekindel ja mõõdukas värvide kasutamine. Sisestusvälja väärtuse lisamisel peab kasutaja saama visuaalselt hinnata, kui palju sümboleid saab sellesse välja lisada. Välisvõtme väärtuseid peab kasutaja saama valida. Lihtne kursori liikumine. Tab-klahvi kasutamine. Järjekindel graafiliste sümbolite kasutamine. Ühesuguse pildiga nupud peavad tegema kogu rakenduse ulatuses ühte ja seda sama asja. Kui graafilise sümboli tähendust tuleb eraldi seletada, kasutage selle asemel teksti. Lühikorraldused peavad säilitama kõikjal oma tähenduse Valikulised või siis kohustuslikud väljad tuleb selgelt esile tuua. Esiletoomine peab olema ühesugune kogu rakenduse ulatuses. Kasutajatel tuleb aidata vigadest aru saada ja neid parandada. Loetavad ja arusaadavad juhendid. Loetavad nii keelekasutuse kui ka teksti suuruse ja liigendatuse mõttes). Mittesobivate väärtuste sisestamise korral tuleb esitada veateade, mis aitab kasutajal probleemist aru saada ja seda lahendada. Veateated võib logida. 53

Halb näide: Ülikooli õppeinfosüsteemi tarkvarasüsteemi peamenüü. Ülikooli infosüsteem Aine Semester Õpingukava Ekraaninupule vajutades avaneb aken, kus saab registreerida andmeid sellesse tabelisse Õppimine Üliõpilane Õppekava Aine õpingukavas OK Joonis 24 Halvasti kujundatud ekraanivormi näide. 4.2 Transaktsioonide loogiline projekteerimine Luuakse transaktsioonide spetsifikatsioonid tekstilist ja/või graafilist kirjelduskeelt kasutades. Spetsifikatsioon nimetab andmebaasi operatsioonid, millest see transaktsioon koosneb. Iga transaktsioon tuleb siduda mõne kasutaja poolse toiminguga ekraanivormil. Transaktsioon on tegevus või tegevuste jada, mis küsib andmeid andmebaasist või muudab andmeid andmebaasis ja mida viib läbi kas üks kasutaja või rakendusprogramm. Transaktsioonist võib mõelda kui andmebaasi operatsioonide jadast. Transaktsioon on tingitud reaalse maailma sündmusest, mille tulemusel tuleb andmebaasist midagi otsida või viia andmebaasi olevad andmed kooskõlla reaalses maailmas toimunud muutusega. Kui transaktsiooni ei suudeta lõpetada, peab andmebaasisüsteem tagama, et kõik transaktsiooni poolt andmebaasis tehtud muudatused tühistatakse. Kui transaktsioon õnnestub, tuleb kõik tehtud muudatused andmebaasis salvestada. Üks transaktsioon võib hõlmata üht või mitut andmebaasioperatsiooni. Näide: Klient kannab pangas raha ühelt arvelt teisele. Transaktsioonide liigid. Andmete küsimise transaktsioon. Andmete muutmise transaktsioon. Sega-transaktsioon (toimub nii andmete küsimine kui ka muutmine). 54

5 CASE vahendid CASE tähendus: Computer Aided Assisted Automated Software System Engineering CASE vahend on tarkvarasüsteem, mis aitab tarkvara arendajat ühe või rohkema tarkvara arendustsükli etapi jooksul. 5.1 CASE vahendi kasutamisest tulenev võimalik kasu Vähendab kulutusi, eriti seoses tarkvara hooldamisega. Parandab tarkvara kvaliteeti. Kiirendab arendusprotsessi. Suurendab tootlikust. 5.2 Üldised nõuded CASE vahenditele Hea graafika. Võimaldab kirjeldada süsteemi kasutades mudeleid. Mudelitel on erinevat esitusviisid diagrammid, tekst, maatriksid jne. Teisisõnu mudel ei pea olema visuaalne (diagramm). Peab olema võimalik mudeleid koguda, säilitada ja hallata. Peab olema võimalik mudelite elemente sirvida (tavaliselt kuvatakse mudelite elemente hierarhiatena). Muudatuse tegemine mudeli elementi ühel mudelil kannab selle edasi ka teistesse mudelitesse, kus seda mudeli elementi kajastatakse. Peab olema võimalik mudeleid otsida ja visualiseerida. Peab võimaldama automaatselt diagramme organiseerida, nii et oleks võimalikult vähe ristuvaid jooni ja diagramm oleks võimalikult hästi loetav. Peab olema võimalik informatsiooni vahetamine teiste CASE vahenditega (näiteks Extensible Metadata Intrchange e. XMI standardi alusel). See tähendab, et ideaalis peaks olema võimalik mudeli importimine ühe CASE vahendi poolt mingisse spetsiaal-formaadis faili ning seejärel selle faili sisselugemine mõne teise CASE vahendi poolt. CASE vahend peaks võimaldama maksimaalselt projekteerija tööd automatiseerida. Selleks peab vahend võimaldama olemasolevates mudelitest uute mudelite genereerimist. Sealjuures oleks hea kui kasutaja saaks ise määrata reegleid, mida genereerimise juures kasutatakse. Peab olema võimalik genereerida ka järgnevat. Aruanded. Kindlasti peaks vahend võimaldama genereerida aruandeid HTML formaadis dokumentidena. 55

Rakendusmoodulid. Testjuhud. CASE vahend peaks olema integreeritud tekstitöötlus- ja tabelarvutusprogrammidega, kuhu saab edastada mudeli põhjal genereeritud dokumentatsiooni. Peab olema võimalik olemasolevast andmebaasi skeemist või rakendusmoodulitest mudelite genereerimine. Peab olema võimalik rakendusmoodulite ja andmebaasi skripti ning mudelite omavahelise kooskõla tagamine (sünkroniseerimine). Peab olema võimalik mudelite kvaliteedi automaatne hindamine. Peab olema võimalik mudelite omavahelise kooskõlalisuse hindamine ja mudelite omavahelise kooskõlalisuse tagamine. CASE vahend peab võimaldama kirjeldada süsteemi paralleelselt ja mitmevaateliselt (modelleerimise kolmnurk). CASE vahend peab aitama süsteemi mingi metoodika alusel arendada. Nt. Rational Rose kasutaja võib kuid ei pruugi süsteemi arendamisel järgida Rational Unified Process (RUP) metoodikat. Meta-CASE vahendites saavad kasutajad ise defineerida uusi süsteemi modelleerimiseks kasutatavaid keeli. Arendajal peab olema võimalik defineerida uut liiki mudeli-elemente. CASE vahend peab aitama rakendada standardeid (nt. UML). Peab olema võimalik mudelite kuvamine erinevas notatsioonis e. erineva tähistusega. Nt. võib andmete modelleerimise CASE vahend võimaldada vaadata andmebaasi skeemi kirjeldust nii IE, IDEF1X ja UML notatsioonis. Peaks olema võimalik mitme kasutaja üheaegne töö mudeliga. CASE vahend peab võimaldama mudelite versioonikontrolli ja integreerimist. Näiteks võib süsteemianalüüsi projektis iga analüütik töötada ühe kindla allsüsteemi ja registriga. Kuid allsüsteem kasutab ka selliste allsüsteemide ja registrite teenuseid, mida ta ise ei projekteeri. Kõigil analüütikutel peab vajadusel olema võimalik näha tervikmudelit. CASE vahendiga peavad olema integreeritud modelleerimist juhendavad abimaterjalid. CASE vahendiga võiks olla seotud mustrite või universaalsete mudelite teek, kust modelleerija saaks uue mudeli koostamisel endale sobivaid mudeleid või nende alamosi valida. CASE vahend peaks võimaldama simuleerida koostatud mudelite põhjal tulevase süsteemi tööd. Peaks olema võimalik teha päringuid süsteemi kirjelduste põhjal, et leida kirjeldatavat süsteemi iseloomustavaid arvulisi suurusi (tarkvarameetrikate väärtuseid) (nt. olemitüüpide arv, kasutusjuhtude arv, allsüsteemide arv jne.) Näide 1: ERwin CASE on andmete modelleerimise jaoks mõeldud CASE vahend. Mudeli loomiseks saab kasutada nii reaalselt eksisteerivat andmebaasi kui ka andmebaasi loomiseks kasutatavat DDL (Data Definition Language) keelset skripti. Valides menüüst Tasks käsu Reverse Engineer tuleb kõigepealt valida uue mudeli loomisel aluseks võetav mall. Võib valida "Blank diagramm" 56

Seejärel käivitub dialoog: Joonis 25 Pöördprojekteerimise aken CASE vahendis ERwin. Selles aknas saab valida, millise andmebaasisüsteemi andmebaasis põhjal soovite mudelit luua. Valides "Next" avaneb aken, kus on võimalik häälestada seda, kuidas andmebaasi või skripti põhjal andmemudel luuakse. 57

Andmemudeli saab sisse lugeda nii olemasolevast andmebaasi skeemist kui ka andmebaasi loomise skriptifailist. Juhul kui lugeda andmete kirjeldused sisse otse andmebaasist peab olema loodud ühendus vastava andmebaasiga. Seda saab teha menüüst Server käsuga Target Server. Seejärel tuleb luua ühendus vastava andmebaasiga. Joonis 26 Pöördprojekteerimise aken CASE vahendis ERwin. 58

Näide 2: CASE vahendi Rational-Rose võimaldab süsteemi modelleerida kasutades visuaalset modelleerimiskeelt UML. Joonis 27 CASE vahendi Rational-Rose töölaud. 59

Joonis 28 CASE vahendis Rational-Rose Data Definition Language skripti genereerimine. Fragment tulemusest: CREATE TABLE Ruum ( ruumi_nr SMALLINT NOT NULL, hotelli_nr SMALLINT NOT NULL, tyyp CHAR ( 1 ) NOT NULL, hind DECIMAL ( 7, 2 ) NOT NULL, CONSTRAINT PK_Ruum4 PRIMARY KEY (hotelli_nr, ruumi_nr), CONSTRAINT TC_Ruum3 CHECK (VALUE IN ("A","L")) ); CREATE TABLE Hotell ( hotelli_nr SMALLINT NOT NULL, hotelli_nimi VARCHAR ( 50 ) NOT NULL, linn VARCHAR ( 30 ) NOT NULL, CONSTRAINT PK_Hotell5 PRIMARY KEY (hotelli_nr), CONSTRAINT TC_Hotell36 UNIQUE (hotelli_nimi) ); 60