Normalisering

Den här texten är översatt och fritt tolkad från DatabaseDev, texten är alltså tolkad såsom ja tycker den ska översättas så om du kopierar allt detta och får fel på nån uppgift så är det inte mitt fel (som ju för övrigt gäller det mesta här på min blogg/vlogg/artikeltrams)

I databas design finns det sk. standarder som kallar ”normal forms”. Processen att få dina tabeller och data att matcha dessa standarder kallas normalisering. Genom att normalisera din data och dina tabeller slipper du onödig, dubbel information och skapar bättre organiserad data som är lättare att söka efter och gör att ändringar blir lättare i framtiden. När man normaliserar data grenar man ofta av tabeller till flera tabeller och sätter ihop dom med nycklar istället. (Foreign key, primary keys).

Data normalisering är en del av databas design och är inte unik för någon sorts RDBMS (relational database management system, design verktyg). Det finns i ordningen, första, andra, tredje, Boyce-Codd, fjärde, femte och sjätte normal formen. Varje form en ökad grad av regler och förutsätter att den tidigare nivåns regler har uppfyllts. Många databasdesigners anser att om man har uppnått den tredje graden av normalisering så är de flesta design problemen lösta. Högre nivåer kan dock vara användbara i vissa fall.

Den första normal nivån 1NF (First normal form)

Regel:
I den första nivån av normalisering finns det inga repeterande grupper.

En repeterande grupp är en mängd data eller relaterade fält som uppstår flera gången på en rad.

Ett exempel:
Exempel tabellen nedanför bryter mot reglerna i 1NF, leta efter fält som innehåller för mycket data och repeterande grupper.

EMPLOYEES_PROJECTS_TIME

En tabell med fält som innehåller för mycket data
EmployeeID Name Project Time
EN1-26 Sean O’Brien 30-452-T3, 30-457-T3, 32-244-T3 0.25, 0.40, 0.30
EN1-33 Amy Guya 30-452-T3, 30-382-TC, 32-244-T3 0.05, 0.35, 0.60
EN1-35 Steven Baranco 30-452-T3, 31-238-TC 0.15, 0.80
EN1-36 Elizabeth Roslyn 35-152-TC 0.90
EN1-38 Carol Schaaf 36-272-TC 0.75
EN1-40 Alexandra Wing 31-238-TC, 31-241-TC 0.20, 0.70

Exemplet ovan adresserar även ett annat design problem, nämligen, att varje fält ska innehålla den minsta meningsfulla mängd värden och det ska inte finnas några repeterande värden i samma fält.

Varför är det ett problem med flera värden i samma fält?
I exemplet skulle det inte gå att sortera (med SQL) på efternamn och man skulle heller inte kunna se vilken tid som hörinhopp med vilket projekt.

EMPLOYEES_PROJECTS_TIME

En tabell med repeterande grupper
EmpID Last Name First Name Project1 Time1 Project2 Time2 Project3 Time3
EN1-26 O’Brien Sean 30-452-T3 0.25 30-457-T3 0.40 32-244-T3 0.30
EN1-33 Guya Amy 30-452-T3 0.05 30-382-TC 0.35 32-244-T3 0.60
EN1-35 Baranco Steven 30-452-T3 0.15 31-238-TC 0.80
EN1-36 Roslyn Elizabeth 35-152-TC 0.90
EN1-38 Schaaf Carol 36-272-TC 0.75
EN1-40 Wing Alexandra 31-238-TC 0.20 31-241-TC 0.70

Varför är repeterande grupper ett problem?
Om en anställt var tilldelat ett fjärde projekt skulle vi bli tvungna att lägga till ytterligare två nya fält till tabellen. Det skulle också vara svårt att se den sammanlagda tiden lagd på ett särskilt projekt.

Dessa design problem är ett vanligt misstag bland nybörjare som är vana o tänka i Excel liknande tankesätt, dvs. med horisontella data kolumner. När vi designar tabeller till bra relationsdatabaser måste vi tänka mer vertikalt.

Designa för att uppnå 1NF

Nu ska vi titta på hur vi gör om exemplet ovan så vi följer reglerna för första normala formen.

Leta efter repeterande grupper av data, tänkt vertikalt och tänkt på att liknande data ska hållas i samma fält. Länka ihop tabellerna med primär och sekundär nycklar. (Markerade med en * nedan)

EMPLOYEES

* EmployeeID Last Name First Name
EN1-26 O’Brien Sean
EN1-33 Guya Amy
EN1-35 Baranco Steven
EN1-36 Roslyn Elizabeth
EN1-38 Schaaf Carol
EN1-40 Wing Alexandra

PROJECTS_EMPLOYEES_TIME

* ProjectNum ** EmployeeID Time
30-328-TC EN1-33 0.35
30-452-T3 EN1-26 0.25
30-452-T3 EN1-33 0.05
30-452-T3 EN1-35 0.15
31-238-TC EN1-35 0.80
30-457-T3 EN1-26 0.40
31-238-TC EN1-40 0.20
31-241-TC EN1-40 0.70
32-244-T3 EN1-33 0.60
35-152-TC EN1-36 0.90
36-272-TC EN1-38 0.75

