Normaliseren

 
26 mei 2008

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


Werken met ?
Kijk dan bij onze mogelijkheden voor starters en/of ervaren IT'ers.


Categorieën: Architectuur, Development, Overige talen en platformen

Tags: ,


Reacties (6)

  • Ik heb ooit ook normaliseren mogen doceren aan trainees maar miste met name de mooie start van dit blog met de anomalieën.
    Mooi werk met treffende en prettig korte voorbeelden!

    Geplaatst op 30 augustus 2013 om 13:52 Permalink

  • Peter schreef:

    Mooi stukje!

    Geplaatst op 16 december 2011 om 14:30 Permalink

  • Jasper Floor schreef:

    Er is natuurlijk ook een reden om niet te normaliseren. Normaliseren is goed voor data integriteit maar niet zo goed voor performance. In de regel zeg ik dat je wel moet normaliseren.
    Niet genormaliseerde data is handig voor afgeleide data. Zie data warehousing voor een reden om niet te normaliseren

    Geplaatst op 09 januari 2010 om 23:20 Permalink

  • Dick schreef:

    Karin,

    Helder artikel, maar in het voorbeeld m.b.t. BCNF moet denk ik de zinsnede “elke studentassistent heeft precies één cursus” worden geschrapt. Studentassistent Ellen heeft blijkens tabel 5c twee cursussen.

    Geplaatst op 14 oktober 2009 om 20:00 Permalink

  • Just Boerlage schreef:

    Zeer helder geschreven. Wanneer komt je eerste boek uit?

    Geplaatst op 22 juli 2008 om 14:01 Permalink

  • Interessant! Goed bezig Karin! Laatst was ik hier ook mee bezig, maar ik had de theorie niet direct bij de hand, nu wel weer :-)

    Geplaatst op 27 mei 2008 om 9:51 Permalink