Databases demystified

Relational model

11 min
What you'll learn
  • tell tables, rows, and columns apart and explain why every row needs a (usually id)
  • find the links between tables through a : orders.user_id → users.id
  • tell a surrogate key (IDENTITY, ) from a natural one (email, ISBN) and justify why a primary key must not change
  • lock down the uniqueness of a field like email with a UNIQUE , without making it the primary key

The index is open. QUERY unfolds a hologram above the desk: thousands of records hang in the air in a neat grid, and thin amber threads run between some of them. You reach for one — it rings like a string. This isn’t a pile of files. It’s a fabric.

A holographic table of capsule-rows and columns; amber key-threads run from order records to people records
Rows are records, columns are their properties, and the thread from an order to its buyer is a key-based link.

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:

Kotomarket’s first buyers, straight from the table:
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

A lets you pinpoint a single row without error (usually id). A links tables: for example, orders.user_id → users.id shows whose order it is. Next, QUERY will unfold the whole map of the for you — all five tables.

usersidfull_namecityordersiduser_idstatususer_id → id
The foreign key orders.user_id references the primary key users.id — that’s how an order remembers its buyer.

Natural or surrogate key

Where does a come from? There are two paths. A natural key is a real attribute that’s already unique: a buyer’s email, a book’s ISBN, a currency code. A surrogate key is an artificial identifier with no meaning in the outside world: an auto-number or a . Kotomarket uses surrogate id values everywhere — and that’s a textbook choice:

-- Surrogate key: the database hands out the next number itself (PostgreSQL)
CREATE TABLE users (
  id        BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  email     TEXT NOT NULL UNIQUE,  -- the natural candidate lives alongside it as UNIQUE
  full_name TEXT NOT NULL
);

Why this way? The cardinal property of a primary key: it must not change. Foreign keys in other tables point at the PK, and changing its value would drag along an update of every thread at once — in orders, in events, everywhere. And "eternal" natural attributes barely exist: people change their email and surname, phone numbers get reassigned, even ISBNs get reissued. A surrogate id never changes — precisely because it means nothing.

Requirements for any primary key: unique, not NULL, stable. Save natural keys for small, immutable reference tables — the currency code 'RUB' from ISO 4217, say. And the uniqueness of a natural candidate like email you pin down with a separate UNIQUE , as in the example above: the links hold, the data stays honest, and the buyer is still free to change their email.

Looking ahead: the actual syntax for creating tables and (CREATE TABLE, PRIMARY KEY, UNIQUE) is the subject of Chapter 9. Here, look at the structure of the key rather than the command: that a surrogate id became the , while email lives alongside it as UNIQUE.

Interview question

Interview question: how does a surrogate key differ from a natural one, and which would you choose for a users table?

Strong answer: a natural key is a real unique attribute (email, ISBN); a surrogate key is an artificial identifier (an IDENTITY column or a ). For users — surrogate: a must not change because foreign keys reference it, and people change their email. The uniqueness of the email is then pinned down by a separate UNIQUE . A natural key is justified in stable reference tables like ISO 4217 currency codes.

Check yourself
What is a foreign key for in a database?