Forstå relasjonsdatabasemodellen, fremmednøkler, relasjonstyper og ER-diagrammer.
Relasjonsdatabasar og datamodellering
I førre kapittel vart vi kjende med grunnleggjande databaseomgrep. No skal vi dykke djupare inn i relasjonsdatabasemodellen – den modellen som ligg til grunn for dei fleste databasar i verda. Vi skal lære korleis tabellar blir kopla saman, kva for typar relasjonar som finst, og korleis vi planlegg ein database ved hjelp av ER-diagram.
God datamodellering er noko av det viktigaste du kan lære om databasar. Ein godt designa database er enkel å jobbe med, rask å søkje i og lett å utvide. Ein dårleg designa database fører derimot til dupliserte data, inkonsistens og ytingsproblem som er vanskelege å rette opp i etterkant. Difor brukar ein alltid tid på å planleggje databasestrukturen grundig før ein byrjar å lage tabellar og fylle inn data.
Ein framandnøkkel er ein kolonne i ein tabell som inneheld verdiar som refererer til primærnøkkelen i ein annan tabell. Framandnøklar er limet som held ein relasjonsdatabase saman – dei oppretter koplingar mellom tabellar. Framandnøklar sikrar referanseintegritet, som betyr at databasen hindrar deg i å opprette referansar til rader som ikkje eksisterer. Til dømes kan du ikkje registrere ein karakter for elev_id 99 dersom det ikkje finst nokon elev med id 99 i elevtabellen.
Det finst tre grunnleggjande typar relasjonar mellom tabellar i ein relasjonsdatabase:
1. Ein-til-ein (1:1)
Kvar rad i tabell A er kopla til nøyaktig éin rad i tabell B, og omvendt. Denne typen er relativt sjeldan.
Døme: Kvar elev har nøyaktig eitt elevkort, og kvart elevkort høyrer til nøyaktig éin elev.
| elevid | fornavn | etternavn | → | kortid | elevid | kortnummer | utstedtdato |
|---|---|---|---|---|---|---|---|
| 1 | Emma | Hansen | 1 | 1 | EK-2024-001 | 2024-08-15 | |
| 2 | Oliver | Johansen | 2 | 2 | EK-2024-002 | 2024-08-15 |
2. Ein-til-mange (1:N)
Éin rad i tabell A kan koplast til mange rader i tabell B, men kvar rad i tabell B blir kopla til berre éin rad i tabell A. Dette er den vanlegaste relasjonstypen.
Døme: Éin klasse har mange elevar, men kvar elev høyrer berre til éin klasse.
| klasseid | klassenavn | → | elevid | fornavn | klasseid |
|---|---|---|---|---|---|
| 1 | 10A | 1 | Emma | 1 | |
| 2 | 10B | 2 | Oliver | 1 | |
| 3 | Nora | 2 |
Framandnøkkelen klasse_id ligg på mange-sida (i elevtabellen).
3. Mange-til-mange (M:N)
Mange rader i tabell A kan koplast til mange rader i tabell B. Denne relasjonstypen krev alltid ein koplingstabell.
Døme: Ein elev kan ha mange fag, og eit fag kan ha mange elevar.
Denne relasjonen kan ikkje løysast med berre éin framandnøkkel – vi treng ein koplingstabell mellom dei to:
elever ← elevfag → fag
Lat oss sjå på forholdet mellom elevar og fag:
Tabell: elever
| elevid | fornavn | etternavn |
|---|---|---|
| 1 | Emma | Hansen |
| 2 | Oliver | Johansen |
| 3 | Nora | Olsen |
Tabell: fag
| fagid | fagnavn |
|---|---|
| 1 | Matematikk |
| 2 | Norsk |
| 3 | Naturfag |
Koplingstabell: elevfag
| elevid | fagid |
|---|---|
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 1 |
| 2 | 2 |
| 3 | 2 |
| 3 | 3 |
Her kan vi lese at:
- Emma (elevid 1) tek matematikk, norsk og naturfag
- Oliver (elevid 2) tek matematikk og norsk
- Nora (elevid 3) tek norsk og naturfag
Koplingstabellen har ein samansett primærnøkkel beståande av begge framandnøklane (elev_id + fag_id). Han kan òg utvidast med ekstra kolonnar, til dømes karakter eller termin.
Før du oppretter ein database, bør du planleggje strukturen visuelt. Eit ER-diagram (Entity-Relationship-diagram) er eit standardverktøy for dette. ER-diagram viser:
- Entitetar (ting vi lagrar informasjon om) som rektangel
- Attributt (eigenskapar) som ovalar kopla til entiteten
- Relasjonar som linjer mellom entitetar med markeringar for relasjonstype
Kråkefotsnotasjon (Crow's Foot)
Den mest brukte notasjonen for ER-diagram i praksis er kråkefotsnotasjon. Her blir symbol på linjene mellom tabellane brukte:
- | (strek) = nøyaktig éin
- O (sirkel) = null (valfri)
- < (kråkefot/gaffel) = mange
Kombinasjonar:
- ||——|| = ein-til-ein (begge obligatoriske)
- ||——O< = ein-til-mange (mange-sida er valfri)
- ||——|< = ein-til-mange (mange-sida er obligatorisk)
- >O——O< = mange-til-mange (begge sider valfrie)
Døme: ER-diagram for skuledatabase
┌──────────┐ ┌──────────┐
│ Klasse │ 1 N │ Elev │
│──────────│─────────│──────────│
│ klasse_id│ │ elev_id │
│ navn │ │ fornavn │
└──────────┘ │ etternavn│
│ klasse_id│
└──────────┘
│
│ N
┌──────────┐
│ Elev_Fag │
│──────────│
│ elev_id │
│ fag_id │
│ karakter │
└──────────┘
│
│ N
┌──────────┐
│ Fag │
│──────────│
│ fag_id │
│ fagnavn │
│ laerer │
└──────────┘Her ser vi at Klasse har ein ein-til-mange-relasjon med Elev (éin klasse har mange elevar), og Elev har ein mange-til-mange-relasjon med Fag (via koplingstabellen Elev_Fag).
Når vi har planlagt databasestrukturen, er neste steg å opprette tabellane med SQL. Kommandoen CREATE TABLE blir brukt til å definere ein ny tabell med kolonnar, datatypar og avgrensingar.
Her er SQL-koden for skuledatabasen:
-- Opprett tabellen for klasser
CREATE TABLE klasser (
klasse_id INTEGER PRIMARY KEY AUTOINCREMENT,
klassenavn TEXT NOT NULL
);
-- Opprett tabellen for elever
CREATE TABLE elever (
elev_id INTEGER PRIMARY KEY AUTOINCREMENT,
fornavn TEXT NOT NULL,
etternavn TEXT NOT NULL,
fodselsdato DATE,
klasse_id INTEGER,
FOREIGN KEY (klasse_id) REFERENCES klasser(klasse_id)
);
-- Opprett tabellen for fag
CREATE TABLE fag (
fag_id INTEGER PRIMARY KEY AUTOINCREMENT,
fagnavn TEXT NOT NULL,
laerer TEXT
);
-- Opprett koblingstabellen for elever og fag
CREATE TABLE elev_fag (
elev_id INTEGER,
fag_id INTEGER,
karakter INTEGER,
termin TEXT,
PRIMARY KEY (elev_id, fag_id),
FOREIGN KEY (elev_id) REFERENCES elever(elev_id),
FOREIGN KEY (fag_id) REFERENCES fag(fag_id)
);Lat oss bryte ned dei viktigaste elementa:
- INTEGER PRIMARY KEY AUTOINCREMENT – Oppretter ein primærnøkkel som automatisk aukar med 1 for kvar ny rad
- TEXT NOT NULL – Kolonnen lagrar tekst og kan ikkje vere tom
- FOREIGN KEY ... REFERENCES ... – Oppretter ein framandnøkkel som refererer til ein annan tabell
- PRIMARY KEY (elev_id, fag_id) – Samansett primærnøkkel som sikrar at kombinasjonen av elev og fag er unik
Lat oss modellere ein enkel nettbutikk med kundar, produkt og bestillingar.
Entitetar og attributt:
- Kunde: kundeid, fornavn, etternavn, epost, telefon
- Produkt: produktid, produktnavn, beskrivelse, pris, antallpaalager
- Bestilling: bestillingid, kundeid, bestillingsdato, totalpris, status
- Bestillingslinje: bestillingid, produktid, antall, linjepris
Relasjonar:
- Kunde → Bestilling: Ein-til-mange (éin kunde kan ha mange bestillingar)
- Bestilling → Bestillingslinje: Ein-til-mange (éi bestilling kan ha mange produkt)
- Produkt → Bestillingslinje: Ein-til-mange (eitt produkt kan vere i mange bestillingar)
CREATE TABLE kunder (
kunde_id INTEGER PRIMARY KEY AUTOINCREMENT,
fornavn TEXT NOT NULL,
etternavn TEXT NOT NULL,
epost TEXT UNIQUE NOT NULL,
telefon TEXT
);
CREATE TABLE produkter (
produkt_id INTEGER PRIMARY KEY AUTOINCREMENT,
produktnavn TEXT NOT NULL,
beskrivelse TEXT,
pris REAL NOT NULL,
antall_paa_lager INTEGER DEFAULT 0
);
CREATE TABLE bestillinger (
bestilling_id INTEGER PRIMARY KEY AUTOINCREMENT,
kunde_id INTEGER NOT NULL,
bestillingsdato DATE DEFAULT CURRENT_DATE,
totalpris REAL,
status TEXT DEFAULT 'ny',
FOREIGN KEY (kunde_id) REFERENCES kunder(kunde_id)
);
CREATE TABLE bestillingslinjer (
bestilling_id INTEGER,
produkt_id INTEGER,
antall INTEGER NOT NULL,
linjepris REAL NOT NULL,
PRIMARY KEY (bestilling_id, produkt_id),
FOREIGN KEY (bestilling_id) REFERENCES bestillinger(bestilling_id),
FOREIGN KEY (produkt_id) REFERENCES produkter(produkt_id)
);Her ser vi mange-til-mange-relasjonen mellom bestillingar og produkt løyst gjennom koplingstabellen bestillingslinjer. Ei bestilling kan innehalde mange produkt, og eit produkt kan inngå i mange bestillingar.
Avgrensingar (constraints) er reglar du kan leggje på kolonnar for å sikre datakvalitet:
- PRIMARY KEY – Kolonnen er primærnøkkel (unik og ikkje NULL)
- NOT NULL – Kolonnen kan ikkje vere tom
- UNIQUE – Alle verdiar i kolonnen må vere unike
- DEFAULT verdi – Gjev kolonnen ein standardverdi dersom ingen verdi blir oppgjeven
- CHECK (vilkår) – Verdien må oppfylle eit vilkår (t.d. CHECK (alder >= 0))
- FOREIGN KEY – Verdien må eksistere som primærnøkkel i ein annan tabell
Avgrensingar er viktige fordi dei sikrar at dataa i databasen alltid er gyldige og konsistente, uavhengig av kven eller kva som set inn data.
Unngå desse vanlege feila når du designar ein database:
1. Alt i éin tabell: Ikkje legg all informasjon i éin stor tabell. Del opp i logiske einingar.
2. Gløyme primærnøkkel: Kvar tabell bør alltid ha ein primærnøkkel.
3. Bruke namn som primærnøkkel: Namn er ikkje unike – bruk eit generert ID-nummer.
4. Lagre utrekna verdiar: Ikkje lagre data som kan reknast ut (t.d. alder frå fødselsdato).
5. Gløyme framandnøklar: Definer alltid framandnøklar eksplisitt for å sikre referanseintegritet.
6. Inkonsistente datatypar: Bruk alltid same datatype for kolonnar som skal samanliknast.
Følg desse stega når du skal designe ein ny database:
1. Identifiser entitetane – Kva treng du å lagre informasjon om? (Elevar, bøker, bestillingar...)
2. Definer attributta – Kva for eigenskapar har kvar entitet? (Namn, pris, dato...)
3. Bestem primærnøklar – Kva identifiserer kvar rad unikt?
4. Finn relasjonane – Korleis heng entitetane saman? (Ein-til-mange, mange-til-mange?)
5. Teikn ER-diagram – Lag ei visuell oversikt over strukturen
6. Skriv CREATE TABLE – Opprett tabellane med SQL
7. Test med data – Set inn nokre testrader og verifiser at alt fungerer
Kva er ein framandnøkkel?
Kva for ein relasjonstype finst mellom tabellane «klasser» og «elever» dersom kvar elev høyrer til nøyaktig éin klasse, men ein klasse kan ha mange elevar?
Korleis blir ein mange-til-mange-relasjon implementert i ein relasjonsdatabase?
Gitt følgjande SQL:
CREATE TABLE elever (
elev_id INTEGER PRIMARY KEY AUTOINCREMENT,
fornavn TEXT NOT NULL,
etternavn TEXT NOT NULL,
klasse_id INTEGER,
FOREIGN KEY (klasse_id) REFERENCES klasser(klasse_id)
);Kva betyr NOT NULL for kolonnane fornavn og etternavn?
Teikn eit ER-diagram (eller skildra det med tekst) for ein enkel kino-database. Kinoen treng å halde oversikt over filmar (tittel, sjanger, lengd, aldersgrense), salar (salnummer, tal på plassar) og forestillingar (dato, klokkeslett). Identifiser entitetar, attributt, primærnøklar og relasjonar mellom tabellane.
Skriv SQL-kode (CREATE TABLE) for kino-databasen frå førre oppgåve. Inkluder passande datatypar, primærnøklar, framandnøklar og NOT NULL-avgrensingar der det er relevant.
Du har tabellane forfattere og boker. Ein forfattar kan skrive mange bøker, og ei bok kan ha fleire forfattarar (samarbeid). Kva for ein relasjonstype er dette, og korleis blir det løyst?
Oppsummering
I dette kapittelet har du lært:
- Relasjonsmodellen: tabellar kopla med nøklar.
- Framandnøkkel: refererer til primærnøkkelen i ein annan tabell.
- Relasjonstypar: ein-til-ein, ein-til-mange og mange-til-mange.
- Koplingstabell: løyser mange-til-mange-relasjonar.
- ER-diagram: modellerer datastrukturar (kråkefotsnotasjon).
Nøkkelomgrep
| Omgrep | Forklaring |
|---|---|
| Framandnøkkel | Kolonne som refererer til primærnøkkelen i ein annan tabell |
| ER-diagram | Diagram som modellerer entitetar og relasjonar |
| Koplingstabell | Tabell som løyser mange-til-mange-relasjonar |
Dette kapitlet er skrevet av Anthropics toppmodeller (Claude Opus og Claude Fable) og er foreløpig ikke manuelt gjennomgått — kvalitetskontrollen gjøres av uavhengige KI-agenter, og innmeldte feil rettes fortløpende. Funnet en feil? Meld fra, så retter vi den. Les mer om hvordan innholdet lages.