Om en anställd i detta fall skulle tilldelas ett nytt projekt skulle vi bara behöva lägga till en nya rad. Det skulle också vara lättare att söka efter projekt då projektnumren finns sparade i en enda rad.

Innan du läser vidare om normalisering kan det vara lite klokt att läsa om beroendeförhållanden – functional dependencies.

Den andra normal nivån 2NF (Second normal form)

Nu när vi har kollat lite på den första nivån ska vi hugga in i den andra normala formen.

Regel:
En tabell som är av andra normala formen skall uppnå nivå ett och varje icke-nyckelfält är helt funktionellt beroende av primär nyckeln.

Icke nyckelfält är alltså inte primär- eller sekundärnyckel. (Primary/ foreignkey)

En lite jobbig regel men den blir ganska klar med ett exempel

Exempel:

En tabell med flera fält i primärnyckeln och repeterande data.
*EmployeeID LastName FirstName *ProjectNumber ProjectTitle
EN1-26 O’Brien Sean 30-452-T3 STAR manual
EN1-26 O’Brien Sean 30-457-T3 ISO procedures
EN1-26 O’Brien Sean 31-124-T3 Employee handbook
EN1-33 Guya Amy 30-452-T3 STAR manual
EN1-33 Guya Amy 30-482-TC Web Site
EN1-33 Guya Amy 31-241-TC New catalog
EN1-35 Baranco Steven 30-452-T3 STAR manual
EN1-35 Baranco Steven 31-238-TC STAR prototype
EN1-36 Roslyn Elizabeth 35-152-TC STAR pricing
EN1-38 Schaaf Carol 36-272-TC Order system
EN1-40 Wing Alexandra 31-238-TC STAR prototype
EN1-40 Wing Alexandra 31-241-TC New catalog
Bra o veta shit: ”Primärnyckel” En primär nyckel avgör vad som är unikt i tabellen så att data kan adresseras. En primär nyckel kan bestå av data från flera fält ihop men det kan bara finnas en nyckel per tabell, en sekundär (foreignkey på engelska) är en primärnyckel som satts i en annan tabell. En sekundärnyckel används alltså för att referera till en rad i en annan tabell. (Kanske lite klantigt förklarat men jag tror den som läser detta hänger med)

Fortsättning av exemplet.

I tabellen ovan så bryter vi mot båda reglerna för 2NF. Primärnyckeln består av två fält och det finns repeterande data som inte finns i dessa två kolumner. Det är alltså ganska naturligt i detta fall att det är två tabeller som sitter ihopp i en.

I en väl designad databas hade så hade duplicerade primär nycklar delats upp i flera tabeller. Detta antaget att datan i dessa fält sällan byts. T.ex. personnummer, id-nummer etc.

Varför är inte detta bra?

Om vi har repeterande data i en kolumn får problem både med säkerheten och kapaciteten. Med datasäkerheten i detta fall menar vi att data kan skilja sig åt beroende på vilken rad vi tittar. Vi får också en förlorad prestanda då vi måste söka genom fler rader för att hitta det vi vill åt. Om vi ska uppdatera Sean´s namn i exemplet ovan måste vi uppdatera tre st olika rader. Risken att nått blir fel ökar och vi kan inte garantera att Sean stavas likadant på alla rader. Lika så tar Sean upp två fält mer än vad som absolut behövs.

Anledningen, lite mer akademiskt talat, till att vi får detta fel (anomalie / avvikelse) är att fälten LastName, FirstName och ProjectTitle inte till fullo har beroende till primärnyckeln. EmployeeID avgör vad som ska stå i LastName men värdet ProjectNum har inget med den att göra. Liknande bestämmer ProjectNum vad som ska stå i ProjectTitle.

Dessa ikke nyckel fält är alltså bara delvis beroende av nyckeln och du minns väll vad som stod i regeln.

En tabell som är av andra normala formen skall uppnå nivå ett och varje ikke-nyckelfält är helt funktionellt beroende av primär nyckeln.

Lösningen blir i detta fall att bryta ner tabellen till ”mindre” tabeller.

Designa för att uppnå 2NF

Vi ska nu designa föregående exempel men hålla oss till reglerna i 2NF. Ingen repeterande data i icke-nyckelfält!

1. Först måste vi angöra vilka fält som hör ihopp. Tänk på vilka fält som är avgörare och vilka fält som avgörs beroende på detta. Skapa en tabell och lägg all data i den tabellen.

2. Klura ut vilken kolumn som kan användas som primär nyckel i tabellen och hur relationen mellan tabellerna ska se ut. Om du måste så använda sekundärnycklar och sambandstabeller (tabell som bara innehåller relationen mellan två tabeller).

3. Markera primärnyckel i varje tabell och kopiera in datan. Se till att du inte har repeterande data i icke nyckelfält.

