Bazele de date, fără mistere

Tabele, rânduri și chei

11 min
What you'll learn
  • să deosebești tabelele, rândurile și coloanele și să explici de ce fiecare rând are nevoie de o cheie primară (de obicei id)
  • să găsești legăturile dintre tabele după cheia externă: orders.user_id → users.id
  • să deosebești o cheie surogat (IDENTITY, ) de una naturală (email, ISBN) și să argumentezi de ce o cheie primară nu trebuie să se schimbe
  • să fixezi unicitatea unui câmp precum email cu o restricție UNIQUE, fără să-l transformi în cheie primară

Inventarul e deschis. QUERY desfășoară pe birou o hologramă: mii de înregistrări plutesc în aer într-o rețea ordonată, iar între unele se întind fire subțiri, chihlimbarii. Atingi unul și sună ca o coardă. Nu e un morman de fișiere. E o țesătură.

Tabele, rânduri, coloane

O bază de date relațională seamănă cu un catalog bine îngrijit: datele sunt așezate în tabele, iar fiecare tabel are coloane (ce proprietăți păstrăm) și rânduri (înregistrările concrete).

Ia tabelul cumpărătorilor users: fiecare rând este un cumpărător al vechiului Pământ, iar coloanele descriu id, full_name, email, country, city, signup_date.

Ca să nu încurci oamenii cu nume identice, fiecare rând are o cheie primară () — un identificator unic, de obicei coloana id. Prin ea, alte tabele pot trimite la acest rând cu ajutorul unei chei externe (). De exemplu, în comanda orders există user_id — așa își ține minte comanda cumpărătorul. Firele chihlimbarii de pe hologramă sunt tocmai legăturile prin chei.

QUERY: Cât timp cheia e întreagă, și firul rămâne întreg. A trecut un secol și jumătate, iar fiecare comandă încă își ține minte omul.

Rulează interogarea și vezi cum arată cumpărătorii „Kotomarket” — înregistrări pe care nu le-a mai deschis nimeni din vremea vechii Rețele:

Tabel holografic format din rânduri-capsule și coloane; de la înregistrările comenzilor către înregistrările oamenilor se întind firele-cheie chihlimbarii
Rândurile sunt înregistrări, coloanele sunt proprietățile lor, iar firul de la o comandă la cumpărător este o legătură prin cheie.

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:

Primii cumpărători „Kotomarket” din tabel:
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

Cheia primară ajută să găsești fără greș un singur rând (de obicei id). Cheia externă leagă tabelele: de exemplu, orders.user_id → users.id arată a cui este comanda. Mai departe, QUERY va desfășura în fața ta toată harta copiei de arhivă — cele cinci tabele, complet.

usersidfull_namecityordersiduser_idstatususer_id → id
Cheia externă orders.user_id face referință la cheia primară users.id — așa își ține minte comanda cumpărătorul.

Cheie naturală sau surogat

De unde vine cheia primară? Există două variante. Cheia naturală este un atribut real care este oricum unic: emailul cumpărătorului, ISBN-ul unei cărți, codul monedei. Cheia surogat este un identificator artificial, fără sens în lumea exterioară: o autonumerotare sau un . În „Kotomarket” se folosesc peste tot id-uri surogat — și aceasta este o soluție tipică:

-- Cheie surogat: baza emite singură următorul număr (PostgreSQL)
CREATE TABLE users (
  id        BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  email     TEXT NOT NULL UNIQUE,  -- candidatul natural trăiește alături ca UNIQUE
  full_name TEXT NOT NULL
);

De ce așa? Proprietatea esențială a cheii primare este că ea nu trebuie să se schimbe. Cheile externe din alte tabele trimit la PK, iar schimbarea valorii ar cere actualizarea tuturor firelor deodată — în orders, în events, peste tot. În plus, atribute naturale „veșnice” aproape că nu există: oamenii își schimbă emailul și numele, telefoanele se reatribuie, până și ISBN-urile se reeditează. Un id surogat nu se schimbă niciodată tocmai fiindcă nu înseamnă nimic.

Cerințele pentru orice cheie primară: să fie unică, să nu fie NULL, să fie stabilă. Păstrează cheile naturale pentru micile tabele de referință care nu se schimbă — de exemplu, codul monedei 'RUB' din standardul ISO 4217. Iar unicitatea unui candidat natural precum email fixeaz-o cu o restricție UNIQUE separată, ca în exemplul de mai sus: legăturile se păstrează, datele rămân corecte, iar cumpărătorului nu îi interzici să-și schimbe emailul.

Notă pentru mai târziu: sintaxa propriu-zisă pentru crearea tabelelor și a restricțiilor (CREATE TABLE, PRIMARY KEY, UNIQUE) este tema Capitolului 9. Aici uită-te la structura cheii, nu la comandă: la faptul că un id surogat a devenit cheie primară, iar email trăiește alături ca UNIQUE.

Interview question

Întrebare de interviu: prin ce se deosebește o cheie surogat de una naturală și pe care o vei alege pentru un tabel de utilizatori?

Răspuns puternic: cheia naturală este un atribut real, unic (email, ISBN), iar cheia surogat este un identificator artificial (o coloană IDENTITY sau un ). Pentru utilizatori aleg surogat: cheia primară nu trebuie să se schimbe, fiindcă la ea trimit cheile externe, iar oamenii își schimbă emailul. Unicitatea emailului se fixează separat, cu o restricție UNIQUE. O cheie naturală este justificată în tabele de referință stabile, precum codurile valutare ISO 4217.

Check yourself
La ce folosește o cheie externă (foreign key) într-o bază?