Duomenų bazės be miglos

Lentelės, eilutės ir raktai

11 min
What you'll learn
  • atskirti lenteles, eilutes ir stulpelius ir paaiškinti, kam kiekvienai eilutei reikia pirminio rakto (paprastai id)
  • rasti ryšius tarp lentelių pagal išorinį raktą: orders.user_id → users.id
  • atskirti surogatinį raktą (IDENTITY, ) nuo natūralaus (email, ISBN) ir pagrįsti, kodėl pirminis raktas neturi keistis
  • įtvirtinti lauko, tokio kaip email, unikalumą apribojimu UNIQUE, nedarant jo pirminiu raktu

Aprašas atvertas. QUERY virš darbo stalo išskleidžia hologramą: tūkstančiai įrašų pakimba ore tolygiu tinkleliu, o tarp kai kurių driekiasi plonos gintarinės gijos. Tu tiesi ranką prie vienos — ji suskamba it styga. Tai ne krūva failų. Tai audinys.

Lentelės, eilutės, stulpeliai

Reliacinė bazė panaši į tvarkingą katalogą: duomenys sudėlioti po lenteles, o kiekvienoje lentelėje yra stulpeliai (kokias savybes saugome) ir eilutės (konkretūs įrašai).

Paimk pirkėjų lentelę users: kiekviena eilutė — vienas senosios Žemės pirkėjas, o stulpeliai aprašo jo id, full_name, email, country, city, signup_date.

Kad nesupainiotum žmonių vienodais vardais, kiekviena eilutė turi pirminį raktą () — unikalų identifikatorių, paprastai stulpelį id. Per jį kitos lentelės gali nurodyti šią eilutę naudodamos išorinį raktą (). Pavyzdžiui, užsakyme orders yra user_id — taip užsakymas atsimena savo pirkėją. Tos pačios gintarinės gijos hologramoje — tai ir yra ryšiai per raktus.

QUERY: Kol sveikas raktas — sveika ir gija. Pusantro amžiaus praėjo, o kiekvienas užsakymas vis dar atsimena savo žmogų.

Paleisk užklausą ir pažiūrėk, kaip atrodo „Kotomarket“ pirkėjai — įrašai, kurių niekas neatvėrė nuo senojo Tinklo laikų:

Holografinė lentelė iš eilučių-kapsulių ir stulpelių; nuo užsakymų įrašų prie žmonių įrašų driekiasi gintarinės raktų gijos
Eilutės — įrašai, stulpeliai — jų savybės, o gija nuo užsakymo prie pirkėjo — ryšys per raktą.

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:

Pirmieji „Kotomarket“ pirkėjai lentelėje:
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

Pirminis raktas padeda nepaklystant rasti vieną eilutę (paprastai id). Išorinis raktas sieja lenteles: pavyzdžiui, orders.user_id → users.id parodo, kieno tai užsakymas. Toliau QUERY išskleis prieš tave visą kopijos žemėlapį — penkias lenteles iš eilės.

usersidfull_namecityordersiduser_idstatususer_id → id
Išorinis raktas orders.user_id nurodo į pirminį raktą users.id — taip užsakymas atsimena savo pirkėją.

Natūralus ar surogatinis raktas

Iš kur atsiranda pirminis raktas? Keliai du. Natūralus raktas — realus atributas, kuris ir taip unikalus: pirkėjo email, knygos ISBN, valiutos kodas. Surogatinis raktas — dirbtinis identifikatorius, neturintis prasmės išoriniame pasaulyje: automatinė numeracija arba . „Kotomarket“ visur naudojami surogatiniai id — ir tai tipinis sprendimas:

-- Surogatinis raktas: bazė pati išduoda kitą numerį (PostgreSQL)
CREATE TABLE users (
  id        BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  email     TEXT NOT NULL UNIQUE,  -- natūralus kandidatas gyvena šalia kaip UNIQUE
  full_name TEXT NOT NULL
);

Kodėl taip? Svarbiausia pirminio rakto savybė: jis neturi keistis. Į PK nurodo kitų lentelių išoriniai raktai, ir reikšmės keitimas iškart už savęs nutemptų visų gijų atnaujinimą — orders, events, visur. O „amžinų“ natūralių atributų beveik nebūna: žmonės keičia email ir pavardes, telefonai persikelia, net ISBN perleidžiami. Surogatinis id nesikeičia niekada — būtent todėl, kad nieko nereiškia.

Reikalavimai bet kuriam pirminiam raktui: unikalus, ne NULL, stabilus. Natūralius raktus palik mažiems nekintamiems žinynams — pavyzdžiui, valiutos kodui 'RUB' iš ISO 4217. O natūralaus kandidato, tokio kaip email, unikalumą įtvirtink atskiru apribojimu UNIQUE, kaip pavyzdyje aukščiau: ryšiai išlieka, duomenys lieka sąžiningi, ir keisti pirkėjui pašto nedraudžiama.

Užbėgame į priekį: pats lentelių ir apribojimų kūrimo sintaksis (CREATE TABLE, PRIMARY KEY, UNIQUE) — 9 skyriaus tema. Čia žiūrėk į rakto struktūrą, o ne į komandą: kad surogatinis id tapo pirminiu raktu, o email gyvena šalia kaip UNIQUE.

Interview question

Klausimas iš pokalbio: kuo surogatinis raktas skiriasi nuo natūralaus ir kurį pasirinksi naudotojų lentelei?

Stiprus atsakymas: natūralus — realus unikalus atributas (email, ISBN), surogatinis — dirbtinis identifikatorius (IDENTITY stulpelis arba ). Naudotojams — surogatinis: pirminis raktas neturi keistis, nes į jį nurodo išoriniai raktai, o email žmonės keičia. Email unikalumas tuo metu įtvirtinamas atskiru UNIQUE apribojimu. Natūralus raktas pateisinamas stabiliuose žinynuose kaip ISO 4217 valiutų kodai.

Check yourself
Kam bazėje reikalingas išorinis raktas (foreign key)?