Bazy danych bez tajemnic

Tabele, wiersze i klucze

11 min
What you'll learn
  • odróżniać tabele, wiersze i kolumny oraz wyjaśniać, po co każdemu wierszowi klucz główny (zwykle id)
  • znajdować powiązania między tabelami po kluczu obcym: orders.user_id → users.id
  • odróżniać klucz sztuczny (IDENTITY, ) od naturalnego (email, ISBN) i uzasadniać, dlaczego klucz główny nie powinien się zmieniać
  • wymuszać unikalność pola takiego jak email ograniczeniem UNIQUE, bez robienia z niego klucza głównego

Inwentarz otwarty. QUERY rozwija nad biurkiem hologram: tysiące rekordów zawisają w powietrzu równą siatką, a między niektórymi ciągną się cienkie bursztynowe nici. Dotykasz jednej — dźwięczy jak struna. To nie sterta plików. To splot.

Tabele, wiersze, kolumny

Baza relacyjna przypomina porządny katalog: dane są rozłożone na tabele, a wewnątrz każdej tabeli są kolumny (jakie właściwości przechowujemy) i wiersze (konkretne rekordy).

Weź tabelę kupujących users: każdy wiersz to jeden kupujący ze starej Ziemi, a kolumny opisują jego id, full_name, email, country, city, signup_date.

Żeby nie mylić ludzi o tych samych imionach, każdy wiersz ma klucz główny () — unikalny identyfikator, zwykle kolumnę id. Dzięki niemu inne tabele mogą odwoływać się do tego wiersza za pomocą klucza obcego (). Na przykład w zamówieniu orders jest user_id — tak zamówienie pamięta swojego kupującego. Bursztynowe nici na hologramie to właśnie powiązania po kluczach.

QUERY: Dopóki klucz jest cały, nić też trzyma. Minęło półtora wieku, a każde zamówienie wciąż pamięta swojego człowieka.

Uruchom zapytanie i zobacz, jak wyglądają kupujący „Kotomarketu” — rekordy, których nikt nie otwierał od czasów starej Sieci:

Holograficzna tabela z wierszy-kapsuł i kolumn; od rekordów zamówień do rekordów ludzi ciągną się bursztynowe nici kluczy
Wiersze to rekordy, kolumny to ich właściwości, a nić od zamówienia do kupującego to powiązanie po kluczu.

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:

Pierwsi kupujący „Kotomarketu” w tabeli:
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

Klucz główny pomaga bezbłędnie znaleźć jeden wiersz (zwykle id). Klucz obcy łączy tabele: na przykład orders.user_id → users.id pokazuje, do kogo należy zamówienie. Dalej QUERY rozwinie przed tobą całą mapę migawki — wszystkie pięć tabel.

usersidfull_namecityordersiduser_idstatususer_id → id
Klucz obcy orders.user_id odwołuje się do klucza głównego users.id — tak zamówienie pamięta swojego kupującego.

Klucz naturalny czy sztuczny

Skąd bierze się klucz główny? Są dwie drogi. Klucz naturalny to rzeczywisty atrybut, który i tak jest unikalny: email kupującego, ISBN książki, kod waluty. Klucz sztuczny to identyfikator wymyślony, bez znaczenia poza bazą: numer generowany automatycznie albo . W „Kotomarkecie” wszędzie używane są sztuczne id — i to typowe rozwiązanie:

-- Klucz sztuczny: baza sama wydaje kolejny numer (PostgreSQL)
CREATE TABLE users (
  id        BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  email     TEXT NOT NULL UNIQUE,  -- naturalny kandydat żyje obok jako UNIQUE
  full_name TEXT NOT NULL
);

Dlaczego tak? Najważniejsza właściwość klucza głównego: nie powinien się zmieniać. Do PK odwołują się klucze obce innych tabel, a zmiana wartości pociągnęłaby za sobą aktualizację wszystkich nici naraz — w orders, w events, wszędzie. A „wiecznych” atrybutów naturalnych prawie nie ma: ludzie zmieniają email i nazwiska, telefony przechodzą do kogoś innego, nawet ISBN bywa wznawiany. Sztuczne id nie zmienia się nigdy — właśnie dlatego, że nic nie znaczy.

Wymagania wobec każdego klucza głównego: unikalny, nie NULL, stabilny. Klucze naturalne zostaw niewielkim, stabilnym słownikom — na przykład kodowi waluty 'RUB' z ISO 4217. A unikalność naturalnego kandydata takiego jak email utrwal osobnym ograniczeniem UNIQUE, jak w przykładzie powyżej: powiązania zostają zachowane, dane pozostają rzetelne, a zmiana adresu e-mail kupującego nie jest zabroniona.

Na później: sama składnia tworzenia tabel i ograniczeń (CREATE TABLE, PRIMARY KEY, UNIQUE) to temat Rozdziału 9. Tutaj patrz na strukturę klucza, a nie na polecenie: sztuczne id stało się kluczem głównym, a email żyje obok jako UNIQUE.

Interview question

Pytanie z rozmowy kwalifikacyjnej: czym klucz sztuczny różni się od naturalnego i który wybierzesz dla tabeli użytkowników?

Mocna odpowiedź: naturalny — rzeczywisty unikalny atrybut (email, ISBN), sztuczny — wymyślony identyfikator (kolumna IDENTITY albo ). Dla użytkowników wybiorę sztuczny: klucz główny nie powinien się zmieniać, bo odwołują się do niego klucze obce, a email ludzie zmieniają. Unikalność emaila utrwala się przy tym osobnym ograniczeniem UNIQUE. Klucz naturalny ma sens w stabilnych słownikach, takich jak kody walut ISO 4217.

Check yourself
Po co w bazie potrzebny jest klucz obcy (foreign key)?