Databaser: Kageopskrifter

Databaser er modeller af virkeligheden

Databaser er modeller af virkeligheden. Facebook har en database – hvad mon der er i den? Jo, der er selvfølgelig stamoplysninger om brugere, oplysninger om ting de har postet, poster de har liket, oplysninger om hvilke personer de er venner med osv, osv.

Banken har en database. Hvad mon der er i den? Og skolens database? Fodboldklubbens?

Databaser er helt grundlæggende for informatikken. Ved hjælp af databaser kan man sætte simple og avancerede systemer op, som strukturerer virkelige forhold. Mellem mennesker, varer, tv-programmer, kemiske reaktioner, hvad som helst(!).

I lærebogen kan du læse, at en database skal være:

  • Pladseffektiv. Designet så oplysninger kun gemmes ét sted, og det er tydeligt hvilken datatype tingene har. Skal du for eksempel gemme en persons alder, er der ikke grund til at gemme et max. trecifret tal, vel?
  • Fleksibel. Databasen er let at bruge, vedligeholde og udvide.
    • Her kommer alt det her med entiteter og relationer ind i billedet. Det er ikke sikkert man har brug for en særlig avanceret database – så skal den heller ikke være det.
    • Forestil dig at du vil lave en database med kontaktinformationer til forældre i en skoleklasse. Her er der kun brug for en helt enkel tabel med navn, adresse, tlf osv..
    • Forestil dig så at du vil bygge Facebook med en enkelt tabel i et enkelt regneark. Det ville måske være mest oplagt at kalde tabellen “Personer”. Men hvad så med poster? Nu ville du være nødt til at lave en ny kolonne, hver gang nogen postede et indlæg: Navn, efternavn, Post 1, post 2, post en milliard.. Det er ikke fleksibelt. Det ville være meget smartere at lave to tabeller: en der hedder ‘personer’ og en der hedder ‘poster’. Og så lave en relation i mellem de to tabeller, så man kan se hvilke personer der har skrevet hvilke poster. Ja?
  • Sikker. Ondsindede personer kan ikke uretmæssigt ændre databasens indhold,
    Korrekt. Databasens indhold afspejler den virkelighed, databasen modellerer.

Analysen

For at være sikker på at den database man skal udvikle overholder de regler, laver man først en analyse af den virkelighed man vil modellere. Lad os tage et eksempel: vi vil modellere en database med kageopskrifter. Det er jo enkelt nok – man kan næsten se tabellen for sig:

Navn Ingredienser Opskrift Ophavsmand Tidsforbrug
Chokoladekage

Ikke sandt?

Nu ligner databasen i øvrigt fuldkommen et regneark, som vi kender dem – og det er fint nok til at begynde med. Vi skal snart se at vi kan vælge at lade databasen være præcis som den er her – eller vi kan udvide databasen betragteligt. Det kommer helt an på hvad den skal bruges til!

Use Cases

Use-cases er en brugerorienteret metode til at planlægge hvad vi ønsker at bruge en database til. Use case kan oversættes til “brugs-mulighed” eller lignende, men det engelske ord er mere mundret. For at lave en use-case, skal vi forestille os at en eller anden bruger, skal anvende databasen, f.eks:

  • Finn har lavet en fantastisk sandkage, og får lyst til at dele den med andre. Han har brug for et sted hvor han kan gemme oplysninger om kagens navn, opskrift og ingredienser, så andre kan få glæde af den.
  • Johnny skal holde fødselsdag, og leder efter en kageopskrift. Han slår op i databasen og kigger på alle kagernes navne. Han kigger også på hvor lang tid det tager at lave dem, for han har lidt travlt.
  • Elsa er lækkersulten, men hun gider ikke gå ud i regnvejret. Hun slår op i databasen og kigger opskrifter og ingredienslister igennem for at finde en opskrift, hvor hun kun skal bruge de ting hun i forvejen har i køkkenet.

Det var tre use-cases. Det er vigtigt at use-cases tager udgangspunkt i den virkelige verden – derfor bruger man små historier og navngivne personer til at lave dem. På den måde sætter man sig også lidt ind i hvordan databasen engang skal blive til et digitalt “produkt”, for eksempel en hjemmeside eller app, som skal bruges i den virkelige verden.

