Lær prinsippene for god databasedesign gjennom de tre normalformene.
Normalisering og databasedesign
Forestill deg at ein skule lagrar all informasjon i éin einaste tabell:
| elev_id | fornavn | etternavn | klasse | lærer | fag | karakter |
|---|---|---|---|---|---|---|
| 1 | Emma | Hansen | 10A | Kari Nordli | Matematikk | 5 |
| 1 | Emma | Hansen | 10A | Per Haugen | Norsk | 4 |
| 1 | Emma | Hansen | 10A | Lise Vik | Naturfag | 5 |
| 2 | Oliver | Johansen | 10A | Kari Nordli | Matematikk | 3 |
| 2 | Oliver | Johansen | 10A | Per Haugen | Norsk | 4 |
Ser du problema? Namnet og klassen til Emma blir gjentekne for kvar karakter. Viss Emma byter klasse, må vi oppdatere tre rader. Kva viss vi gløymer éi? Då har vi inkonsistente data. Og kva viss vi slettar alle karakterane til ein elev – forsvinn all informasjon om eleven?
Normalisering er løysinga. Det er ein systematisk metode for å organisere databasetabellar slik at dei unngår desse problema. I dette kapittelet skal du lære dei tre første normalformene og korleis du brukar dei til å designe gode databasar.
Unormaliserte tabellar (som den store enkelttabellen over) fører til tre typar problem kalla anomaliar:
1. Oppdateringsanomali
Når data er dupliserte og du endrar berre nokre førekomstar, blir dataa inkonsistente.
Døme: Emma Hansen byter frå 10A til 10B. Informasjonen «10A» finst i tre rader. Viss vi berre oppdaterer to av dei, står det 10B i to rader og 10A i éi rad – inkonsistens.
2. Innsettingsanomali
Du kan ikkje lagre informasjon utan å ha tilhøyrande data.
Døme: Vi tilset ein ny lærar, Jon Hauge, som skal undervise i historie. Men vi kan ikkje leggje han inn i tabellen utan å òg ha ein elev og ein karakter, fordi alle kolonnane er i same tabell.
3. Slettingsanomali
Sletting av data fører til utilsikta tap av annan informasjon.
Døme: Viss vi slettar alle karakterrader for Liam (den einaste eleven i 10C med naturfagskarakter), mistar vi ikkje berre karakteren, men potensielt informasjonen om at Lise Vik underviser i naturfag.
Alle tre anomaliane skuldast det same grunnproblemet: data som logisk høyrer til ulike ting er blanda saman i éin tabell. Normalisering løyser dette ved å dele data inn i separate, spesialiserte tabellar.
Ein tabell er i første normalform (1NF) når:
1. Alle kolonnar inneheld atomære verdiar (udelelege enkeltverdiar)
2. Det finst ingen gjentakande grupper eller kolonnar
3. Kvar rad er unik (tabellen har ein primærnøkkel)
Døme: Brot med 1NF
| elevid | fornavn | fag |
|---|---|---|
| 1 | Emma | Matematikk, Norsk, Naturfag |
| 2 | Oliver | Matematikk, Norsk |
Kolonnen
fag inneheld fleire verdiar i éi celle – det bryt med 1NF. Korleis finn du alle elevar som tek naturfag? Du kan ikkje bruke WHERE fag = 'Naturfag' fordi verdien er «Matematikk, Norsk, Naturfag».Etter 1NF
| elevid | fornavn | fag |
|---|---|---|
| 1 | Emma | Matematikk |
| 1 | Emma | Norsk |
| 1 | Emma | Naturfag |
| 2 | Oliver | Matematikk |
| 2 | Oliver | Norsk |
No har kvar celle berre éin verdi, og vi kan enkelt søkje:
SELECT fornavn FROM elever_fag WHERE fag = 'Naturfag';Eit anna døme: Gjentakande kolonnar
| elev_id | fornavn | fag1 | fag2 | fag3 |
|---|---|---|---|---|
| 1 | Emma | Matematikk | Norsk | Naturfag |
| 2 | Oliver | Matematikk | Norsk | NULL |
Dette bryt òg med 1NF – gjentakande kolonnar for fag. Kva viss ein elev tek fire fag? Då må vi leggje til ein ny kolonne. Løysinga er å dele opp i rader, som vist over.
Ein tabell er i andre normalform (2NF) når:
1. Han er i 1NF
2. Alle ikkje-nøkkelkolonnar er fullt funksjonelt avhengige av heile primærnøkkelen
2NF er relevant for tabellar med samansette primærnøklar (primærnøklar som består av to eller fleire kolonnar). Viss ein kolonne berre avheng av éin del av nøkkelen, bør han flyttast til ein eigen tabell.
Døme: Brot med 2NF
Tenk deg ein tabell for kursregistrering med samansett primærnøkkel (elevid + fagid):
| elevid | fagid | elevnavn | fagnavn | karakter |
|---|---|---|---|---|
| 1 | 1 | Emma | Matematikk | 5 |
| 1 | 2 | Emma | Norsk | 4 |
| 2 | 1 | Oliver | Matematikk | 3 |
Primærnøkkel: (elevid, fagid)
Problem:
elevnavn avheng berre av elev_id (ikkje av heile nøkkelen). fagnavn avheng berre av fag_id. Berre karakter avheng av heile nøkkelen (elevid + fagid).Etter 2NF – del opp i tre tabellar:
elever:
| elevid | elevnavn |
|---|---|
| 1 | Emma |
| 2 | Oliver |
fag:
| fagid | fagnavn |
|---|---|
| 1 | Matematikk |
| 2 | Norsk |
karakterer:
| elevid | fagid | karakter |
|---|---|---|
| 1 | 1 | 5 |
| 1 | 2 | 4 |
| 2 | 1 | 3 |
No avheng alle kolonnar av heile primærnøkkelen i sin respektive tabell. Elevnamn blir lagra berre éin gong, og fagnamn blir lagra berre éin gong.
Ein tabell er i tredje normalform (3NF) når:
1. Han er i 2NF
2. Ingen ikkje-nøkkelkolonne er avhengig av ein annan ikkje-nøkkelkolonne (ingen transitive avhengigheiter)
Med andre ord: alle ikkje-nøkkelkolonnar avheng direkte av primærnøkkelen, ikkje indirekte via andre kolonnar.
Døme: Brot med 3NF
| elevid | fornavn | etternavn | postnummer | poststed |
|---|---|---|---|---|
| 1 | Emma | Hansen | 0150 | Oslo |
| 2 | Oliver | Johansen | 0150 | Oslo |
| 3 | Nora | Olsen | 5003 | Bergen |
Problem:
poststed avheng av postnummer, som igjen avheng av elev_id. Dette er ei transitiv avhengigheit: elevid → postnummer → poststed. Poststad avheng ikkje direkte av elevid.Konsekvensen er at «Oslo» blir lagra to gonger (for postnummer 0150). Viss postnummer 0150 byter namn, må vi oppdatere alle rader.
Etter 3NF – skil ut poststader:
elever:
| elevid | fornavn | etternavn | postnummer |
|---|---|---|---|
| 1 | Emma | Hansen | 0150 |
| 2 | Oliver | Johansen | 0150 |
| 3 | Nora | Olsen | 5003 |
poststeder:
| postnummer | poststed |
|---|---|
| 0150 | Oslo |
| 5003 | Bergen |
No blir kvar poststad lagra berre éin gong, og alle ikkje-nøkkelkolonnar avheng direkte av primærnøkkelen i sin respektive tabell.
2NF – Full funksjonell avhengigheit: Alle ikkje-nøkkelkolonnar avheng av heile primærnøkkelen, ikkje berre ein del av han. (Relevant ved samansette primærnøklar.)
3NF – Ingen transitive avhengigheiter: Alle ikkje-nøkkelkolonnar avheng direkte av primærnøkkelen, ikkje av andre ikkje-nøkkelkolonnar.
Hugseregel: «Nøkkelen, heile nøkkelen, og ingenting anna enn nøkkelen.»
- 1NF: Dataa har ein nøkkel (primærnøkkel, atomære verdiar)
- 2NF: Avheng av heile nøkkelen (ikkje delar av samansett nøkkel)
- 3NF: Ingenting anna enn nøkkelen (ingen transitive avhengigheiter)
| utlaan_id | elevnavn | klasse | boktittel | forfatter | isbn | utdato | inndato |
|---|---|---|---|---|---|---|---|
| 1 | Emma Hansen | 10A | Sofies verden | Jostein Gaarder | 978-82-03-19 | 2024-09-01 | 2024-09-15 |
| 2 | Emma Hansen | 10A | Beatles | Lars S. Christensen | 978-82-02-25 | 2024-09-10 | NULL |
| 3 | Oliver Johansen | 10A | Sofies verden | Jostein Gaarder | 978-82-03-19 | 2024-09-05 | 2024-09-20 |
Problem:
- Namnet og klassen til Emma blir gjentekne (redundans)
- «Sofies verden» med forfattar og ISBN blir gjenteke (redundans)
-
elevnavn er ikkje atomært (fornamn + etternamn i éin kolonne) → bryt 1NFSteg 1: 1NF – atomære verdiar
Del elevnavn i fornavn og etternavn. Fjern gjentakande data.
Steg 2: 2NF og 3NF – fjern partielle og transitive avhengigheiter
CREATE TABLE elever (
elev_id INTEGER PRIMARY KEY AUTOINCREMENT,
fornavn TEXT NOT NULL,
etternavn TEXT NOT NULL,
klasse TEXT
);
CREATE TABLE boker (
bok_id INTEGER PRIMARY KEY AUTOINCREMENT,
tittel TEXT NOT NULL,
forfatter TEXT,
isbn TEXT UNIQUE
);
CREATE TABLE utlaan (
utlaan_id INTEGER PRIMARY KEY AUTOINCREMENT,
elev_id INTEGER NOT NULL,
bok_id INTEGER NOT NULL,
utlaans_dato DATE NOT NULL,
innleverings_dato DATE,
FOREIGN KEY (elev_id) REFERENCES elever(elev_id),
FOREIGN KEY (bok_id) REFERENCES boker(bok_id)
);
-- Sett inn data
INSERT INTO elever (fornavn, etternavn, klasse) VALUES
('Emma', 'Hansen', '10A'),
('Oliver', 'Johansen', '10A');
INSERT INTO boker (tittel, forfatter, isbn) VALUES
('Sofies verden', 'Jostein Gaarder', '978-82-03-19'),
('Beatles', 'Lars S. Christensen', '978-82-02-25');
INSERT INTO utlaan (elev_id, bok_id, utlaans_dato, innleverings_dato) VALUES
(1, 1, '2024-09-01', '2024-09-15'),
(1, 2, '2024-09-10', NULL),
(2, 1, '2024-09-05', '2024-09-20');No er dataa normaliserte: elevinformasjon blir lagra berre éin gong, bokinformasjon blir lagra berre éin gong, og utlånstabellen koplar dei saman.
Normalisering er generelt ein god praksis, men det finst situasjonar der ein medvite vel å denormalisere – altså tillate noko redundans:
Ytingsomsyn
Normaliserte databasar krev mange JOIN-operasjonar for å setje saman data frå fleire tabellar. I system med ekstremt mange spørjingar (som sosiale medium med millionar av brukarar) kan dette bli ein flaskehals. Då kan ein medvite duplisere noko data for å unngå dyre JOIN-operasjonar.
Rapportering og analyse
For rapporterings-databasar (datavarehus) er det vanleg å bruke «flate» tabellar med noko redundans, fordi det gjer spørjingane enklare og raskare.
Enkle system
For svært enkle system med lite data kan full normalisering gjere ting unødvendig komplisert.
Hovudregelen er: Start alltid med normalisering. Denormaliser berre viss du har dokumenterte ytingsproblem som ikkje kan løysast på andre måtar. Det er mykje lettare å denormalisere ein normalisert database enn å normalisere ein rotete ein.
Når du skal designe ein database frå botnen av, følg denne prosessen:
1. Forstå krava – Kva skal systemet gjere? Kva data trengst?
2. Identifiser entitetar – Kva er «tinga» vi lagrar? (Elevar, bøker, bestillingar...)
3. Definer attributt – Kva eigenskapar har kvar entitet?
4. Finn relasjonar – Korleis heng entitetane saman?
5. Teikn ER-diagram – Visualiser strukturen
6. Normaliser – Sjekk 1NF, 2NF, 3NF og juster tabellane
7. Skriv SQL – Opprett tabellane med CREATE TABLE
8. Test med data – Sett inn testdata og køyr spørjingar
9. Iterer – Juster designet basert på reelle behov
God databasedesign er ein ferdigheit som blir utvikla med praksis. Jo fleire databasar du designar, jo betre intuisjon utviklar du for kva som fungerer og kva som ikkje fungerer.
Pass deg for desse vanlege feila:
1. Kommaseparerte lister i kolonnar: fag = "Matte, Norsk, Naturfag" bryt med 1NF. Bruk ein koplingstabell.
2. Gjentakande kolonnar: telefon1, telefon2, telefon3 bryt med 1NF. Lag ein eigen tabell for telefonnummer.
3. Berekna verdiar lagra i tabellen: Ikkje lagre alder viss du har fodselsdato. Rekn det ut med SQL i staden.
4. Miks av ulike entitetar: Ikkje legg elevinfo og faginfo i same tabell berre fordi dei blir brukte saman.
5. For mykje normalisering: Det finst tilfelle der det er greitt å lagre noko «ekstra» data for å forenkle spørjingar.
Kva er normalisering i databasesamanheng?
Denne tabellen bryt med første normalform (1NF). Kvifor?
| elev_id | fornavn | hobbyer |
|---|---|---|
| 1 | Emma | Fotball, Lesing, Sjakk |
| 2 | Oliver | Gaming, Fotball |
Kva type anomali oppstår i dette scenarioet?
Du har ein tabell der elevnamn og klasse blir lagra saman med karakterar. Emma Hansen er i klasse 10A og har tre karakterrader. Du oppdaterer klassen til 10B i to av radene, men gløymer den tredje.
Denne tabellen er unormalisert. Identifiser kva normalformer han bryt med, og vis korleis du normaliserer han til 3NF.
| bestillingid | kundenavn | kundeepost | produkt | pris | antall | totalpris |
|---|---|---|---|---|---|---|
| 1 | Emma Hansen | emma@mail.no | USB-kabel | 79 | 2 | 158 |
| 2 | Emma Hansen | emma@mail.no | Mus | 299 | 1 | 299 |
| 3 | Oliver Johansen | oliver@mail.no | USB-kabel | 79 | 3 | 237 |
Kva normalform bryt denne tabellen med?
| ansattid | navn | avdeling | avdelingsleder |
|---|---|---|---|
| 1 | Kari Nordli | Matematikk | Per Haugen |
| 2 | Lise Vik | Naturfag | Tom Bakke |
| 3 | Jon Hauge | Matematikk | Per Haugen |
Primærnøkkel: ansattid. Avdelingsleiar avheng av avdeling (ikkje direkte av ansatt_id).
Design ein fullstendig normalisert database (3NF) for eit treningssenter. Systemet skal handtere:
- Medlemmer (namn, telefon, e-post, medlemstype)
- Treningsklassar (namn, skildring, varigheit, instruktør)
- Påmeldingar til klassar (medlem, klasse, dato, tidspunkt)
- Instruktørar (namn, spesialisering, telefon)
Teikn eller skildr tabellane med kolonnar, primærnøklar, framandnøklar og relasjonstypar. Skriv deretter CREATE TABLE-kode for alle tabellane.
Kva er hugseregelen for dei tre første normalformene?
Oppsummering
I dette kapittelet har du lært:
- Normalisering: organiserer data for å unngå redundans.
- Anomaliar: oppdaterings-, innsettings- og slettingsanomali.
- 1NF: atomære verdiar, ingen gjentakande grupper.
- 2NF: ingen delvis avhengigheit av samansett nøkkel.
- 3NF: ingen transitiv avhengigheit.
Nøkkelomgrep
| Omgrep | Forklaring |
|---|---|
| Normalisering | Å organisere data for å minimere redundans |
| 1NF | Atomære verdiar i kvar kolonne |
| 3NF | Ingen transitiv avhengigheit |
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.