Fouten in Relationele Databanken

leestijd: 9 minuten

redundantie herhalende groep niet-gestandaardiseerde waarde samengestelde data enkelvoudige data cel record field

FOUTEN IN RELATIONELE DATABANKEN

De structuur van een relationele database bepaalt welke tabellen een database heeft, waarom juist die tabellen, en wat die tabellen met elkaar te maken hebben.

Hoe het niet moet

In dit onderdeel wordt een databasestructuur besproken waarbij alle gegevens in één tabel worden geplaatst. Dit is géén goede databasestructuur.

Waarom deze structuur niet goed is wordt hier uitgelegd. Daarbij komen drie belangrijke begrippen aan de orde: redundantie, herhalende groepen en niet-gestandaardiseerde waardes.

In dit hoofdstuk wordt getoond hoe je deze fouten herkend. In een volgend hoofdstuk leer je hoe je deze fouten oplost en voorkomt.

Kenmerken van recepten

Hieronder staat één van de drie voorbeeld recepten.

gerecht Coupe Kiwano
bereidingstijd (minuten) 20
bereidingswijze Schil de kiwano, snijd hem in stukjes, voeg de tequila toe en laat dit mengsel 15 minuten staan. Neem per persoon 3 bolletjes ijs en voeg hier de kiwano met tequila aan toe. Serveer met gezoete, stijfgeslagen slagroom.
ingrediënten product hoeveelheid per persoon eenheid energie per eenheid (kcal)
ijs 0.15 liter 1600
kiwano 0.5 stuks 40
slagroom 0.3 deciliter 336
suiker 10 gram 4
tequila 1 eetlepel 30

Per recept zijn vier kenmerken opgenomen:

De eerste 3 kenmerken (naam, bereidingstijd en bereidingswijze) zijn allemaal enkelvoudige data: ze bevatten allemaal slechts één waarde. Enkelvoudige data bestaat meestal uit tekst (“Coupe Kiwano”) of een getalwaarde (“403”).

Het 4de kenmerk, de ingrediënten, bevat samengestelde data: hierin bevindt zich niet één waarde, maar een hele subtabel van waardes. Samengestelde data bestaat dus uit meerdere waardes (een lijst, een subtabel, …). Elke rij van deze subtabel bevat de gegevens van één ingrediënt:

Eén tabel met subtabellen

Alle recepten en hun ingredienten kunnen we samenbrengen in één grote tabel genaamd Recept. Om de tabel wat kleiner en leesbaarder te maken zijn sommige namen van kolommen veranderd (“hoeveelheid per persoon” wordt “hoeveelheid PP”).

naam energiePP bereidingstijd bereidingswijze ingrediënten
product hoeveelheidPP eenheid energiePE
Coupe Kiwano 431 20 Schil ijs 0.15 liter 1600
kiwano 0.5 stuks 40
slagroom 0.3 deciliter 336
suiker 10 gram 4
tequila 1 eetlepel 30
Glace Terrace 403 5 Neem ijs 0.2 liter 1600
aardbeien 50 gram 0.25
pernod 2 eetlepel 35
peper
Mango Plus Plus 131 8 Snij mango 0.5 stuks 80
aardbeien 50 gram 0.25
zure room 0.4 deciliter 195

Elke rij stelt in deze tabel één “ding” voor (een recept). Een rij wordt daarom een record genoemd: het houdt alle gegevens bij (engels: ‘to record’) van één “ding” in de tabel.

Elke kolom stelt in deze tabel één “eigenschap van een ding” voor (onderdeel van een recept). Een kolom wordt een field (veld) genoemd. Elk veld heeft een kolomnaam.

Belangrijk! De volgorde waarin rijen en kolommen staan maakt geen verschil voor de tabel.

De kolom genaamd “ingrediënten” is één kolom. Dit is een samengestelde kolom. Met andere woorden, deze kolom bestaat uit meerdere subkolommen.