Heldigvis var de tre use-cases ret simple – vores superenkle database kan sagtens bruges til at opfylde Elsa, Finn og Johnnys behov. Vi kunne imidlertid også godt forestille os mere avancerede use-cases:

  • Jan-Ole har travlt og vil kun se de opskrifter hvor tidsforbruget er mindst. Han vil derfor gerne kunne sortere kagerne så dem der tager kortest tid at lave, står øverst.
  • Freja gider ikke læse de lange beskrivelser. Hun vil helst se et bilede af kagen hun skal lave, og en video med hvordan man gør.
  • Per har haft succes med flere af de opskrifter som “Anna Larsen” har lagt i databasen. Samtidig elsker han ingefær og chokolade. Han vil gerne kunne udtrække en liste, som kombinerer ophavsmand samt ingredienserne “ingefær” og “chokolade”.

Need to have og nice to have

Vi kan hurtigt se at der er stor forskel på hvor komplicerede de forskellige use-cases er. Det er vigtigt at gøre sig klart fra start, hvor avanceret databasen skal være. Man kan for eksempel dele use-cases op i need to have og nice to have:

Need

  • Finn har lavet en fantastisk sandkage, og får lyst til at dele den med andre. Han har brug for et sted hvor han kan gemme oplysninger om kagens navn, opskrift og ingredienser, så andre kan få glæde af den.
  • Johnny skal holde fødselsdag, og leder efter en kageopskrift. Han slår op i databasen og kigger på alle kagernes navne. Han kigger også på hvor lang tid det tager at lave dem, for han har lidt travlt.
  • Elsa er lækkersulten, men hun gider ikke gå ud i regnvejret. Hun slår op i databasen og kigger opskrifter og ingredienslister igennem for at finde en opskrift, hvor hun kun skal bruge de ting hun i forvejen har i køkkenet.
  • Jan-Ole har travlt og vil kun se de opskrifter hvor tidsforbruget er mindst. Han vil derfor gerne kunne sortere kagerne så dem der tager kortest tid at lave, står øverst.

Nice

  • Freja gider ikke læse de lange beskrivelser. Hun vil helst se et bilede af kagen hun skal lave, og en video med hvordan man gør.
  • Per har haft succes med flere af de opskrifter som “Anna Larsen” har lagt i databasen. Samtidig elsker han ingefær og chokolade. Han vil gerne kunne udtrække en liste, som kombinerer ophavsmand samt ingredienserne “ingefær” og “chokolade”.

De første use-cases kan vi sagtens implementere med den simple tabel vi lavede først. Freja og Per har nogle lidt mere komplicerede behov:

Frejas kan nok løses ved at udvide tabellen med billede og videofelter. Men Pers use-case dækker over noget mere fundamentalt. I vores supersimple tabel er ingredienser bare et enkelt felt med en tekst i. Det er ikke fleksibelt hvis brugere skal kunne søge på enkeltingredienser.

Når i skal lave en database skal i derfor tage stilling til i analysen om den skal være meget simpel eller mere kompleks. HVIS man skulle lave den her database mere kompleks, kunne man lave nogle flere tabeller, f.eks sådan her:

  • Kager
    • Kage_ID, navn, Opskrift, Tidsforbrug
  • Ingredienser
    • Ingrediens_ID, Navn, beskrivelse
  • Bagere
    • ID, Navn, Efternavn, alder

Nu er der tre tabeller i databasen. Som i kan se, har de allesammen et ID. Det hedder en PRIMÆRNØGLE, og det er smart, som vi skal se nu. For hvordan finder vi nu ud af hvilke ingredienser, der er i en kage?

Jo, vi laver en RELATION mellem de to tabeller. Det er i virkeligheden en tabel til:

  • Kage_Ingrediens
    • Kage_ID
    • Ingrediens_ID

Og hvordan finder vi ud af hvilken bager der har bidraget med en kage?

  • Kage_Bager
    • Kage_ID
    • Bager_ID

Sammenhængen mellem tabellerne kaldes altså en relation. 

Entiteter og Attributter

På databasesprog kan man beskrive kager som en entitet. Entiteter er kort sagt navnet på de tabeller der skal være i databasen. I denne database kan vi vælge kun at have en enkelt tabel: kager.

Man kan tegne en figur af entiteten og dens attributter sådan her:

Entitet-attribut skitse. Kopiér skabelonen her og lav jeres egen   

Det er altså den simple database. HVIS vi ville lave den mere avancerede database, skal der oprettes tre entiteter: “Kager”, “Ingredienser” og “Bagere”.

Datatyper

