Normalisering Christer Stuxberg christer.stuxberg@im.uu.se Institutionen för Informatik och Media
Översikt Normalisering Dataredundans och Uppdateringsanomalier Anomalier vid insättning Anomalier vid borttagning Anomalier vid modifiering Första Normalformen (1NF) Andra Normalformen (2NF) Tredje Normalformen (3NF) Exempel
Normalisering Normalisering togs fram av Codd 1972 för att underlätta designen av relationsdatabaser. Normalisering utförs ofta som en serie av tester på en tabell för att avgöra om den uppfyller eller bryter mot reglerna för en given normalform. Det finns ett flertal normalformer. De mest använda är första normalformen (1NF), andra normalformen (2NF) och tredje normalformen (3NF). Alla dessa normalformer bygger på regler om relationer bland kolumnerna i en tabell.
Normalisering Det finns två sätt att utföra normalisering på: den första är en bottom-up databasdesign metodologi medan den andra är en top-down utvecklingsprocess. I bottom-up analyserar vi sambanden mellan attribut för att skapa tabeller som representerar entiteter och deras samband. Vi designar databasen på tabellnivå helt enkelt. Utan att använda oss av ER-diagram. Normalisering används då för att städa upp dåligt strukturerade tabeller.
Normalisering I top-down använder man sig utav ER-modellering för att skapa en modell som representerar entiteter, relationer och attribut. ER-modellen översätts sedan till tabeller. När detta är gjort så normaliserar vi dessa tabeller för att se om tabellerna är korrekt designade.
Dataredundans och Operationsanomalier Ett av huvudmålen är att gruppera kolumner i tabeller för att minimera dataredundans och minska det nödvändiga fillagringsutrymmet för dessa tabeller. Tänk på dessa två tabeller: Staff (staffno, name, position, salary, dcenterno) Primärnyckel: staffno Främmande nyckel: dcenterno DistributionCenter (dcenterno, dadress, dtelno) Primärnyckel: dcenterno
Dataredundans och Operationsanomalier Ett annat sätt att utforma Staff och DistributionCenter tabellerna på är att slå ihop dem till en tabell: StaffDistrubitionCenter (staffno, name, position, salary, dcenterno, dadress, dtelno) Primärnyckel: staffno De verkar vara relativt lika. Men när vi börjar lägga in data i tabellerna så märker vi skillnader.
Staff och DistributionCenter Staff staffno name position salary dcenterno S1500 Tom Daniels Manager 48000 D001 S0003 Sally Adams Assistant 30000 D001 S0010 Mary Martinez Manager 51000 D002 S3250 Robert Chin Assistant 33000 D002 DistributionCenter dcenterno dadress dtelno D001 8 Jefferson Way, Portland, OR 97201 503-555-3618 D002 City Center Plaza, Seattle, WA 98122 206-555-6756
StaffDistributionCenter staffno name position salary dcenterno dadress dtelno S1500 Tom Daniels Manager 48000 D001 8 Jefferson Way, Portland, OR 97201 503-555-3618 S0003 Sally Adams Assistant 30000 D001 8 Jefferson Way, Portland, OR 97201 503-555-3618 S0010 Mary Martinez Manager 51000 D002 City Center Plaza, Seattle, WA 98122 206-555-6756 S3250 Robert Chin Assistant 33000 D002 City Center Plaza, Seattle, WA 98122 206-555-6756 I StaffDistributionCenter finns det överflödig (redundant) data. Uppgifterna för ett distributionscenter upprepas för varje anställd vid det distributionscentret. Tabeller med redundant data kan ha problem som kallas uppdateringsanomalier (insättning, borttagning, modifikation)
Anomalier vid insättning (Insertion) Det finns två huvudsakliga typer av anomalier vid insättning: För att lägga till en ny anställd vid ett visst distributionscenter i StaffDistributionCenter så måste vi även lägga till de korrekta uppgifterna för det distributionscentret. För att lägga till ett nytt distributionscenter utan anställda i StaffDistributionCenter så måste vi lägga till nullvärden i kolumnerna som har med de anställda att göra.
Anomalier vid borttagning (Deletion) Om vi tar bort en post (rad) från StaffDistributionCenter tabellen som representerar den sista anställda vid ett distributionscenter så kommer all information om det distributionscentret att försvinna från databasen. staffno name position salary dcenterno dadress dtelno S1500 Tom Daniels Manager 48000 D001 8 Jefferson Way, Portland, OR 97201 503-555-3618 S0003 Sally Adams Assistant 30000 D001 8 Jefferson Way, Portland, OR 97201 503-555-3618 S0010 Mary Martinez Manager 51000 D002 City Center Plaza, Seattle, WA 98122 206-555-6756 S3250 Robert Chin Assistant 33000 D002 City Center Plaza, Seattle, WA 98122 206-555-6756 S0007 James Farmer Manager 55000 D003 14 8th Avenue, New York, NY 10012 212-371-3000 Om vi tar bort posten med James Farmer så förlorar vi även all information om center D003. Detta händer inte om vi hade haft frikopplade tabeller.
Anomalier vid modifikation Om vi vill ända ett värde i en av kolumnerna för ett specifikt distributionscenter i StaffDistributionCenter tabellen, t.ex. telefonnumret för center D001. Då måste vi ändra det värdet för alla anställda vi det distributionscentret. Annars kommer databasen att bli inkonsekvent.
Normalisering minskar risken av anomalier Tanken med normalisering är att frigöra databasen från tidigare nämnda anomalier. Det säkerställer att när ett nytt värde är introducerat i en relation så har det minimal påverkan på databasen och därför även minimal påverkan på programmet som använder databasen.
Första normalformen (1NF) En tabell i vilken skärningen mellan varje kolumn och rad (cell) innehåller endast ett värde. Det är den enda normalform som är avgörande för att skapa relationsdatabaser, men för att undvika uppdateringsanomalier (update anomalies) så är det rekommenderat att normalisera tom 3NF. En kolumn som innehåller mer än ett värde per rad måste tas bort för att skapa en ny tabell där dessa värden separeras och blir nya primärnycklar.
Exempel dcenterno P dadress dtelno D001 8 Jefferson Way, Portland, OR 97201 503-555-3618, 503-555- 3619, 503-555-3620 D002 City Center Plaza, Seattle, WA 98122 206-555-6756, 206-555- 6757 Det finns flera värden i kolumnen dtelno för båda raderna. Tabellen är alltså inte i 1NF. dadress kolumnen ser ut att ha flera värden men det är endast en adress per rad.
Normalisering av tabellen Vi skapar tabellen DistributionCenter genom att ta bort dtelno: dcenterno P dadress D001 8 Jefferson Way, Portland, OR 97201 D002 City Center Plaza, Seattle, WA 98122 Och sen skapar vi tabellen DistributionCenterTelephone: dcenterno F dtelno P D001 503-555-3618 D001 503-555-3619 D001 503-555-3620 D002 206-555-6756 D002 206-555-6757
Främmande nycklar En främmande nyckel är en kolumn eller flera kolumner som används för att skapa en koppling mellan två tabeller. Tabellen som innehåller den främmande nyckeln kallas för den refererande tabellen och tabellen som innehåller kandidatnyckeln kallas för den refererade tabellen. Då meningen med en främmande nyckel är att identifiera en särskild rad i den refererade tabellen så krävs det generellt att den främmande nyckeln är samma som en kandidatnyckel i någon rad i den refererade tabellen
Andra normalformen (2NF) En tabell som är i 1NF och i vilket värdena i alla kolumner som inte är en del av primärnyckeln bestäms av alla kolumner som är den sammansatta primärnyckeln. Andra normalformen gäller tabeller med sammansatta primärnycklar. Dvs. primärnycklar som är sammansatta av två eller fler kolumner.
Exempel: TempStaffAllocation Primärnyckeln är sammansatt av staffno och dcenterno. staffno P dcenterno P name position hourswk S4555 D002 Ellen Layman Assistant 16 S4555 D004 Ellen Layman Assistant 9 S4612 D002 Dave Sinclair Assistant 14 S4612 D004 Dave Sinclair Assistant 10 Värdena i hourswk bestäms av (staffno, dcenterno) Värdena i name och position bestäms endast av staffno. Vi har alltså ett partiellt beroende och tabellen är inte i 2NF.
Funktionellt Beroende Funktionellt beroende beskriver relationerna mellan kolumnerna i en tabell och indikerar hur kolumnerna är relaterade till varandra. Föreställ er en tabell med kolumnerna a och b där värdet i kolumn a bestämmer värdet i kolumn b (detta skrivs a b) Om vi vet värdet för a så kommer värdet för b alltid att vara samma på alla ställen där a har samma värde. Men även om vi vet värdet för b så kan a ha flera olika värden.
Konsekvenser av Partiellt Beroende Partiellt beroende skapar problem, närmare bestämt redundant data. I vårat fall i kolumnerna name och position vilket kan leda till uppdateringsanomalier. T.ex. för att byta namn på Ellen Layman så måste vi uppdatera två rader i vår tabell. Om vi bara uppdaterar den ena raden så kommer databasen att bli inkonsekvent.
Normalisering av TempStaffAllocation Det partiella beroendet måste bort. Det gör vi genom att ta bort de kolumner som endast bestäms av en del av den primära nyckeln: staffno F^P dcenterno P hourswk S4555 D002 16 S4555 D004 9 S4612 D002 14 S4612 D004 10 Och sen skapar vi en ny fullt funktionellt beroende tabell staffno P name position S4555 Ellen Layman Assistant S4612 Dave Sinclair Assistant
Fullständigt Funktionellt Beroende Om a och b är kolumner i en tabell så är b helt beroende av a om b inte är beroende av en delmängd av a. Om b är beroende av en delmängd av a så kallas det för ett partiellt beroende. Den formella definitionen av 2NF är att tabellen är i 1NF och att alla kolumner som inte är primärnycklar är fullständigt funktionellt beroende av primärnyckeln.
Fullständigt Funktionellt Beroende i TempStaffAllocation tabellen hourswk är fullständigt funktionellt beroende av staffno och dcenterno staffno F^P dcenterno P hourswk S4555 D002 16 S4555 D004 9 S4612 D002 14 S4612 D004 10 Värdena i kolumnen hourswk kan endast bestämmas av värdena från staffno och dcenterno. Vi säger att (staffno, dcenterno) bestämmer hourswk (staffno, dcenterno) hourswk
Tredje Normalformen (3NF) Tabeller i 2NF har mindre redundans är tabeller i 1NF men de kan fortfarande lida av uppdateringsanomalier. En tabell som redan är i 1NF och 2NF och vars värden i alla kolumner som inte är primärnyckel endast kan bestämmas av primärnyckel kolumnen/-erna och inga andra kolumner. De funktionella beroenden som skapar problem kallas transitiva beroenden. En tabell är i 3NF om ingen kolumn är transitivt beroende av primärnyckeln.
Transitivt Beroende Beskriver beroendet mellan kolumnerna a, b och c. Om a bestämmer b (a b) och b bestämmer c (b c) så är c transitivt beroende av a via b (förutsatt att b eller c inte bestämmer a)
Exempel StaffDistributionCenter Transitiva beroenden har orsakat redundant data i kolumnerna dcenterno, dadress och dtel. staffno P name position salary dcenterno dadress dtelno S1500 Tom Daniels Manager 48000 D001 8 Jefferson Way, Portland, OR 97201 503-555-3618 S0003 Sally Adams Assistant 30000 D001 8 Jefferson Way, Portland, OR 97201 503-555-3618 S0010 Mary Martinez Manager 51000 D002 City Center Plaza, Seattle, WA 98122 206-555-6756 S3250 Robert Chin Assistant 33000 D002 City Center Plaza, Seattle, WA 98122 206-555-6756 S0007 James Farmer Manager 55000 D003 14 8th Avenue, New York, NY 10012 212-371-3000 Värdena i dadress och dtel bestäms av dcenterno. Värdena i dcenterno och dtel bestäms av dadress. Värdena i dcenterno och dadress bestäms av dtel.
Normalisering av StaffDistributionCenter Vi måste ta bort de kolumner som kan bestämmas av en kolumn som inte är primärnyckelkolumnen. Tabellen är inte i 3NF så länge vi har kvar dessa beroenden.
Normalisering av StaffDistributionCenter Så vi tar helt enkelt bort de kolumner som kan bestämmas av någon annan kolumn än primärnyckelkolumnen. Vi skapar en ny tabell (DistributionCenter) som innehåller dadress och dtel och vi sätter dcenterno som primärnyckel. dcenterno P dadress dtel D001 8 Jefferson Way, Portland, OR 97201 503-555-3618 D002 City Center Plaza, Seattle, WA 98122 206-555-6756 D003 14 8th Avenue, New York, NY 10012 212-371-3000
Normalisering av StaffDistributionCenter Relationen mellan anställd och distributionscenter bibehålls eftersom en kopia av dcenterno kolumnen i StaffDistributionCenter tabellen blir en främmande nyckel: staffno P name position salary dcenterno F S1500 Tom Daniels Manager 48000 D001 S0003 Sally Adams Assistant 30000 D001 S0010 Mary Martinez Manager 51000 D002 S3250 Robert Chin Assistant 33000 D002 S0007 James Farmer Manager 55000 D003
Normalisering av StaffDistributionCenter Den nya tabellen DistributionCenter är även den i 3NF eftersom alla kolumner som inte är primärnycklar kan bestämmas med primärnyckeln. Vi kunde ha lämnat en kopia av någon av de andra kolumnerna och använt den som främmande nyckel eftersom de har samma egenskaper som dcenterno. De flesta 3NF tabeller är fria från uppdateringsanomalier. Det finns dock vissa som fortfarande är påverkade och som då behöver normaliseras enligt 4NF eller 5NF.
Fler Exempel Ett exempel på en 2NF tabell som inte möter kraven för 3NF är tabellen Top5ActionMovies: movietitle year actor actordob The Dark Knight 2008 Christian Bale 30-Jan-1974 Inception 2010 Leonardo DiCaprio 11-Nov-1974 Star Wars: Episode V 1980 Mark Hamill 25-Sep-1951 The Matrix 1999 Keanu Reeves 2-Sep-1964 Star Wars: Episode IV 1977 Mark Hamill 25-Sep-1951 Varje rad berättar vem som hade huvudrollen i en viss film från ett visst år.
Eftersom flera filmer kan ha samma namn så behöver vi sätta både movietitle och year som primärnyckel. movietitle P year P actor actordob The Dark Knight 2008 Christian Bale 30-Jan-1974 Inception 2010 Leonardo DiCaprio 11-Nov-1974 Star Wars: Episode V 1980 Mark Hamill 25-Sep-1951 The Matrix 1999 Keanu Reeves 2-Sep-1964 Star Wars: Episode IV 1977 Mark Hamill 25-Sep-1951
Anledningen till att den inte är i 3NF är att actordob är transitivt beroende av kandidatnyckeln (movietitle, year) via actor. Eftersom actordob är funktionellt beroende av actor så är tabellen sårbar för logisk inkonsekvens. Det finns inget som hindrar att samma skådespelare visas med olika födelsedatum på olika poster.
Lösning För att uppfylla 3NF så måste vi dela tabellen i två: movietitle P year P actor F The Dark Knight 2008 Christian Bale Inception 2010 Leonardo DiCaprio Star Wars: Episode V 1980 Mark Hamill The Matrix 1999 Keanu Reeves Star Wars: Episode IV 1977 Mark Hamill actor P Christian Bale Leonardo DiCaprio Mark Hamill Keanu Reeves actordob 30-Jan-1974 11-Nov-1974 25-Sep-1951 2-Sep-1964