Tabelle, righe e chiavi
What you'll learn
- a distinguere tabelle, righe e colonne e a spiegare perché ogni riga ha bisogno di una chiave primaria (di solito
id) - a trovare i collegamenti tra le tabelle tramite una chiave esterna:
orders.user_id → users.id - a distinguere una chiave surrogata (
IDENTITY, ) da una naturale (email, ISBN) e a motivare perché una chiave primaria non deve cambiare - a fissare l'unicità di un campo come
emailcon un vincoloUNIQUE, senza renderlo la chiave primaria
L'inventario è aperto. QUERY dispiega sopra la scrivania un ologramma: migliaia di record sospesi in aria formano una griglia regolare, e tra alcuni di essi corrono sottili fili ambrati. Allunghi la mano verso uno di quei fili: vibra come una corda. Questo non è un mucchio di file. È un tessuto.
Tabelle, righe, colonne
Un database relazionale somiglia a un catalogo ordinato: i dati sono disposti in tabelle, e dentro ogni tabella ci sono colonne (le proprietà che conserviamo) e righe (i singoli record).
Prendi la tabella dei clienti users: ogni riga è un cliente della vecchia Terra, e le colonne ne descrivono id, full_name, email, country, city, signup_date.
Per non confondere persone con lo stesso nome, ogni riga ha una chiave primaria (): un identificatore univoco, di solito la colonna id. Tramite questa chiave, altre tabelle possono fare riferimento alla riga usando una chiave esterna (). Per esempio, un ordine in orders ha un user_id: così l'ordine ricorda il proprio cliente. Quei fili ambrati nell'ologramma sono proprio i collegamenti tramite chiavi.
QUERY: Finché la chiave regge, il filo regge. È passato un secolo e mezzo, eppure ogni ordine ricorda ancora la sua persona.
Esegui la query e guarda che aspetto hanno i clienti di Kotomarket: record che nessuno apriva dai tempi della vecchia Rete.

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:
| id | full_name | city | signup_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 |
La chiave primaria ti aiuta a trovare senza errori una singola riga (di solito id). La chiave esterna collega le tabelle: per esempio, orders.user_id → users.id mostra di chi è quell'ordine. Più avanti QUERY dispiegherà davanti a te l'intera mappa dello : tutte e cinque le tabelle.
orders.user_id fa riferimento alla chiave primaria users.id: così l'ordine ricorda il proprio cliente.Chiave naturale o surrogata
Da dove arriva una chiave primaria? Ci sono due strade. Una chiave naturale è un attributo reale che è già univoco: l'email del cliente, l'ISBN di un libro, un codice valuta. Una chiave surrogata è un identificatore artificiale senza significato nel mondo esterno: una numerazione automatica o un . In Kotomarket si usano ovunque degli id surrogati, ed è una scelta da manuale:
-- Chiave surrogata: il database assegna da sé il numero successivo (PostgreSQL)
CREATE TABLE users (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
email TEXT NOT NULL UNIQUE, -- il candidato naturale vive accanto come UNIQUE
full_name TEXT NOT NULL
);
Perché così? La proprietà fondamentale di una chiave primaria è questa: non deve cambiare. Sulla PK puntano le chiavi esterne di altre tabelle, e cambiarne il valore obbligherebbe ad aggiornare tutti i fili in una volta sola: in orders, in events, ovunque. Inoltre gli attributi naturali davvero «eterni» sono rarissimi: le persone cambiano email e cognome, i numeri di telefono vengono riassegnati, perfino gli ISBN possono essere ristampati. Un id surrogato non cambia mai, proprio perché non significa nulla.
I requisiti di qualsiasi chiave primaria: univoca, non NULL, stabile. Lascia le chiavi naturali alle piccole tabelle di riferimento immutabili, per esempio il codice valuta 'RUB' della ISO 4217. E l'unicità di un candidato naturale come email fissala con un vincolo UNIQUE separato, come nell'esempio qui sopra: i collegamenti restano stabili, i dati restano corretti, e al cliente non viene impedito di cambiare email.
Anticipiamo un po': la sintassi vera e propria per creare tabelle e vincoli (CREATE TABLE, PRIMARY KEY, UNIQUE) è argomento del Capitolo 9. Qui osserva la struttura della chiave, non il comando: un id surrogato è diventato la chiave primaria, mentre email vive accanto come UNIQUE.
Interview question
Domanda da colloquio: qual è la differenza tra una chiave surrogata e una naturale, e quale sceglieresti per una tabella di utenti?
Risposta efficace: la chiave naturale è un attributo reale e univoco (email, ISBN), la surrogata è un identificatore artificiale (una colonna IDENTITY o un ). Per gli utenti sceglierei una surrogata: una chiave primaria non deve cambiare, perché su di essa puntano le chiavi esterne, e le persone possono cambiare email. L'unicità dell'email, invece, si fissa con un vincolo UNIQUE separato. Una chiave naturale ha senso in tabelle di riferimento stabili, come i codici valuta ISO 4217.