Het Normaliseren van tabellen / Boyce-Codd normaalvorm
Wat is een genormaliseerde tabel?
Een genormaliseerde tabel is een tabel, waarvan alle niet-sleutel attribuuttypen functioneel afhankelijk zijn van alleen de volledige sleutel en daarnaast niet afhankelijk zijn van niet-sleutel attribuuttypen.
Aan een tabellenmodel stellen we de eis dat het in de Boyce-Codd normaalvorm staat. In het navolgende zullen we dit nader toelichten. We behandelen de normaalvormen die in de Boyce-Codd normaalvorm culmineren. Er worden in de literatuur nog wel verdergaande normaalvormen onderkend. Deze achten wij niet relevant voor het tabellenmodel en laten wij derhalve onbehandeld.
Eerst definiëren we het begrip functionele afhankelijkheid. Hieronder wordt verstaan: als op grond van de betekenisrelatie tussen attribuuttypen geconcludeerd kan worden dat de waarde van een groep attribuuttypen de waarde van attribuuttype X uniek bepaalt, dan heet X functioneel afhankelijk van deze groep attribuuttypen. Stel dat de groep attribuuttypen de primaire sleutel van een tabel vormen, dan betekent dit, dat per primaire sleutel slechts één waarde van X voor kan komen. We vinden bijvoorbeeld per medewerkernummer (= primaire sleutel) slechts één naam van de medewerker. Daarmee is de naam functioneel afhankelijk van de sleutel.
Het attribuuttype, of de groep attribuuttypen, waarvan een attribuuttype X functioneel afhankelijk is wordt ook wel de determinant voor X genoemd.
1e normaalvorm
In de eerste normaalvorm is elk attribuut functioneel afhankelijk van de primaire sleutel van de tabel waarin deze voorkomt.
Als bijvoorbeeld een medewerker op meer afdelingen kan werken en we zouden de afdelingscode opnemen in de medewerkertabel, staat die tabel niet in de eerste normaalvorm. Per medewerkernummer kunnen immers meer afdelingen voorkomen. Anders gezegd: in een tabel in de eerste normaalvorm komen geen 'repeating groups' voor.
2e normaalvorm
Een tabel staat in de tweede normaalvorm indien deze in de eerste normaalvorm staat en bovendien alleen attributen bevat, die alle afhankelijk zijn van de gehele primaire sleutel.
Kijk bijvoorbeeld naar de volgende tabel:
MEDEWERKER_IN_AFDELING (medewerkernummer, afdelingscode, percentage, bonus, datum ingang, datum einde)
De rijen van de tabel worden geïdentificeerd door medewerkernummer en afdelingscode. In de structuur van de tabel ligt besloten, dat een medewerker op meer afdelingen kan werken en dat op een afdeling meer medewerkers kunnen werken. Stel dat een medewerker slechts één bonus kan ontvangen (d.w.z. niet per afdeling waar deze werkt), dan is de bonus niet functioneel afhankelijk van de gehele sleutel, maar van slechts een deel daarvan (n.l. alleen van het medewerkernummer). In een dergelijke situatie zeggen we, dat de tabel niet voldoet aan de tweede normaalvorm.
3e normaalvorm
Een tabel staat in de derde normaalvorm, indien deze in de twee normaalvorm staat en bovendien geen attribuuttypen bevat die afhankelijk zijn van attributen die geen sleutel zijn.
Kijk bijvoorbeeld naar de volgende tabel:
MEDEWERKER (medewerkernummer, naam, voornaam, afdelingscode, afdelingsnaam)
De tabel wordt geïdentificeerd door het medewerkernummer (onderstreept) en staat in de tweede normaalvorm, dat wil zeggen per medewerkernummer komen we slechts één naam, voornaam, afdelingscode en afdelingsnaam tegen en bovendien zijn alle attributen functioneel afhankelijk van de gehele sleutel. Alleen is de afdelingsnaam tevens afhankelijk van het niet-sleutel attribuut afdelingscode. Er bestaat dus een functionele afhankelijkheid tussen een attribuuttype van de tabel en een ander attribuuttype van dezelfde tabel (niet zijnde de sleutel). Afdelingsnaam is afhankelijk van de afdelingscode en afdelingscode is afhankelijk van medewerkernummer. Ofwel afdelingsnaam is transitief afhankelijk van de sleutel (medewerkernummer). De tabel voldoet derhalve niet aan de derde normaalvorm.
Boyce-Codd normaalvorm
Een model voldoet aan de Boyce-Codd-normaalvorm als elk attribuuttype of combinatie van attribuuttypen waarvan een ander attribuuttype functioneel afhankelijk is een kandidaat-sleutel is. Anders gezegd: een tabel staat in de Boyce-Codd normaalvorm indien iedere determinant een kandidaat-sleutel is.
Als we de hiervoor genoemde drie normalisatiestappen met gezond verstand uitvoeren, dan zal het slechts zelden voorkomen dat tabellen daarna niet aan de Boyce-Codd normaalvorm voldoen. In onderstaande geven we er een voorbeeld van het tegendeel:
Neem de tabel:
ADRES (straatnaam, huisnummer, postcode)
Merk op dat deze tabel twee kandidaat sleutels heeft:
- postcode + huisnummer
- straatnaam + huisnummer
De tabel staat in de derde normaalvorm, maar niet in de Boyce-Codd normaalvorm, omdat straatnaam functioneel afhankelijk is van postcode en postcode geen kandidaat-sleutel is. We lossen dat op door de relatie postcode - straatnaam af te splitsen:
ADRES (postcode, huisnummer)
POSTCODE (postcode, straatnaam)
N.B. Overal waar op deze pagina sleutel staat moet dit worden gelezen als een sleutel. Het maakt daarbij niet uit welke kandidaat-sleutel gekozen wordt als primaire sleutel. Bijvoorbeeld de tabel (medewerkernummer, sofi-nummer, naam) staat in de derde normaalvorm. Weliswaar is naam afhankelijk van het attribuuttype sofi-nummer dat geen onderdeel uitmaakt van de primaire sleutel, maar zowel medewerkernummer als sofi-nummer zijn een kandidaat sleutel van de tabel.
Verwerkingsanomalieën
Het normaliseren van tabellen wordt uitgevoerd om onregelmatigheden bij het beheer van de gegevens (ook wel aangeduid met de term verwerkingsanomalieën) te voorkomen. Het gebruik van de gegevens wordt er echter soms door bemoeilijkt (gegevens zijn vaak het eenvoudigst te gebruiken indien ze alle in één tabel zouden staan). Het opkrikken van de performance hoort echter niet thuis in het tabellenmodel, maar in het databasemodel. Elk hulpmiddel biedt weer andere mogelijkheden om de performance te verbeteren met het behoud van de integriteit van verwerking. Het is niet verstandig in het logische gegevensmodel op een mogelijke oplossing vooruit te lopen.
Lees verder: Tijdsaspecten en historie