I skal nu tage stilling til hvilke datatyper jeres attributter har. Når man skal gemme data i en base, er det nemlig ret vigtigt at være præcis med hvad man gemmer. Lad os sige man vil gemme et fornavn. Så er der ikke grund til at gøre plads til en dansk stil vel? I virkeligheden er der voldsomt mange datatyper, men i behøver ikke sætte jer ind i dem allesammen på dette niveau. I skal tage stilling til om jeres attributter har følgende typer:

  • Tekst (kort tekstfelt, for eksempel fornavn)
  • Lang tekst (for eksempel præsentation af person)
  • Boolean (for eksempel om man er kagefan eller ej, repræsenteres som 0 eller 1)
  • Dato
  • Numerisk (for eksempel et tal)

Der er et par ting til som skal angives for hver attribut:

    • PRIMÆRNØGLE – er dette felt den unikke nøgle (nummer) som tabellen skal bruge?
  • Obligatorisk (skal udfyldes før medlemmet kan oprettes)
  • Default (værdi som indsættes som default, hvis der ikke er angivet andet)
  • Krypteret (angiver om oplysningen skal gemmes i krypteret form)

I den simple database kunne felterne se sådan her ud:

Kager

  • KAGE_ID (Integer, fortløbende nummer)
  • Navn (Tekst, Obligatorisk)
  • Ingredienser (Lang tekst, Obligatorisk)
  • Opskrift (Lang tekst, Obligatorisk)
  • Ophavsmand (Tekst, Obligatorisk)

For den avancerede database, skal øvelsen gentages med alle tre entiteter:

  • Kager
    1. KAGE_ID (Integer, fortløbende nummer)
    2. Navn (Tekst, Obligatorisk)
    3. Opskrift (Tekst, Obligatorisk)
  • Ingredienser
    1. KAGE_ID (Integer, fortløbende nummer)
    2. Navn (Tekst, Obligatorisk)
    3. Beskrivelse (Lang tekst)
  • Bagere
    1. BAGER_ID (Integer, fortløbende nummer)
    2. Navn (Tekst, Obligatorisk)
    3. Efternavn (Tekst, Obligatorisk)
    4. Alder (Numerisk)

Men så var der jo det her med relationerne. Hvis vi skal lave den avancerede database, skal vi have to tabeller til. Som udelukkende skal bruges til at slå relationer op mellem “kager og ingredienser” og “kager og bagere”:

  • Kage_Ingrediens
    1. Kage_ID
    2. Ingrediens_ID
  • Kage_Bager
    1. Kage_ID
    2. Bager_ID

Fagterm: Relationer

I den simple database er der ikke nogen relationer. Der er kun en tabel – og alle kager, ingredienser og bagere er i den. Det er sådan set okay – eftersom det ikke ligefrem er en bank vi modellerer.

Men det har nogle svagheder i forhold til de kriterier for en god database, som vi indledningsvis så på. Tænk jer for eksempel at vi har en bager – vi kalder hende “Irma Larsen” – som lægger rigtig mange opskrifter ind i databasen. Vi kan nu forestille os hvordan tabellen kunne se ud efterhånden:

Navn Ingredienser Opskrift Ophavsmand Tidsforbrug
Chokoladekage Anna Larsen
Sandkage Anna Larsen
Kiksekage Ann Larsen

Anna Larsens navn står nu rigtig mange gange i tabellen. Det er jo ikke pladseffektivt. Men det er heller ikke så smart at hun skal taste sit navn ind hver gang hun vil lægge en ny opskrift ind. Det kunne f.eks være hun lavede en tastefejl på et tidspunkt, så der står “Ann Larsen”. Er det mon den samme som Anna Larsen? En mere problematisk side ved den simple database, er derfor at data i den risikerer ikke at være korrekte.

Det kommer vi ud over ved at lave databasen relationel. Lad os se på hvordan.

Øvelse: entitet-relations diagram

Man kan sætte den avancerede databases entiteter og relationer op i et såkaldt enititet-relations diagram, som beskrevet i grundbogen her. Nedenfor ser i et E/R diagram for den avancerede kagedatabase.

E/R Diagrammet skal læses sådan her:

  • En kage har flere ingredienser, og en ingrediens kan

Hent skabelonen her

En entitet er en enhed, der ofte er en enhed i fysisk forstand. Fx. en bil, en person eller et spil.

  • En relation er en sammenkobling af to entiteter. Fx. medlem ejer spil – her er ejer relationen.
  • Relationsgraden bestemmer forholdet mellem relationerne.
    • 1-M (en-til-mange)
    • M-M (mange-til-mange)
    • 1-1 (en-til-en)