Tietokannat I c 2007 Olli Luoma olli.luoma@it.utu.fi Kevät 2007
Tiivistelmä Tämän luentomonisteen tarkoituksena on toimia pääasiallisena oppimateriaalina Turun yliopiston Informaatioteknologian laitoksen kurssilla Tietokannat I. Kurssilla käytettiin aiemmin Ramez Elmasrin ja Shamkant B. Navathen sinänsä erinomaista kirjaa Fundamentals of Database Systems, joka kuitenkin todettiin turhan raskaslukuiseksi kurssin ohjeellisen suoritusajankohdan siirryttyä ensimmäiseen opiskeluvuoteen. Luentomoniste onkin pyritty kirjoitettamaan siten, että asiat olisi mahdollista omaksua ennen esimerkiksi kurssin Tietorakenteet ja algoritmit suorittamista. Tämän takia useita asioita on jouduttu huomattavasti yksinkertaistamaan. Lukijan on myös syytä muistaa, että kyseessä on luentomonisteen ensimmäinen versio, joten korjauksia ja kommentteja otetaan vastaan ilolla ja mielihyvällä.
Luku 1 Johdanto Sanan tietokanta ajatellaan tavallisesti tarkoittavan kokoelmaa yhteenkuuluvaa ja jonkin käyttötarkoituksen kannalta oleellista tietoa. Esimerkiksi puhelinluettelon, johon on koottu tietoa henkilöiden ja yritysten nimistä, osoitteista ja puhelinnumeroista, voidaan siten ajatella olevan eräänlainen tietokanta. Kaupan tietokannassa taas voisi olla tietoa vaikkapa asiakkaiden nimistä, osoitteista, tuotteista, tilauksista, tuotteiden toimittajista, toimittajien yhteystiedoista jne. Tällä kurssilla perehdymme ennen kaikkea digitaalisiin tietokantoihin, eli sellaisiin tietokokoelmiin, jotka on tallennettu tietokoneen kiintolevylle. Emme kuitenkaan pidä mitä tahansa kiintolevylle tallennettua tiedostoa tietokantana, vaan asetamme tietokannalle edellämainittujen ehtojen lisäksi myös seuraavat lisävaatimukset: 1. Tietokannan on oltava itsekuvaileva eli sen on sisällettävä tallennetun tiedon lisäksi myös tieto siitä, mikä on kunkin tietoalkion merkitys. Varsinaista tietoa kutsutaan dataksi ja tiedon rakennetta kuvailevaa tietoa metadataksi. Tämän määritelmän mukaan esimerkiksi henkilöiden nimiä, syntymäaikoja, osoitteita, mieliruokia ja puhelinnumeroita tiedostoon tallentavan Java-ohjelman käyttämää tiedostoa ei voida pitää tietokantana, sillä yksittäisten tietoalkioiden merkitys selviää vain tarkastelemalla tiedostoa käyttävää ohjelmaa. 2. Tietokannan on tuettava useita yhtäaikaisia käyttäjiä. Tämä on oikeastaan hyvin luonnollista, sillä esimerkiksi verkkokaupan tai pankin tietokannalla on usein voitava olla useita käyttäjiä. Yhtäaikaisesta käytöstä seuraa kuitenkin muutamia ongelmia. Esimerkiksi edellä mainitussa verkkokaupassa kaksi asiakasta saattaa samanaikaisesti yrittää tilata tuotteen, jota on varastossa vain yksi kappale. Myöhemmin perehdytään tällaisten ongelmien ratkaisemiseen. 3. Tietokannan on tarjottava useita erilaisia näkymiä tietoon. Esimerkiksi tieto tuotteiden tukkuhinnoista voidaan piilottaa verkkokaupan asiakkailta, vaikka kaupan työntekijät tämän tiedon näkisivätkin. Samalla tavoin tietokannan on tarjottava pankkitoimihenkilöille mahdollisuus käsitellä ja tutkia tietoja, joihin tavalliset asiakkaat eivät pääse käsiksi. 4. Tietokannan ja sitä käyttävien ohjelmien on oltava erillisiä. Käytännössä tämä tarkoittaa sitä, että tietokantaa on käsiteltävä selkeän 1
rajapinnan avulla siten, että käyttäjiltä ja tietokantaa käyttäviltä sovelluksilta piilotetaan esimerkiksi tietojen tallennustapa. Nimensä mukaisesti tietokanta sisältää siis ainoastaan tietoa eli dataa ja tietoa kuvailevaa tietoa eli metadataa eikä ota kantaa siihen, millä tavalla tai millaisissa ohjelmissa tietoja käytetään. Periaatteessa voisimme siis muuttaa vaikkapa tietojen tallennustapaa kajoamatta tietokantaa käyttäviin sovelluksiin. Tietokantoja luodaan ja hallitaan useimmiten tähän tarkoitukseen varta vasten luodulla ohjelmistolla, jota kutsutaan tietokannanhallintajärjestelmäksi. Tietokannanhallintajärjestelmän avulla käyttäjien on mahdollista: 1. Luoda uusia tietokantoja. Koska tietokantojen on edellä oppimamme mukaan oltava itsekuvailevia, on tietokannanhallintajärjestemän tarjottava työkalut tietokantaan tallennettavan tiedon rakenteen eli metadatan määrittelyyn. Tietokannanhallintajärjestelmän avulla voidaan tietokantoja tietysti myös tuhota. 2. Kohdistaa tietokantoihin monipuolisia operaatioita eli lisätä, poistaa ja hakea tietoa tietokannasta. Tämä ominaisuus antaa erilaisille käyttäjäryhmille mahdollisuuden tarkastella tietokannan tietoja eri näkökulmista, mikä oli eräs tietokannalle edellä asetetuista vaatimuksista. 3. Hallita suuria tietomääriä tehokkaasti. Tietokantaoperaatioiden on toimittava tehokkaasti, vaikka tietokannassa olisi gigatavuja tai jopa teratavuja dataa. Tehokkaiden hakuoperaatioiden mahdollistamiseksi tietokannanhallintajärjestelmä pitää yllä ns. hakemistoja eli indeksejä. 4. Kohdistaa tietokantaan useita yhtäaikaisia operaatioita. Tämä on tietysti seurausta siitä, että yhdellä tietokannalla on voitava olla useita yhtäaikaisia käyttäjiä. Tietokannanhallintajärjestelmä pyrkii estämään ongelmat lukitusten avulla esimerkiksi siten, että kun joku käyttäjistä muuttaa jonkin tietoalkion sisältöä, eivät muut käyttäjät voi kyseistä tietoalkiota käsitellä. 5. Toteuttaa sovelluksia tietokannanhallintajärjestelmän tarjoaman rajapinnan avulla. Näiden rajapintojen avulla yhtä ja samaa tietokantaa voidaan käyttää eri ohjelmointikielillä toteutetuissa sovelluksissa. Esimerkiksi pankkiautomaattisovellus, verkkopankkisovellus ja pankkitoimihenkilön käyttämä sovellus voivat käyttää samaa tietokantaa, vaikka ne olisikin toteutettu eri ohjelmointikielillä. Käytännössä tietokannanhallintajärjestelmät siis tallentavat tietoja tiedostoihin siinä missä muutkin ohjelmat, mutta tarjoavat korkean abstraktiotason rajapinnan tietojen käsittelyyn. Tietokannanhallintajärjestelmää käyttäen voidaan esimerkiksi pankin tietokannasta helposti hakea kaikkien pankin asiakkaiden nimet, jonkin tietyn asiakkaan tilitiedot tai vaikkapa tilien keskisaldo. Suosituin kaupallinen tietokannanhallintajärjestelmä on pitkään ollut Oracle, jonka markkinaosuutta IBM:n DB2 ja Microsoftin SQL Server ovat 2
viime vuosina kuitenkin onnistuneet kaventamaan 1. Ilmaisista tietokannanhallintajärjestelmistä MySQL lienee edelleen suosituin, vaikka PostgreSQL ja Firebird ovatkin huomattavasti kypsempiä. Yhteistä kaikille edellä mainituille ohjelmistoille on se, että ne perustuvat 1970 esiteltyyn relaatiomalliin [1]. Relaatiomalli on toisaalta helposti omaksuttavissa ja toisaalta tehokkaasti toteutettavissa, minkä vuoksi relaatiomalliin perustuva tietokannat ovat käytännössä syrjäyttäneet muihin tietomalleihin perustuvat tietokannat, kuten esimerkiksi verkkotietokannat ja hierarkkiset tietokannat. Liioittelematta voidaankin sanoa, että käytännössä jokaisen organisaation tiedonhallinnan ytimessä on relaatiotietokanta, sillä valtaosa tietojärjestelmistä rakentuu juuri relaatiotietokantojen varaan. Tietokantaosaamista vaaditaankin paitsi tietokannan ylläpitäjiltä, myös systeemisuunnittelijoilta, sovellussuunnittelijoilta, ohjelmistosuunnittelijoilta, ohjelmoijilta ja vaikkapa teknisiltä arkkitehdeilta. 1 Tilanne vuoden 2005 markkinatutkimuksen mukaan (International Data Corporation). 3
Luku 2 Relaatiomalli Relaatiomallin ideana on käsitellä tietokantaa kokoelmana matemaattisia relaatioita. Mallin matemaattisesta taustasta johtuen joukko-opin perusteiden hallinta helpottaa mallin ymmärtämistä huomattavasti. Suosittelemmekin joukko-opin perusteiden kertaamista ennen perehtymistä relaatiomallin saloihin. 2.1 Relaatiot 2.1.1 Relaatio ja relaatiokaava Sanalla relaatio tarkoitetaan asioiden välistä yhteyttä, suhdetta. Voimme esimerkiksi sanoa, että Aku tykkää Iineksestä tai Mikki tykkää Minnistä [2]. Koska näin sanoessamme tarkoitamme toisaalta Akun ja Iineksen ja toisaalta Mikin ja Minnin välillä vallitsevan jonkilaisen suhteen, on tykkäämisessä selvästikin kyse relaatiosta. Samalla tavoin voimme sanoa, että Masa tilaa Tuulilasia ja Lissu tilaa Eevaa. Lehden tilaamista kuvaavalla relaatiolla on siten kaksi ominaisuutta, tilaaja ja lehti. Relaation ominaisuuksia kutsutaan attribuuteiksi. Voimme kuvata tilaamisrelaatiota seuraavan relaatiokaavan avulla: Tilaus(Tilaaja,Lehti) Kaavan perusteella relaatio Tilaus siis liittää toisiinsa tiedon tilaajasta ja lehdestä. Yksittäistä tilaajan ja lehden muodostamaa paria nimitetään monikoksi tai tuplaksi. Toisinaan monikkoa kutsutaan myös tietueeksi. Monikkoja voidaan esittää luettelemalla attribuuttien arvot merkkien < ja > sisällä, joten Tilaus-relaatiossamme on kaksi monikkoa: <Masa,Tuulilasi> ja <Lissu,Eeva>. Havainnollisimmin relaatiot voidaan esittää tauluina, joissa sarakkeet vastaavat attribuutteja ja rivit monikkoja. Kuvassa 2.1 on esitetty relaatiota Tilaus vastaava taulu. Yleisesti relaatiokaava on muotoa Relaatio(Attribuutti 1, Attribuutti 2,..., Attribuutti n ), missä Relaatio on relaation nimi ja Attribuutti 1, Attribuutti 2,..., Attribuutti n relaation attribuuttien nimet. Relaation attribuuttien määrää kutsutaan relaation asteeksi ja monikkojen määrää kardinaliteetiksi tai kooksi. Siten esi- 4
Tilaus Tilaaja Lehti Masa Lissu Tuulilasi Eeva Kuva 2.1: Esimerkki relaation tauluesityksestä. Tilaus Tilaaja Lehti Kestotilaus Lissu Eeva Ei Lissu Cosmopolitan Kyllä Hessu Tuulilasi Kyllä Hessu Eeva Kyllä Kuva 2.2: Kuvan 2.1 relaatio monikkojen ja attribuutin lisäämisen jälkeen. merkiksi kuvan 2.1 relaation Tilaus aste on 2 ja koko 2. Relaatioita ja attribuutteja voi nimetä vapaasti edellyttäen, että jokaisen attribuutin nimi on yksikäsitteinen, eli kahdella relaation attribuutilla ei ole samaa nimeä. Selvyyden vuoksi on kuitenkin syytä valita mahdollisimman kuvaavat nimet 1. Koska relaatio on monikkojen muodostama joukko, voimme esittää kuvan 2.1 relaation myös joukkona {<Masa,Tuulilasi>,<Lissu,Eeva>}. Siten monikoiden keskinäisellä järjestyksellä ei ole merkitystä, mutta yksittäisen monikon arvojen järjestyksellä on. Niinpä esimerkiksi {<Lissu,Eeva>,<Masa,Tuulilasi>} ja {<Masa,Tuulilasi>,<Lissu,Eeva>} ovat identtiset, mutta <Masa,Tuulilasi> ja <Tuulilasi,Masa> eivät, mikä on oikeastaan varsin ilmeistä, sillä Masa tilaa Tuulilasia, ei Tuulilasi Masaa. Relaation kaava on yleensä pysyvämpi kuin relaation sisältö. Jos Lissu tilaa Eevan lisäksi vielä vaikkapa Cosmopolitanin, lisäämme relaatioon Tilaus monikon <Lissu,Cosmopolitan>. Jos taas Masa peruuttaa oman tilauksensa, poistamme monikon <Masa,Tuulilasi>. Ja jos uusi ystävämme Hessu tilaa Tuulilasin ja Eevan, lisäämme tietysti monikot <Hessu,Tuulilasi> ja <Hessu,Eeva>. Jokaisessa tapauksessa relaation kaava siis säilyy, mutta sisältö muuttuu. Joissakin tapauksissa voimme tietysti joutua muuttamaan myös relaatiokaavaa. Jos esimerkiksi tieto siitä, onko kyseessä kestotilaus vai määräaikainen tilaus, muuttuu jostain syystä oleelliseksi, on meidän lisättävä relaation Tilaus kaavaan tätä tietoa kuvaava attribuutti. Edellä mainittujen päivitysoperaatioiden ja attribuutin lisäämisen jälkeen relaatio Tilaus voisi olla vaikkapa kuvassa 2.2 esitetyn kaltainen. 2.1.2 Pääavain ja vierasavain Relaation pääavain tai yksinkertaisemmin vain avain on yksinkertaisesti sellainen attribuuttijoukko, jonka perusteella monikot voidaan tunnistaa relaation sisällöstä riippumatta. Toisin sanoen joukon attribuuttien arvojen yhdistelmän on oltava erilainen relaation jokaisessa monikossa. Attribuutit Tilaaja ja Lehti eivät siten yksinään kelpaa relaation Tilaus avaimiksi, sillä yksi 1 Esimerkiksi Tyyppi ja Arvo ovat yleensä huonoja nimiä, sillä ne eivät juurikaan kerro attribuutin roolista relaatiossa. Kukapa osaisi kertoa, millaista tietoa esimerkiksi kaavan Taulu(Arvo1,Arvo2,Arvo3) mukainen relaatio sisältää? 5
ja sama tilaaja voi tilata montaa eri lehteä ja yhdellä lehdellä voi olla monta tilaajaa. Näiden attribuuttien yhdistelmä sen sijaan kelpaa avaimeksi, sillä niiden perusteella voidaan yksikäsitteisesti tunnistaa jokainen relaation rivi. Tämä pätee sekä kuvassa 2.1 että kuvassa 2.2 esitettyyn Tilausrelaatioon. Attribuutteja, jotka kuuluvat avaimeen kutsutaan yksikertaisesti avainattribuuteiksi. Relaatiokaavassa avainattribuutit erotetaan muista attribuuteista alleviivaamalla. Siten voimme tarkentaa kuvassa 2.2 esitetyttyä relaatiota seuraavasti: Tilaus(Tilaaja,Lehti,Kestotilaus) Tarkasti ottaen avaimen muodostavan attribuuttijoukon on yksikäsitteisyyden lisäksi täytettävä myös minimaalisuuden ehto. Avain on minimaalinen silloin, jos siitä ei voida poistaa yhtään attribuuttia ilman, että sen yksikäsitteisyys katoaa. Esimerkiksi kuvan 2.2 relaation avaimeksi ei kelpaa attribuuttien Tilaaja, Lehti ja Kestotilaus yhdistelmä, sillä Kestotilaus voidaan poistaa yksikäsitteisyyden kärsimättä. Avaimesta puhutaan usein myös id:nä, minkä takia myös relaation avainattribuutti - kuten esimerkiksi asiakasnumero, tilinumero tai tuotenumero - nimetään usein lyhyemmin Id:ksi. Mitä tahansa attribuuttijoukkoa, joka sisältää pääavaimen attribuutit, kutsutaan superavaimeksi. Vierasavain eli viiteavain puolestaan on sellainen attribuuttijoukko, joka viittaa jonkin relaation pääavaimeen. Vierasavaimen käsite on erittäin keskeinen, sillä juuri vierasavainten käyttö mahdollistaa tiedon hajauttamisen useisiin tauluihin. Vierasavainten käyttöä valotetaan tarkemmin seuraavassa osassa. 2.2 Relaatiotietokannat 2.2.1 Relaatiotietokanta Relaatiotietokannan voidaan ajatella olevan kokoelma edellä esitellyn kaltaisia relaatioita. Koska relaatioita voidaan yksinkertaisimmin käsitellä tauluina, voidaan relaatiotietokantaa käsitellä kokoelmana tauluja. Tietokannan relaatiokaava tai lyhyemmin tietokantakaava voidaan esittää tietokantaan kuuluvien relaatioiden kaavojen avulla. Siten voimme määritellä esimerkiksi seuraavanlaisen relaatiotietokannan 2. Asiakas(Id,Etunimi,Sukunimi) Tilaus(AsiakasId,TuoteId) Tuote(Id,Nimi,Kuvaus,ToimittajaId) Toimittaja(Id,Nimi) Kuvassa 2.3 on esitetty edellisen tietokantakaavan mukainen relaatiotietokanta. Vaikka tietokannan taulut on nimettävä yksikäsitteisesti, voi useassa relaatiossa olla samannimisiä attribuutteja. Edellisessä tietokantakaavassa esimerkiksi attribuutti Id esiintyy relaatioissa Asiakas, Tuote ja Toimittaja. Sekaannusten välttämiseksi voimmekin tarkentaa attribuuttien nimiä relaatioiden 2 Tilan säästämiseksi on esimerkkitietokannastamme jätetty pois hyvinkin oleellisia attribuutteja, kuten esimerkiksi asikkaitten ja toimittajien yhteystiedot, tuotteiden varastotilanne sekä tieto siitä, onko tilaus jo toimitettu. 6
Asiakas Id Etunimi Sukunimi 1 Orimatti Teuras 2 Laupias Psaltari 3 Hanhikki Hillosilmä Tilaus AsiakasId TuoteId 1 1 2 1 2 3 Tuote Id Nimi Kuvaus Hinta ToimittajaId 1 Hilavitkutin Laatuisa vitkutin 10.99 2 2 Vimpain Vimmattu vimpaaja 99.99 1 3 Masiina Tuotantoväline lisäarvon tuottamiseen 12.50 1 4 Jiirisaha Komea sähkötyökalu 0.99 2 Id Toimittaja Nimi 1 Jaskan vimpain 2 Orimattilan kone Kuva 2.3: Esimerkki yksinkertaisesta relaatiotietokannasta. nimillä eli kirjoittamalla esimerkiksi Asiakas.Id, Tuote.Id ja Toimittaja.Id. Näin voimme esimerkiksi luetella tietokantamme vierasavaimet sekä avaimet, joihin vierasavaimet viittaavat 3. AsiakasId Asiakas.Id TuoteId Tuote.Id ToimittajaId Toimittaja.Id Kuvassa 2.4 on esitetty edellä mainittujen viiteavainten kohteet monikko monikolta. Esimerkiksi Tilaus-taulun rivin <1,1> ensimmäisen attribuutin arvo viittaa Asiakas-taulun riviin <1,Orimatti,Teuras> ja toisen attribuutin arvo Tuote-taulun riviin <1,Hilavitkutin,...>. Voimme siis yksinkertaisemmin sanoa, että Tilaus-taulun monikko <1,1> viittaa Asiakas-taulun monikkoon <1,Orimatti,Teuras> ja Tuote-taulun monikkoon <1,Hilavitkutin,...>. On syytä huomauttaa, että vaikka esimerkissämme kaikki vierasavaimet koostuvat vain yhdestä attribuutista, voi vierasavain hyvin koostua useammastakin attribuutista. Kannattaa myös huomata, että monikko saattaa viitata myös saman relaation monikkoon. Voisimme esimerkiksi määritellä relaation Työntekijä seuraavaa relaatiokaavaa käyttäen: Työntekijä(Id, Etunimi, Sukunimi, EsimiesId) Tässä relaatiossa EsimiesId on vierasavain, joka viittaa Työntekijärelaation avaimeen Id. Tietokantaan voidaan kohdistaa kahdenlaisia operaatioita: kyselyitä eli tietokantaoperaatioita, joiden avulla haetaan tietoa tietokannasta sekä päivityksiä, jotka muuttavat tietokannan sisältöä 4. Kyselyiden avulla 3 Koska relaatiolla voi olla vain yksi pääavain, myös pelkkien relaatioiden luetteleminen riittäisi. 4 Myös tietokannan relaatiokaavaa voidaan muuttaa esimerkiksi attribuutteja ja tauluja lisäämällä tai poistamalla, mutta tällaisia operaatioita ei yleensä lasketa varsinaisiksi tietokantaoperaatioiksi. 7
Asiakas Id Etunimi Sukunimi 1 Orimatti Teuras 2 Laupias Psaltari 3 Hanhikki Hillosilmä Tilaus AsiakasId TuoteId 1 1 2 1 2 3 Tuote Id Nimi Kuvaus Hinta ToimittajaId 1 Hilavitkutin Laatuisa vitkutin 10.99 2 2 Vimpain Vimmattu vimpaaja 99.99 1 3 Masiina Tuotantoväline lisäarvon tuottamiseen 12.50 1 4 Jiirisaha Komea sähkötyökalu 0.99 2 Id Toimittaja Nimi 1 Jaskan vimpain 2 Orimattilan kone Kuva 2.4: Kuvan 2.3 tietokannan viittausten kohteet. Tuote Id Nimi Kuvaus Hinta Toimittaja 1 Hilavitkutin Laatuisa vitkutin 10.99 Orimattilan kone 2 Vimpain Vimmattu vimpaaja 99.99 Jaskain vimpain 3 Masiina Tuotantoväline lisäarvon tuottamiseen 12.50 Jaskan vimpain 4 Jiirisaha Komea sähkötyökalu 0.99 Orimattilan kone Kuva 2.5: Esimerkki huonosta suunnittelusta. Ei näin. voimme esimerkiksi hakea kuvan 2.3 tietokannasta kaikki Orimatti Teuraan tilaamat tuotteet tai Laupias Psaltarin tilaamien tuotteiden yhteishinnan. Päivitysten avulla taas voidaan lisätä ja poistaa rivejä sekä muuttaa rivien sisältöä. Kyselyiden ja päivitysten esittämiseen SQL-kielen avulla perehdytään myöhemmin. Kuva 2.4 antaa myös aavistuksen siitä, että viiteavaimet ja avaimet näyttelevät keskeistä osaa tiedon jäsentämisessä useampaan tauluun. Tiedon hajauttamisella saavutetaan useita etuja, kuten esimerkiksi pieni tallennustilan tarve. Voisimme esimerkiksi poistaa Toimittaja-taulun ja korvata Tuote-taulun attribuutin ToimittajaId toimittajan nimellä. Tällöin tilanne olisi kuvassa 2.5 esitetyn kaltainen. Olettaen, että kokonaisluvun tallentamiseen tarvitaan 4 tavua ja merkkijonon merkin tallentamiseen 1 tavu, tarvittaisiin kuvan 2.5 Tuote-taulun tietojen tallentamiseen 222 tavua. Kuvassa 2.3 esitettyjen taulujen Tuote ja Toimittaja tietojen tallentamiseen taas tarvitaan vain 205 tavua, vaikka molemmat versiot sisältävät yhtä paljon tietoa. Ero olisi tietysti paljon dramaattisempi, jos tuotteita olisi enemmän tai toimittajista pidettäisiin yllä esimerkiksi yhteystietoja. Redundanssin eli toiston eliminointi vaatii sekä suunnittelumenetelmien että normalisoinnin hyvää hallintaa. Tietokannan suunnitteluun ja normalisointiin perehdytään luvuissa 4 ja 7. 8
2.2.2 Eheyssäännöt Jotta viiteavainten merkitys säilyisi, on meidän asetettava pää- ja vierasavainattribuuttien arvoille joitakin lisäehtoja eli ns. eheyssääntöjä. Ensimmäinen ja helpommin täytettävä ehto on entiteettieheys, joka vaatii, että yhdessäkään monikossa ei yhdenkään avainattribuutin arvo saa olla ns. määrittelemätön arvo eli NULL. Toinen ehto on viite-eheys eli se, että jokaisen monikon viiteavainattribuuttien arvot viittaavat olemassolevien monikkojen avainattribuuttien arvoihin. Yksinkertaisemmin tämä voidaan ilmaista niin, että kaikkien viittausten on kohdistuttava olemassaoleviin monikkoihin. Jos tietokanta täyttää nämä säännöt, sen sanotaan olevan eheä. Esimerkiksi kuvan 2.3 tietokanta on eheä, sillä se täyttää nämä ehdot. Esimerkiksi se, ettei Hanhikki Hillosilmään liity yhtään tilausta, ei riko viite-eheyttä, koska viite-eheys vaatii jokaisen vierasavaimen arvoa vastaavan pääavaimen arvon olemassaoloa, ei päinvastoin. Eheyssäännöt luonnollisesti rajoittavat tietokantaan kohdistettavia päivityksiä. Tarkastellaan esimerkiksi seuraavia operaatioita: 1. Asiakkaittemme sankka joukko kasvaa, joten lisäämme Asiakas-relaatioon monikon <NULL,Marsipaani,Räikkönen>. Operaatio estetään, sillä se rikkoisi entiteettieheyden. 2. Meiltä tilataan jiirisaha, joten lisäämme Tilaus-tauluun rivin <4,4>. Lisäys rikkoisi viite-eheyden, sillä Asiakas-taulussa ei ole riviä, jossa attribuutin Id arvo olisi 4. Operaatio siis estetään. 3. Hanhikki Hillosilmä tilaa vimpaimen. Lisäämme Tilaus-tauluun rivin <3,2>. Operaatio ei riko eheyssääntöjä, sillä kumpikaan monikon avainattribuuttien arvoista ei ole NULL ja ne viittaavat olemassaoleviin monikkoihin eli monikkoihin <3,Hanhikki,Hillosilmä> ja <2,Vimpain,Vimmattu vimpaaja,99.99,1>. 4. Orimatti Teuraan tilaama vitkutin on toimitettu. Poistamme Tilausrelaatiosta monikon <1,1>. Operaatio ei riko eheyssääntöjä. 5. Orimattilan kone osoittautuu epäluotettavaksi toimittajaksi. Poistamme Toimittaja-taulusta rivin <2,Orimattilan kone>. Operaatio estetään, sillä se rikkoisi viite-eheyden, koska relaatiossa Tuote on poistettavaan monikkoon viittaavia rivejä. 6. Muutamme pahuuttamme jiirisahan, tuon jykevähampaisen nakertajan, avainattribuutin Id arvoksi 5. Operaatio ei riko viite-eheyttä, sillä yksikään asiakkaistamme ei ole tilannut jiirisahaa eikä mikään Tilaustaulun riveistä siten viittaa Tuote-taulun riviin <4,Jiirisaha,...>. 7. Hanhikki Hillosilmä ottaa miehensä Orimatin sukunimen. Päivitämme rivin <3,Hanhikki,Hillosilmä> muotoon <3,Hanhikki,Teuras> ilman eheyden rikkoutumista. Miten viides päivityoperaatio eli Orimattilan koneen poistaminen sitten pitäisi tehdä? Jotta operaatio ei rikkoisi viite-eheyttä, pitäisi meidän ensin poistaa ne Tuote-taulun rivit, jotka viittaavat poistettavaan monikkoon, eli rivit <1,Hilavitkutin,...,2> ja <4,Jiirisaha,...,2>. Jotta nämä rivit 9
puolestaan voitaisiin poistaa, pitäisi meidän ensin poistaa ne Tilaus-taulun rivit, jotka viittaavat näihin riveihin. Käytännössä tietokannanhallintajärjestemät poistavat viittaavat monikot automaattisesti tai estävät viite-eheyden rikkovat operaatiot. Tähän perehdytään tarkemmin SQL-kielen yhteydessä luvussa 5. 10