De plaats waar een rij en een kolom kruisen heet een cel. Dit is de plaats waar een waarde wordt ingevuld. Op die manier weet je dat “20” de waarde is van “Coupe Kiwano” voor het veld “bereidingstijd”.

De cellen in de kolom “ingrediënten” bevatten een samengestelde waarde: elke cel bevat een subtabel met daarin weer 4 aparte kolommen. Er zijn 3 belangrijke problemen met deze tabel:

  1. Redundantie: bepaalde informatie wordt meer dan één keer opgeslagen.
  2. Herhalende groepen: een tabelstructuur met subtabellen maakt het databasebeheer erg ingewikkeld.
  3. Structuur problemen: Ingrediënten worden alléén als onderdeel van een recept opgeslagen, terwijl ingrediënten eigenlijk ook een ‘soort ding’ zijn dat losstaat van een recept.

Redundantie

Op dit moment wordt op twee verschillende plaatsen vermeld dat ijs gemeten wordt in ‘liter’. Dit is vaker dan nodig is: producten in Désiré’s Dessertenboek worden altijd in dezelfde eenheid gemeten (IJs bijvoorbeeld in liter en aardbeien in gram).

Wanneer er dus bij Coupe Kiwano staat dat ijs in liter wordt gemeten, weet je zonder verder te kijken dat dit ook voor Glace Terrace geldt, en omgekeerd.

Dit heet redundantie. Redundant betekent overtollig: je kan een gegeven ergens anders ook al terugvinden in de databank. Ook de subkolom energiePE heeft redundante gegevens, want voor ijs wordt twee keer vermeld wat de energiewaarde is.

Redundantie is slecht om twee redenen:

  1. Extra opslagruimte: je slaat sommige gegevens meerdere keren opnieuw op.
  2. Gevaar voor inconsistente data: Inconsistente data zijn waardes waarvan de betekenissen niet overeen komen. Redundantie brengt vaak het gevaar van inconsistentie met zich mee.

bijvoorbeeld: bij Coupe Kiwano staat dat ijs 1600 kilocalorie per maateenheid bevat, en bij Glace Terrace dat het 1450 is. Eén van de twee moet dan fout zijn.

Redundantie kan nooit volledig weggewerkt worden, maar het doel is om redundantie tot een minimum te beperken.

Herhalende groepen

Als een waarde uit meerdere kolommen, meerdere rijen of een combinatie van de twee bestaat, is dit een herhalende groep. Een goede databank kan data gemakkelijk toevoegen, opvragen of aanpassen. Herhalende groepen zorgen ervoor dat deze drie bewerkingen veel moeilijker worden. Dit maakt het beheren van de databank veel moeilijker.

Herhalend

Met ‘herhalend’ wordt bedoeld dat hetzelfde soort “ding” meerdere keren voorkomt in dezelfde cel.

Bv.:

ijs
kiwano
slagroom
suiker
tequila

Groep

Met ‘groep’ wordt bedoeld dat één “ding” uit meerdere waardes bestaat in dezelfde cel.

Bv.:

ijs 0.15 liter 1600

Toevoegen van Data

Wanneer een nieuw recept wordt toegevoegd, moet het invoegen van een nieuwe record gebeuren op twee verschillende niveau’s:

  1. In de subtabel met ingrediënten, waar elk ingrediënt met z’n eigenschappen wordt ingevoerd.
  2. In de hoofdtabel, waar de rest van de gegevens van een recept wordt ingevoerd.

Aanpassen

Wanneer een eigenschap van een ingrediënt wordt aangepast, moet elk recept worden nagekeken, om zo op elke plaats waar dat ingrediënt aanwezig is het recept aan te passen.

Bv.: als het ingrediënt ‘ijs’ vanaf nu wordt uitgedrukt in ‘kilogram’ in plaats van ‘liter’, moet in elk recept worden nagekeken of er ‘ijs’ gebruikt wordt, en zo ja, moet daar ‘liter’ worden veranderd in ‘kilogram’.

