programmera.net -> db -> normal     för utskrift      info@programmera.net

Normalisering

1. Vad är normalisering?
2. Första gradens normalform
3. Andra gradens normalform
4. Tredje gradens normalform

1. Vad är normalisering?

Normalisering är olika regler för hur man kan strukturera datat i sina tabeller. Vi normaliserar för att det ska bli så enkelt som möjligt att senare uppdatera data och datamodell utan att det blir fel. Normalisering är framför allt viktigt i OLTP-system, där data ofta uppdateras.

2. Första gradens normalform

Vi definierar första gradens normalform (1NF):

  • En tabell är i första gradens normalform om tabellen har en primär nyckel och inte har flera kolumner av samma typ.
Definitionen ovan innebär att vi inte tillåter flera kolumner innehållande samma typ av data i en tabell. Ett exempel på en tabell som innehåller flera kolumner av samma typ är OWNER nedan:



Här är kolumnerna CAR1, CAR2 och CAR3 egentligen av samma typ. För att normalisera denna tabell bryter vi ut de dubblerade kolumnerna i en egen tabell CAR enligt bilden:



Nu innehåller ingen av tabellerna flera kolumner av samma typ, och vi måste nu fundera över vilka kolumner som kan vara primär nyckel för tabellerna:
  • CAR: Här fungerar registreringsnummret bra som primär nyckel för tabellen CAR, eftersom registreringsnummret är unikt för bilen.
  • OWNER: Det är tveksamt om förnamn är en bra primär nyckel för tabellen OWNER, eftersom det är mycket troligt att två ägare kan ha samma namn. Därför lägger vi till en ny kolumn OWNER_PK med unika heltal som får vara tabellens primära nyckel.
Se bilden:



Tabellerna är nu normaliserade av första graden.

3. Andra gradens normalform

Vi definierar andra gradens normalform (2NF):

  • En tabell är i andra gradens normalform om tabellen är i första gradens normalform och dess kolumner inte innehåller dubblerade värden som kan ses som entiteter i systemet.
Strategin för att uppnå andra gradens normalform är även här att bryta ut de berörda kolumnerna, och använda nycklar för referens mellan tabellerna. Om du till exempel har en tabell CAR som innehåller kolumner och data enligt bilden:



Kolumnen CAR_MODEL innehåller redundant information. För att normalisera till andra graden måste vi bryta ut den redundanta informationen en egnen tabell, se bild nedan:



Den nya tabellen har fått egna primära nycklar, och vi använder dessa nycklar för att referera till den nya tabellen. Varför vill vi inte ha redundant information i kolumnerna?
  • Färre SQL-fel: Om informationen är redundant text finns risken att någon matar in felaktiga värden utan att detta upptäcks. Om detta sker går det inte att gruppera objekt baserat på den aktuella kolumnen. I exemplet ovan kanske någon skriver "Sab 9-3" när de egentligen menar "Saab 9-3". Trots att "Sab 9-3" egentligen är samma modell som "Saab 9-3" kommer det i SQL-frågorna tolkas som en ny modell.
  • Mindre lagringsutrymme: Genom att bryta ut redundant information i en egen tabell sparar vi diskutrymme.
  • Flexibilitet: Det blir lättare att bygga vidare på den nya tabellen om vi senare vill lägga till nya kolumner. I exemplet ovan kanske vi kommer på att vi även vill lagra bilens vikt. Nu passar det bra att lägga till en kolumn WEIGHT i den nya tabellen MODEL. Bilens vikt knyts nu till bilmodellen istället för till den enskilda bilen, vilket är mer korrekt.
Ska alla kolumner som har dubblerade data brytas ut för att tabellen ska uppnå 2NF?
  • Nej, endast de kolumner som kan ses som entiteter i systemet måste brytas ut för att tabellen ska bli 2NF. Vad som kan ses som en entitet är olika från projekt till projekt. Ofta är det intriktningen på organisationens verksamhet som bestämmer vilka parametrar som ska ses som entiteter. Ställ fråga "Vill vi någonsin välja ut alla objekt som har X i denna kolumn?" Om svaret blir nej är det kanske ingen idé att bryta ut kolumnen.
Ett exempel på kolumner som sällan ses som entiteter i ett system är förnamn och efternamn. Trots att en persons förnamn och efternamn ofta uppkommer flera gånger i deras respektive kolumner, speciellt om tabellen är stor, är det oftast ingen idé att bryta ut dessa kolumner till egna tabeller. Hur kan det vara så?
  • Vi får inga SQL-fel: Ett förnamn/efternamn ses oftast bara som en attribut till personen och kan inte sägas vara en egen entitet. Om någon som heter "Johan" fyller i sitt namn som "Johanh" så genrerar detta sällan fel urval i SQL-satserna. Detta eftersom de flesta system inte grupperar personer baserat på namn. Det spelar alltså ingen roll att "Johanh" inte tillhör gruppen av alla personer vid namn "Johan".
  • Vi får ingen ökad flexibilitet: Om vi bryter ut t.ex. förnamn till en egen tabell är det i de flesta projekt ganska otroligt att vi vill hänga på flera kolumner på den tabellen senare. Oftast är ett förnamn inte kritiskt för en organisation, man väljer helt enkelt att expandera andra parametrar som är mer relevanta för organisationens verksamhet.

4. Tredje gradens normalform

Tredje gradens normalform (3NF):

  • En tabell är i tredje gradens normalform om den är i andra gradens normalform och bara innehåller kolumner som beror direkt på primärnyckeln.
Vi använder ett exempel för att belysa denna regel:



Denna tabell är i 1NF (eftersom det inte finns några kolumner av samma typ), och 2NF (eftersom inga kolumner innehåller dubblerade data som kan ses som entiteter). Nu behöver vi bara fråga oss om alla kolumner beror direkt av primärnyckeln:
  • CUST_PK: Detta är bara en referensnyckel till kunden som har beställt enheterna; måste anges för varje beställning.
  • UNITS: Antal enheter som har beställts; måste anges för varje beställning.
  • UNIT_PRICE: Det pris per enhet som kund och säljare har förhandlat fram; måste anges för varje beställning.
  • TOTAL_PRICE: Det totala priset för beställningen; detta behöver INTE anges eftersom totalsumman kan beräknas utifrån UNITS och UNIT_PRICE.
För att vi ska nå 3NF måste alltså kolumnen TOTAL_PRICE tas bort:



Varför vill vi ha tabeller i 3NF?
  • Tabeller i 3NF är lättare att underhålla.