Normalisering

1 Februar 2015

Hvis verdien av ein ein (eller eit sett av fleire) attrubutter A bestemmer verdien av ein attributt B, så seier vi at A determinerer B (A -> B) elller at B er funksjonelt avhengig av A. For eksempel determinerer postnr poststad. Når postnr (A) er gitt så er også poststad (B) bestemt. Poststad er altså determinert eller funksjonelt avhengig av postnr. Men det omvendte gjeld ikkje for det fins mange postnr med same poststad.

1NF: Første normalform

Normalformene er enklast å forstå ved å gi eksempel på brot på dei. Så her er først eit eksempel på ein tabell som ikkje er på første normalform:

Kunde
Kunde ID Navn Telefon
123 Robert Ingram 555-861-2025
456 Jane Wright 555-403-1659, 555-776-4100
789 Maria Fernandez 555-808-9633

Navn er her ein ikkje-atomisk attributt, fordi den inneheld både for- og etternavn. Telefon er det som blir kalla for et repeterande attributt, fordi den inneheld fleire verdiar. Det første problemet er enkelt å løysa ved å dela det opp i to attributter. Det andre er litt verre, for ein slik tabell kan vi ikkje realisera i MySQL uten at Telefon blir eit tekstfelt, eller ved å gjera andre kunstgrep.

Vi kan tenkja oss følgande løysing:

Kunde
Kunde ID Fornavn Etternavn Tlf1 Tlf2 Tlf3
123 Robert Ingram 555-861-2025

456 Jane Wright 555-403-1659 555-776-4100 555-403-1659
789 Maria Fernandez 555-808-9633

Her har vi innført to nye attributtar Tlf2, og Tlf3 for å ta vare på fleire telefonnr. Men vi står igjen med fleire problem- For det første: Det er mulig å skriva inn samme verdien inn i to av tlfnr. For det andre: Vi vil få problemer med å skriva eit query for å søkja etter eigaren til et telefonnr. For det tredje: enn om vi treng endå fleire tlnr? I såfall må vi endra på tabell-definisjonen, og det er upraktisk hvis vi alt har begynt å bruka den og leggja inn data. Måten å løysa disse problema er å splitta tabellen vår opp i to:

Kundenavn
Kunde ID Fornavn Etternavn
123 Robert Ingram
456 Jane Wright
789 Maria Fernandez
 
Kundetelefon
Kunde ID Telefon
123 555-861-2025
456 555-403-1659
456 555-776-4100
789 555-808-9633

Her kan vi sørga for at kolonnen Telefon er unik. Då slepp vi å få inn like nr ved ein feil. Det er no enkelt å søkja på telefonnr., og dessuten kan vi skriva inn så mange tlfnr som vi vil på same kunde, for det blir bare nye rader i tabellen Kundetelefon, og vi har ikkje behov for å endra på tabellens utforming.

Første normalform betyr altså: Alle attributter er atomiske og ikkje-repeterande.

2NF: Andre normalform

For å vera på andre normalform, må tabellen vera på første normalform. Anta at vi har følgande tabell som beskriver ein ansatt sine ferdigheter:

Ansattes ferdigheter
Ansatt Ferdighet Arbeidsstad
Jones Typing 114 Main Street
Jones Shorthand 114 Main Street
Jones Whittling 114 Main Street
Bravo Light Cleaning 73 Industrial Way
Ellis Alchemy 73 Industrial Way
Ellis Flying 73 Industrial Way
Harrison Light Cleaning 73 Industrial Way

Vi ser at adressene gjentar seg fordi det er mange rader for same ansatte. 114 Main Street er det for eksempel tre versjonar av, og det betyr at hvis mr. Jones flytter, så må vi inn i alle disse tre radene og endra. Med andre ord er det stor sjanse for å få inkonsistens i våre data. I tillegg bruker vi meir plass enn nødvendig, men det er ikkje så stort problem.

Ansatt
Navn Arbeidsstad
Jones 114 Main Street
Bravo 73 Industrial Way
Ellis 73 Industrial Way
Harrison 73 Industrial Way
 