Lösning:

EMPLOYEES

*EmployeeID Last Name First Name
EN1-26 O’Brien Sean
EN1-33 Guya Amy
EN1-35 Baranco Steven
EN1-36 Roslyn Elizabeth
EN1-38 Schaaf Carol
EN1-40 Wing Alexandra

EMPLOYEES_PROJECTS

**EmployeeID **ProjectNum
EN1-26 30-452-T3
EN1-26 30-457-T3
EN1-26 31-124-T3
EN1-33 30-328-TC
EN1-33 30-452-T3
EN1-33 32-244-T3
EN1-35 30-452-T3
EN1-35 31-238-TC
EN1-36 35-152-TC
EN1-38 36-272-TC
EN1-40 31-238-TC
EN1-40 31-241-TC

PROJECTS

*ProjectNum ProjectTitle
30-452-T3 STAR manual
30-457-T3 ISO procedures
30-482-TC Web site
31-124-T3 Employee handbook
31-238-TC STAR prototype
31-238-TC New catalog
35-152-TC STAR pricing
36-272-TC Order system
Sammanställning än så länge:

1NF:
– Inte massa olika data i samma fält (t.ex. 15, 20, 55 elelr för+efternamn)
– Inte massa olika kolumner med samma data (t.ex. ”Tid1” 15 – ”Tid2” – 43) Tänk vertikalt.

2NF:
Inte repeterande data i samma kolumn (om det inte är en nyckel). (T.ex. samma elev på flera rader.)
Alla kolumner som inte är nycklar ska vara beroende helt av primärnyckeln. (Annars ska dom ju vara i en annan tabell)

Den tredje normala nivån 3NF (Third normal form)

Ok, hög tid att dyka ner i den tredje formen av normalisering.

Regel:
En tabell som är av tredje normala formen skall uppnå nivå två och inte innehålla några transitiva beroenden.

Hoppsan, transitiva beroenden, finns knappt i ordboken men det heter ”transistive dependency” på engelska. Krångligt akademisk men är inte så krångligt som det låter.

Lite matematik: Om A –> B och B –> C så är C beroende transitivt av A. Skaka o baka så har du en kaka!

Exempel:

En tabell med ett enda primär-nyckel kolumn och repeterande data i en icke-nyckel kolumn
*ProjectNum ProjectTitle ProjectMgr Phone
30-452-T3 STAR manual Garrison 2756
30-457-T3 ISO procedures Jacanda 2954
30-482-TC Web site Friedman 2846
31-124-T3 Employee handbook Jones 3102
31-238-TC STAR prototype Garrison 2756
31-241-TC New catalog Jones 3102
35-152-TC STAR pricing Vance 3022
36-272-TC Order system Jacanda 2954

Leta i exemplet ovan efter repeterande data.

Telefonnumret repeteras varje gång projekt ledaren finns med. Vem som är projektledare beror på vilket projekt vi menar men telefonnumret beror på vilken projekt ledare vi har. Dvs. ProjectNum –> ProjectTitle och ProjectMgr –> Phone, vi har alltså ett transistivt beroende mellan telefonnummer och projektnumret. Och vad sa regeln? Jo gott och gott att alla fält skall vara direkt beroende av primär-nyckeln. Lösningen blir igen att splitta tabellen till två.

Designa för att uppnå 3NF

1. Leta efter fält kolumner som hör ihopp och skapa tabeller till dessa.
2. Lägg in exempel datan och leta efter onödiga repetitioner av data (inte primär nyckeln).
3. Leta upp primärnycklar för tabellerna och om du måste så skapa sekundär-nycklar.

Lösning:

PROJECTS

*ProjectNum ProjectTitle **ProjectMgr
30-452-T3 STAR manual Garrison
30-457-T3 ISO procedures Jacanda
30-482-TC Web site Friedman
31-124-T3 Employee handbook Jones
31-238-TC STAR prototype Garrison
31-241-TC New catalog Jones
35-152-TC STAR pricing Vance
36-272-TC Order system Jacanda

MANAGERS

*ProjectMgr Phone
Friedman 2846
Garrison 2756
Jacanda 2954
Jones 3102
Vance 3022
Avrundning:

1NF:
– Inte massa olika data i samma fält (t.ex. 15, 20, 55 elelr för+efternamn)
– Inte massa olika kolumner med samma data (t.ex. ”Tid1” 15 – ”Tid2” – 43) Tänk vertikalt.

2NF:
Inte repeterande data i samma kolumn (om det inte är en nyckel). (T.ex. samma elev på flera rader.)
Alla kolumner som inte är nycklar ska vara beroende helt av primärnyckeln. (Annars ska dom ju vara i en annan tabell)

3NF:
Inga transitiva beroenden (värden som beror av andra värden än primärnyckeln)

Det var alles om normalisering, som ni läste inledningsvis så finns det ju flera nivåer men det löser ni enkelt med er favorit sökmotor!

Author:Per S.
Kurskod LiU: 725G41

Lämna en kommentar