Opvragen

Om te weten welke recepten gebruik maken van het ingrediënt ‘ijs’ moet, net zoals bij het aanpassen, elk recept z’n ingrediënten-subtabel worden nagekeken of daar ‘ijs’ in voorkomt.

Niet-gestandaardiseerde waardes

Een laatste probleem dat ook vaak voorkomt zijn verschillende waardes die dezelfde betekenis hebben. Een goed voorbeeld hiervan zijn de ingrediënten ‘slagroom’ en ‘zure room’: Slagroom wordt gemeten in ‘deciliter’, zure room wordt gemeten in ‘dl’. Allebei de ingrediënten worden gemeten in dezelfde meeteenheid (namelijk deciliter), maar ze gebruiken een verschillende notatie.

Ook dit kan voor problemen zorgen, zeker bij het opvragen van gegevens. Als je alle ingrediënten wilt zoeken die de maateenheid ‘deciliter’ gebruiken, moet je dus zowel zoeken naar ‘deciliter’ als naar ‘dl’.

Niet-gestandaardiseerde waardes zijn waardes die dezelfde betekenis hebben, maar toch verschillend zijn in de databank. Bijvoorbeeld: ‘deciliter’ en ‘dl’.

Tabellen omkeren

Tot nu toe hebben we elk recept als één “ding” gezien in de tabel, waarbij elk recept meerdere ingrediënten bevat. Daardoor werd de kolom ‘ingrediënten’ een herhalende groep.

Je zou ook omgekeerd kunnen denken: bekijk een ingrediënt als één “ding”, waarbij elk ingrediënt meerdere recepten bevat. Het gevolg hiervan is dat de kolom ‘recepten’ een herhalende groep wordt.

De tabel heet dan ‘Ingrediënt’, met één rij per ingrediënt. Deze tabel heeft vervolgens vier kolommen, waarvan er één een samengestelde kolom is (‘recepten’).

Beide voorbeelden hebben gelijkaardige problemen met redundantie en herhalende groepen. Het is bovendien niet duidelijk welk voorbeeld ‘beter’ is dan de andere: beschouw je de recepten als “ding”, of de ingrediënten? Je kan willekeurig kiezen welke van de twee je het liefst gebruikt, maar je komt altijd dezelfde problemen en fouten tegen.

Deze willekeur staat dan ook haaks op een goede structuur: De kracht van een goede structuur ligt in het gelijkwaardig behandelen van informatie, ongeacht wat de gebruiker later met die informatie doet of hoe de gebruiker die informatie bekijkt.

naam eenheid energiePE gerechten
gerecht bereidingstijd bereidingswijze hoeveelheidPP
ijs liter 1600 Coupe Kiwano 20 Schil ... 0.15
Glace Terrace 5 Neem ... 0.2
kiwano stuks 40 Coupe Kiwano 20 Schil ... 0.5
slagroom deciliter 336 Coupe Kiwano 20 Schil ... 0.3
suiker gram 4 Coupe Kiwano 20 Schil ... 10
tequila eetlepel 30 Coupe Kiwano 20 Schil ... 1
aardbeien gram 0.25 Glace Terrace 5 Neem ... 50
Mango Plus Plus 8 Snijd ... 50
pernod eetlepel 35 Glace Terrace 5 Neem ... 2
peper Glace Terrace 5 Neem ...
mango stuks 80 Mango Plus Plus 8 Snijd ... 0.5
zure room deciliter 195 Mango Plus Plus 8 Snijd ... 0.4

Belangrijk! De kolom ‘hoeveelheid PP’ bevindt zich in beide voorbeelden in de subtabel. Dit komt doordat de hoeveelheid per persoon zowel afhangt van het recept als van het ingrediënt.

Bv.: