Databaser uden tåge

Tabeller, rækker og nøgler

11 min
What you'll learn
  • at skelne mellem tabeller, rækker og kolonner og forklare, hvorfor hver række har brug for en primærnøgle (som regel id)
  • at finde forbindelser mellem tabeller via en fremmednøgle: orders.user_id → users.id
  • at skelne mellem en surrogatnøgle (IDENTITY, ) og en naturlig nøgle (email, ISBN) og begrunde, hvorfor en primærnøgle ikke må ændre sig
  • at fastlåse entydigheden af et felt som email med en UNIQUE-begrænsning uden at gøre det til primærnøgle

Indekset er åbnet. QUERY folder et hologram ud over arbejdsbordet: tusindvis af poster svæver i luften i et jævnt gitter, og mellem nogle af dem løber tynde ravgule tråde. Du rækker ud efter én — den klinger som en streng. Det er ikke en bunke filer. Det er et væv.

Tabeller, rækker, kolonner

En relationel database ligner et velordnet katalog: dataene er fordelt på tabeller, og inde i hver tabel er der kolonner (hvilke egenskaber vi gemmer) og rækker (de konkrete poster).

Tag kundetabellen users: hver række er én kunde fra den gamle Jord, og kolonnerne beskriver vedkommendes id, full_name, email, country, city, signup_date.

For ikke at forveksle mennesker med samme navn har hver række en primærnøgle () — en entydig identifikator, som regel kolonnen id. Via den kan andre tabeller henvise til denne række ved hjælp af en fremmednøgle (). For eksempel har en ordre i orders et user_id — sådan husker ordren sin kunde. De selvsamme ravgule tråde på hologrammet er netop forbindelserne via nøgler.

QUERY: Så længe nøglen holder — holder tråden. Halvandet århundrede er gået, og hver ordre husker stadig sit menneske.

Kør forespørgslen og se, hvordan Kotomarkets kunder ser ud — poster, ingen har åbnet siden det gamle Nets tid:

En holografisk tabel af kapsel-rækker og kolonner; fra ordreposterne til menneskeposterne løber ravgule nøgletråde
Rækker er poster, kolonner er deres egenskaber, og tråden fra en ordre til en kunde er en forbindelse via nøgle.

Tables, rows, columns

A relational database is like a tidy catalog: the data is sorted into tables, and inside each table there are columns (what properties we store) and rows (the individual records).

Take the buyers’ table users: each row is one buyer from old Earth, and the columns describe their id, full_name, email, country, city, signup_date.

So that people with the same name don’t get confused, every row has a — a unique identifier, usually the id column. Through it, other tables can reference this row using a . For example, an order in orders has a user_id — that’s how an order remembers its buyer. Those amber threads on the hologram are exactly these key-based links.

QUERY: As long as the key holds, the thread holds. A century and a half on, every order still remembers its person.

Run the query and see what Kotomarket’s buyers look like — records no one has opened since the days of the old Net:

Kotomarkets første kunder i tabellen:
Query result
idfull_namecitysignup_date
1Артём ВолковСанкт-Петербург2024-10-20
2Екатерина АлексеевЕкатеринбург2025-01-25
3Николай НикитинАлматы2024-09-21
4Екатерина ИвановНовосибирск2024-05-04
5Елена ПетровКазань2025-01-05
6Ирина КузнецовНовосибирск2024-09-12

En primærnøgle hjælper dig med fejlfrit at finde én række (som regel id). En fremmednøgle knytter tabeller sammen: for eksempel viser orders.user_id → users.id, hvis ordre det er. Dernæst folder QUERY hele snapshottets kort ud for dig — alle fem tabeller på én gang.

usersidfull_namecityordersiduser_idstatususer_id → id
Fremmednøglen orders.user_id henviser til primærnøglen users.id — sådan husker en ordre sin kunde.

Naturlig eller surrogatnøgle

Hvor kommer en primærnøgle fra? Der er to veje. En naturlig nøgle er en virkelig attribut, der i forvejen er entydig: en kundes email, en bogs ISBN, en valutakode. En surrogatnøgle er en kunstig identifikator uden betydning i den ydre verden: en autonummerering eller en . I Kotomarket bruges der overalt surrogat-id-er — og det er en standardløsning:

-- Surrogatnøgle: databasen udsteder selv det næste nummer (PostgreSQL)
CREATE TABLE users (
  id        BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  email     TEXT NOT NULL UNIQUE,  -- den naturlige kandidat lever ved siden af som UNIQUE
  full_name TEXT NOT NULL
);

Hvorfor sådan? Primærnøglens vigtigste egenskab: den må ikke ændre sig. Fremmednøgler i andre tabeller peger på PK'en, og en ændring af dens værdi ville trække en opdatering af alle tråde med sig på én gang — i orders, i events, overalt. Og »evige« naturlige attributter findes næsten ikke: folk ændrer email og efternavn, telefonnumre flytter, selv ISBN'er genudgives. En surrogat-id ændrer sig aldrig — netop fordi den intet betyder.

Krav til enhver primærnøgle: entydig, ikke NULL, stabil. Lad de naturlige nøgler være forbeholdt små, uforanderlige opslagstabeller — for eksempel valutakoden 'RUB' fra ISO 4217. Og entydigheden af en naturlig kandidat som email fastlåser du med en separat UNIQUE-begrænsning, som i eksemplet ovenfor: forbindelserne holder, dataene forbliver ærlige, og det er stadig tilladt at ændre en kundes email.

Vi foregriber lidt: selve syntaksen til at oprette tabeller og begrænsninger (CREATE TABLE, PRIMARY KEY, UNIQUE) er emnet for kapitel 9. Her skal du kigge på nøglens struktur, ikke på kommandoen: at en surrogat-id blev primærnøgle, mens email lever ved siden af som UNIQUE.

Interview question

Spørgsmål fra en jobsamtale: hvad er forskellen på en surrogatnøgle og en naturlig nøgle, og hvilken vælger du til en brugertabel?

Et stærkt svar: en naturlig nøgle er en virkelig entydig attribut (email, ISBN), en surrogatnøgle er en kunstig identifikator (en IDENTITY-kolonne eller en ). Til brugere — en surrogatnøgle: en primærnøgle må ikke ændre sig, fordi fremmednøgler henviser til den, og email ændrer folk. Entydigheden af email fastlåses så med en separat UNIQUE-begrænsning. En naturlig nøgle er berettiget i stabile opslagstabeller som ISO 4217-valutakoder.

Check yourself
Hvad skal en fremmednøgle (foreign key) bruges til i en database?