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 |
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