Kapitel 6. Normalisering

Innehållsförteckning
Första normalformen, 1NF
Andra normalformen, 2NF
Tredje normalformen, 3NF

Att normalisera en databas betyder att man konstruerar databasens schema efter vissa regler. Normaliserar gör man alltså medan kan konstruerar databasen och inte i efterhand. Normaliseringen har egentligen ett övergripande mål, att eliminera redundant data. Med redundant menas sådant som är dubbellagrat, det vill säga finns på fler än ett ställe.

Man kan normalisera sin databas i flera steg. Dessa steg har namn. Det första steget kallas första normalformen som förkortas 1NF, efter det så kommer andra och tredje normalformen. Det finns fler normalformer men dessa är de viktigaste.

Första normalformen, 1NF

En tabell är normaliserad enligt första normalformen om:


1. Det inte finns några fält som är likadana.
2. Alla fält i varje post bara har ett värde. 
3. Alla poster i samma fält har samma datatyp.

Vi tittar på tabellen från kapitel 1:


+--------+---------+-------------+
| nummer | namn    | adress      |
+--------+---------+-------------+
|      1 | jonas   | helsingborg |
|      2 | stefan  | klippan     |
|      3 | lennart | bjuv        |
+--------+---------+-------------+
Alla poster (rader) är olika så det är okej enligt 1NF. Alla fält i varje post har bara ett värde, också okej enligt 1NF. Alla poster i samma fält (kolumn) har samma datatyp (int, text, text=), också okej enligt 1NF. Vår tabell är alltså i 1NF.

Vi säger att Stefan bor på två ställen. Han kanske bor i klippan och har en sportstuga i Vemdalen. Ett sätt att göra det är att ändra tabellen så att den ser ut så här:


+--------+---------+-------------------+
| nummer | namn    | adress            |
+--------+---------+-------------------+
|      1 | jonas   | helsingborg       |
|      2 | stefan  | klippan, vemdalen |
|      3 | lennart | bjuv              |
+--------+---------+-------------------+
Att göra så gör att databasen inte är i första normalformen, vi bryter ju mot punkt 2 ovan, och det är inte bra. Det är i de flesta fall inte ens möjligt. För att databasen skall vara i 1NF kan man ändra den så att den ser ut så här:

+--------+---------+-------------+
| nummer | namn    | adress      |
+--------+---------+-------------+
|      1 | jonas   | helsingborg |
|      2 | stefan  | klippan     |
|      2 | stefan  | vemdalen    |
|      3 | lennart | bjuv        |
+--------+---------+-------------+
Nu bor stefan på två ställen och vår tabell är fortfarande i 1NF. Skulle det, vilket det förmodligen gör, bo fler än en Jonas i Helsningborg, så är det bra att vi har det första fältet, nummer. Annars skulle vi inte kunna lägga till en till Jonas i Helsingborg utan att bryta mot punkt 1 ovan.

Andra normalformen, 2NF

För att en tabell skall var i 2NF krävs att den skall vara i 1NF och att alla fält, som inte är nycklar, skall vara direkt relaterade till nyckeln. Nyckeln är det fält som gör varje post unik, i vårt fall "nummer", som är en identifikation för en person som vi lagrar data om.

Vad innebär då 2NF? För att illustrera det skall vi lägga till information om vilka bilar de olika personerna i vår databas har. Vi vill veta vilket bilmärke de har och vilken årsmodell deras bil har. Vi bygger ut tabellen så här:


+--------+---------+-------------+---------+---------+
| nummer | namn    | adress      | bil     | arsmod  |
+--------+---------+-------------+---------+---------+
|      1 | jonas   | helsingborg | saab    | 1979    |
|      2 | stefan  | klippan     | porsche | 2003    |
|      3 | lennart | bjuv        | ferrari | 2004    |
+--------+---------+-------------+---------+---------+
Denna tabell är forfarande i 1NF men inte i 2NF. Anledningen är att bilens marke och framför allt bilens årsmodell, inte är direkt relaterade till nyckeln som ju identifierar en person. Man kan lösa detta genom att flytta fälten "bil" och "arsmod" till en egen tabell med en egen nyckel. Denna tabell kan man sedan relatera till vår persontabell på följande sätt:

