Relasjoner – Normalisering

I innlegget «Relasjoner – Intro» ble ordet «normaliseringsformer» brukt i forbindelse med databasedesign. Teorien og spesielt ordlyden bak normalisering kan fort bli tung og vanskelig å forstå så jeg vil i dette innlegget forklare hva det er gjennom bruk av eksempler. Dessverre så vil der være noen ord og uttrykk vi ikke kommer rundt så det er bare å bite tenna sammen. Vi begynner med noen data i en tabell. Vi kaller den «universalrelasjonen». Universalrelasjonen har ingen spesielle regler utover at man har rader og kolonner. Under har jeg et eksempel på en universalrelasjon. På grunn av plassmangel har jeg brukt en del forkortelser i kolonnene overskriftene. «l_» står for «lege_». «l_navn» blir da «lege_navn». «p_» står for «pasient_» og da er f.eks. «p_navn» det samme som «pasient_navn». Til informasjon så er primærnøkler merket med grønt i kolonneoverskrifta. Universalrelasjonen viser 2 leger som har 3 pasienter og en del annen informasjon.

For å oppfylle 1. normalform (1NF) så kan tabellen ikke inneholde ikke-atomære verdier eller repeterende grupper. Med «ikke-atomære verdier» menes verdier som inneholder flere delverdier. Tabellen inneholder ikke-atomære verdier i feltene «l_adr» og «p_adr» som består av gateadresse, postnr og poststed. Med «repeterende grupper» menes at det finnes mer enn en verdi i krysset mellom rad og kolonne. De repeterende gruppene i tabellen er: «p_personnr», «p_navn», «p_adr» og «p_tlf». Når man deler opp «l_adr» og «p_adr» i sine respektive kolonner («l_adr», «l_postnr», «l_poststed» og «p_adr», «p_postnr», «p_poststed»), og legger den ekstra pasienten i den repeterende gruppa på en egen rad så oppfyller man 1NF. Tabellen under viser hvordan det vil se ut. Legg merke til at «l_id» og «p_personnr» nå er primærnøkkel siden man ikke unikt kan identifisere den riktige raden for en pasient basert på «l_id» alene.

I 2. normalform (2NF) må alle verdier være fullt funksjonelt avhengig av primærnøkkelen. Med «full funksjonell avhengighet» menes at man ikke har noen partielle avhengigheter. Partiell avhengighet betyr at en verdi er avhengig av kun deler av primærnøkkelen (i tabellen over består primærnøkkelen i grønt av «l_id» og «p_personnummer»). «l_navn» er partiell avhengig av «l_id», men ikke «p_personnummer». På samme måte er «p_navn» partiell avhengig av «p_personnummer», men ikke «l_id». For å fikse dette må tabellen splittes i to. Jeg har kalt tabellene «lege» og «pasient». Legg merke til kolonnen «l_id» i tabellen «pasient». Dette er en fremmednøkkel og brukes til å koble pasientene mot riktig lege.

For at en tabell skal kunne være i 3. normalform (3NF) så kan man ikke ha noen transitive avhengigheter. Transitiv avhengighet betyr at en verdi er avhengig av en annen ikke-primærnøkkel-verdi. I de to tabellene over så er «l_poststed» transitivt avhengig av «l_postnr» og «p_poststed» transitivt avhengig av «p_postnr», men verken «l_postnr» eller «p_postnr» er noen primærnøkkel. For å fikse dette så flyttes poststedene ut i en egen tabell (poststed) hvor postnr er primærnøkkelen. Tabellene under oppfyller nå 3NF.

Til slutt skal vi se på Boyce-Codd normalform som også omtales som BCNF eller 3.5NF. For at en tabell skal kunne være i Boyse-Codd normalform, må alle determinanter være kandidatnøkler. En determinant er en attributt eller gruppe attributter som en annen attributt er fullt funksjonelt avhengig av. Et eller flere attributter som sammen identifiserer en entitet unikt kalles en «supernøkkel». Minimalistiske supernøkler, dvs. at man kan fjerne et attributt fra en supernøkkel og så er det fortsatt unikt kalles en kandidatnøkkel. Kandidatnøkler er sikre identifikatorer for en rad, og kan brukes som primærnøkler og som referanser for fremmednøkler. I vår tabell er det ingen brudd på Boyce-Codd normalform. Determinantene er: personnr(pasient), postnr(poststed) og l_id(lege). Kandidatnøklene er: personnr(pasient), postnr(poststed) og l_id(lege). Dersom en tabell er normalisert til 3NF, vil den i de fleste tilfeller også innfri kravene til BCNF. Brudd på BCNF er sjeldne og litt vanskelige å håndtere på en god måte, så derfor stopper man ofte normaliseringen når tabellen er på 3NF. Da har vi vært gjennom den tyngste og viktigste teorien når man skal lage en relasjonsdatabase. Men hvor skal man lage en relasjonsdatabase? Innlegget «Relasjoner – Verktøy» vil kunne gi noen svar på det.