Normaliseren

Normaliseren van relationele tabellen, hoe zit het ook al weer?

Anomalieën

Waarom willen we eigenlijk normaliseren? Als je wilt voorkomen dat er fouten kunnen onstaan bij het updaten van gegevens in een database, zul je ervoor moeten zorgen dat je tabellen zodanig zijn ingericht dat er geen update-anomalieën kunnen ontstaan.

Er zijn drie soorten anomalieën: invoeg-, verwijder- en modificatie-anomalieën.

Voorbeeld:

Invoeganomalie

Stel dat we in tabel 1 een nieuwe conventie zouden willen invoegen, bijvoorbeeld Spellenspektakel, datum 14-11-2008. Het probleem is dat we Spellenspektakel pas aan bovenstaande tabel kunnen toevoegen, wanneer iemand zich inschrijft als deelnemer voor het Spellenspektakel. Dit noem je een invoeganomalie.

Verwijderanomalie

Stel dat Freek besluit om toch niet naar de Star Trek Convention te gaan, zodat deze rij uit de tabel wordt verwijderd. Het probleem is nu dat we de informatie over de datum van de Star Trek Convention zijn kwijtgeraakt. Dit noem je een verwijderanomalie.

Modificatie-anomalie

Stel dat de datum van Gen Con verandert naar 30-08-2008. In dit geval moeten er twee rijen worden ge-update. Het is mogelijk om er per ongeluk eentje te vergeten en dat zou een inconsistentie in de tabel opleveren. Dit noem je een Modificatie-anomalie.

Eerste Normaalvorm (1NF)

De eerste normaalvorm gaat over de vorm van de gegevens.

Elke tabel met gegevens die voldoet aan de volgende regels is in 1NF.

Een attribuut bestaat uit een attribuutnaam (=kolomnaam) en een attribuutwaarde (=kolomveld).
Een tuple komt overeen met een rij in de tabel.
Elke tuple komt maar één keer voor (= uniek).
Elke tuple heeft hetzelfde aantal attributen.
Een tuple mag geen herhalende attributen van dezelfde soort hebben.

Voorbeeld:

Tabel 2a is nog niet in 1NF.

Tabel 2b is in 1NF.

Tweede normaalvorm (2NF)

Een tabel is in 2NF als aan de volgende voorwaarden is voldaan.

De tabel is in 1NF.
Alle attributen die niet in de sleutel (primary key) zijn opgenomen, zijn afhankelijk van de gehele sleutel, en niet slechts van een gedeelte van de sleutel.

“The whole key”

Voorbeeld:

Tabel 3a is in 1NF, maar nog niet in 2NF. De sleutel bestaat uit {Dier, Kleur}, maar de Soort is alleen afhankelijk van Dier, en dit is slechts een gedeelte van de sleutel. (Hetzelfde zou gelden voor Kleur als je de sleutel {Dier, Soort} zou maken).

Oplossing naar 2NF:

Tabel 3b en 3c zijn in 2NF.

Derde normaalvorm (3NF)

Elke tabel die voldoet aan de volgende regels is in 3NF.

De tabel is in 2NF.
Alle niet-sleutel attributen zijn alleen afhankelijk van de sleutel, niet-sleutel attributen hebben geen relatie met andere niet-sleutel attributen.

“And nothing but the key”

Voorbeeld:

Tabel 4a is in 2NF, maar nog niet in 3NF. Kamernummer Docent is niet alleen afhankelijk van de sleutel {Vak, Jaar}, maar ook van de Docent.

Oplossing naar 3NF:

Tabel 4b en 4c zijn in 3NF.

Boyce-Codd normaalvorm (BCNF)

BCNF is een verdere verfijning van 3NF. Vaak is een tabel in 3NF ook al in BCNF.

Een tabel is in BCNF als aan de volgende voorwaarden wordt voldaan.

De tabel is in 3NF.
Alle determinanten zijn kandidaat-sleutels.

Deze is iets ingewikkelder. Wat is een determinant precies?

Determinant

Een determinant is een attribuut (of een set van attributen) dat een ander attribuut functioneel determineert (een veld determineert de waarde van een ander veld).
Dit is het beste uit te leggen met een voorbeeld.
Denk aan een persoons Naam en haar BurgerServiceNummer (BSN). Een gegeven BSN heeft precies één corresponderende naam. BSN is daarom een determinant voor Naam, ofwel Naam is functioneel afhankelijk van BSN. Echter, een gegeven Naam, bijvoorbeeld J. Smit, kan worden geassocieerd met meerdere BSNs, dus BSN is niet functioneel afhankelijk van Naam, ofwel Naam is geen determinant van BSN.

Dus als in een 3NF tabel alle kandidaat-sleutels een functionele afhankelijkheid hebben, oftewel determinant zijn, dan is een tabel ook in BCNF.
Een tabel met enkel sleutels is automatisch BCNF.

Een andere manier om BCNF uit te leggen, is door aan te geven wanneer een tabel in 3NF niet voldoet aan BCNF.
Als een tabel in 3NF de volgende drie eigenschappen alledrie heeft, dan is de tabel niet in BCNF.

Kandidaat-sleutels bestaan uit meerdere attributen.
Er zijn meerdere kandidaat-sleutels.
De kandidaat-sleutels zijn niet disjunct, ofwel de kandidaat-sleutels hebben gezamenlijke attributen.

Anders gezegd, een tabel in 3NF is niet in BCNF als er meerdere kandidaat-sleutels zijn, en de kandidaat-sleutels zijn samengesteld en overlappend.

Voorbeeld:

Tabel 5a is in 3NF, maar nog niet in BCNF.
De tabel voldoet aan het volgende model:
Elke cursus kan meerdere studenten hebben, elke student kan meerdere cursussen volgen, elke cursus kan meerdere studentassistenten hebben, elke studentassistent heeft precies één cursus en voor elke cursus heeft elke student precies één studentassistent.

Om elke tuple uniek te identificeren, kun je {Cursusnummer, Student} als sleutel nemen. Dit zorgt ervoor dat de tabel in 3NF is, omdat deze sleutel de determinant is van Studentassistent. De tabel heeft nog een andere kandidaat-sleutel, {Student, Studentassistent}. Je ziet dat er meerdere, overlappende, samengestelde kandidaat-sleutels zijn (Student zit in beiden). En dit is precies de reden dat de tabel niet in BCNF is.

Tabel 5b, 5c en 5d zijn in BCNF.

Verder normaliseren

Je kunt relationele tabellen nog verder normaliseren. Na de BCNF komen nog o.a. de vierde normaalvorm (4NF), vijfde normaalvorm (5NF), Domein/Key NF en de zesde normaalvorm (6NF). Over het algemeen is het in de praktijk meestal voldoende om te normaliseren tot en met BCNF.

Bronnen:

http://oldweb.uwp.edu/academic/mis/Baldwin/normal.htm
http://forums.hostrocket.com/archive/index.php/t-15045.html
http://en.wikipedia.org/
http://www.bkent.net/Doc/simple5.htm