[person]
+--------+---------+-------------+-----+
| nummer | namn    | adress      | bil |
+--------+---------+-------------+-----+
|      1 | jonas   | helsingborg | 1   |
|      2 | stefan  | klippan     | 2   |
|      3 | lennart | bjuv        | 3   |
+--------+---------+-------------+-----+

[bil]
+--------+---------+---------+---------+
| nummer | bil     | modell  | arsmod  |
+--------+---------+---------+---------+
|      1 | saab    | 99      | 1979    |
|      2 | porsche | 911     | 2003    |
|      3 | ferrari | 365GT   | 1969    |
+--------+---------+---------+---------+
Nu är tabellen i 2NF och vi har dessutom lagt till mer information om bilarna. Du kanske inte tycker att fältet "bil" i den första tabellen är riktigt enlig 2NF eftersom den inte har med person att göra. Men den har med personen att göra, det är ju personens bil. Däremot så är ju bilens årsmodell ett attribut som hör mer hemma hos bilen än personen, så det hör inte hemma i persontabellen och får inte göra det heller enligt 2NF.

Tredje normalformen, 3NF

Tredje normalformen når man om en tabell är i 2NF och det inte finns några transitiva beroenden. Det är ett fint sätt att säga att inga fält, som inte är nycklar, skall kunna härledas av varandra. Vi säger att vi skall utöka informationen i vår persondatabas med adresser till personerna. Den kan då se up så här:


[person]
+--------+---------+---------------+-------------+-------------+-----+
| nummer | namn    | postadress    | postnummer  | postort     | bil |
+--------+---------+---------------+-------------+-------------+-----+
|      1 | jonas   | tabellgatan 2 | 112 12      | helsingborg | 1   |
|      2 | stefan  | postvägen 16  | 322 13      | klippan     | 2   |
|      3 | lennart | fältstigen    | 561 25      | bjuv        | 3   |
+--------+---------+---------------+-------------+-------------+-----+

[bil]
+--------+---------+---------+---------+
| nummer | bil     | modell  | arsmod  |
+--------+---------+---------+---------+
|      1 | saab    | 99      | 1979    |
|      2 | porsche | 911     | 2003    |
|      3 | ferrari | 365GT   | 1969    |
+--------+---------+---------+---------+
Vi är fortfarande i 2NF, men eftersom postorten är helt beroende av postnummret så är vi inte i tredje normalformen (3NF). För att tabellen skall vara i 3NF måste vi flytta postorten till en egen tabell. Resultatet som är i 3NF kan se ut så här:

[person]
+--------+---------+---------------+-------------+-----+
| nummer | namn    | postadress    | postnummer  | bil |
+--------+---------+---------------+-------------+-----+
|      1 | jonas   | tabellgatan 2 | 112 12      | 1   |
|      2 | stefan  | postvägen 16  | 322 13      | 2   |
|      3 | lennart | fältstigen    | 561 25      | 3   |
+--------+---------+---------------+-------------+-----+

[bil]
+--------+---------+---------+---------+
| nummer | bil     | modell  | arsmod  |
+--------+---------+---------+---------+
|      1 | saab    | 99      | 1979    |
|      2 | porsche | 911     | 2003    |
|      3 | ferrari | 365GT   | 1969    |
+--------+---------+---------+---------+

[postort]
+-------------+-------------+
| postnummer  | postort     |
+-------------+-------------+
| 112 12      | helsingborg |
| 322 13      | klippan     |
| 561 25      | bjuv        |
+-------------+-------------+
Ibland kan det vara lämligt att bryta mot 3NF till exempel för att göra databasdesignen tydligare. Men i de allra flesta fall skall man hålla sin databas enligt tredje normalformen.