Ferdigheter
Ansatt Ferdighet
Jones Typing
Jones Shorthand
Jones Whittling
Bravo Light Cleaning
Ellis Alchemy
Ellis Flying
Harrison Light Cleaning

Her er arbeidsstaden til Jones (og alle andre ansatte) skrive inn bare ein gong, slik at vi unngår inkonsistens i data. Men merk at vi fremdeles vil ha mange ansatte på samme arbeidsstad, så her kunne vi gått lenger ved å laga ein tabell som heiter arbeidsstad.

Når vi ser nærmare på dette eksempelet, legg vi merke til at i den første tabellen (Ansattes ferdigheter) har vi determinering frå Ansatt til Arbeidsstad, altså frå bare ein del av primærnøkkelen (som er samansett av Ansatt + Ferdighet), og det er dette som skaper problemet. Tabellen beskriv både ansatt og ferdighetane, og sidan det kan vera mange ferdigheter, får vi dobbeltlagring av Arbeidsstad.

Andre normalform betyr altså: 1NF er oppfylt + det fins ingen determineringer frå del av nøkkelfel til andre felt som ikkje er nøkkel.

3NF: Tredje normalform

Her er et eksempel på ein tabell som oppfyller 2NF, men som ikkje oppfyller 3NF:

Turneringsvinnarar
Turnering År Vinnar Vinnarens førdselsdato
Indiana Invitational 1998 Al Fredrickson 21 Juli 1975
Cleveland Open 1999 Bob Albertson 28 September 1968
Des Moines Masters 1999 Al Fredrickson 21 Juli 1975
Indiana Invitational 1999 Chip Masterson 14 Mars 1977

Problemet her er at vi fremdeles kan ha redundans, fordi vi kan ha samme vinnar over fleire år. Vi ser at Al Fredrickson vant både i 1998 og i 1991. Vi kan ikkje unngå å ha navnet hans to stader (med mindre vi innfører ein ID som kobling). men i tillegg til navnet, så er også Vinnarens fødelsdato dobbeltlagra i hans tilfelle. Her det altså igjen mulig å få inkonsistens, for det er ingenting som hindrar oss å skriva feil på (minst) ein av stadene. Men dette kan vi unngå, og igjen er løysinga å splitta tabellen i to:

Turnering
Turnering År Vinnar
Indiana Invitational 1998 Al Fredrickson
Cleveland Open 1999 Bob Albertson
Des Moines Masters 1999 Al Fredrickson
Indiana Invitational 1999 Chip Masterson
 
Spiller
Spiller Fødselsdato
Chip Masterson 14 Mars 1977
Al Fredrickson 21 Juli 1975
Bob Albertson 28 September 1968

Det er selvfølgelig fremdeles mulig å skriva inn feil fødselsdato, for det er ingenting som kan garantera det. Men det vi unngår er å få to eller fleire fødselsdatoer for same person i databasen vår. I dette eksempelet hadde vi determinering frå Vinnar til Vinnarens fødselsdato. Og dette skapte dobbeltlagring av Vinnarens fødselsdato.

Tredje normalform betyr altså: 1NF og 2NF må vera oppfylt + det skal ikkje vera determineringar frå et ikkje-nøkkelfelt til andre ikkje-nøkkelfelt.

Oppsummering

1. normalform
Regel: Alle verdiar skal være atomære, og ingen felt får innehalda meir enn ein verdi.

2. normalform
Regel: Ingen ikke-nøkkelkolonner får være avhengig av delar av ein kandidatnøkkel.
Forutsetter: 1. normalform.

3. normalform
Regel: Ingen ikke-nøkkelkolonner får vera avhengig av noke anna enn kandidatnøklar.
Forutsetter: 2. normalform (og då også 1. normalform).

Når det gjeld determineringane under 2NF og 3NF kan du også bruka huskeregelen: "The key, the whole key, and nothing but the key" Og mange tilføyer då "so help me Codd". (Codd var pioneren innanfor relasjonsdatabaser :). Altså, alle determineringer skal gå frå heile nøkkelen og bare den.