Tabelas, linhas e chaves
O que você vai aprender
- diferenciar tabelas, linhas e colunas e explicar por que cada linha precisa de uma chave primária (normalmente
id) - encontrar conexões entre tabelas por meio de uma chave estrangeira:
orders.user_id → users.id - diferenciar uma chave substituta (
IDENTITY, ) de uma chave natural (email, ISBN) e justificar por que uma chave primária não deve mudar - garantir a unicidade de um campo como
emailcom uma restriçãoUNIQUE, sem transformá-lo em chave primária
O índice está aberto. QUERY desdobra um holograma sobre a mesa de trabalho: milhares de registros pairam no ar em uma grade regular, e fios finos de luz âmbar correm entre alguns deles. Você estende a mão para um fio — ele vibra como uma corda. Isto não é um monte de arquivos. É um tecido.
Tabelas, linhas, colunas
Um banco de dados relacional é como um catálogo bem-organizado: os dados ficam distribuídos em tabelas, e dentro de cada tabela há colunas (as propriedades que guardamos) e linhas (os registros individuais).
Pegue a tabela de compradores users: cada linha é um comprador da velha Terra, e as colunas descrevem seu id, full_name, email, country, city, signup_date.
Para não confundir pessoas com o mesmo nome, cada linha tem uma chave primária () — um identificador único, normalmente a coluna id. Por meio dela, outras tabelas conseguem apontar para essa linha usando uma chave estrangeira (). Por exemplo, um pedido em orders tem um user_id — é assim que o pedido se lembra de quem comprou. Aqueles fios âmbar no holograma são exatamente essas conexões por chaves.
QUERY: Enquanto a chave estiver intacta, o fio está intacto. Um século e meio depois, cada pedido ainda sabe de quem é.
Execute a consulta e veja como são os compradores do «Kotomarket» — registros que ninguém abria desde os tempos da velha Rede:

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 |
Uma chave primária permite localizar uma única linha sem ambiguidade (normalmente id). Uma chave estrangeira conecta tabelas: por exemplo, orders.user_id → users.id mostra de quem é o pedido. A seguir, QUERY vai desdobrar diante de você o mapa inteiro do instantâneo — as cinco tabelas completas.
orders.user_id referencia a chave primária users.id — é assim que um pedido se lembra do seu comprador.Chave natural ou substituta
De onde vem uma chave primária? Há dois caminhos. Uma chave natural é um atributo real que já é único: o email de um comprador, o ISBN de um livro, um código de moeda. Uma chave substituta é um identificador artificial, sem significado no mundo externo: uma autonumeração ou um . No «Kotomarket», usam-se id substitutos em tudo — uma escolha clássica:
-- Chave substituta: o banco mesmo entrega o próximo número (PostgreSQL)
CREATE TABLE users (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
email TEXT NOT NULL UNIQUE, -- o candidato natural vive ao lado como UNIQUE
full_name TEXT NOT NULL
);
Por quê? Porque a propriedade fundamental de uma chave primária é: ela não deve mudar. As chaves estrangeiras de outras tabelas apontam para a PK, e alterar esse valor obrigaria a atualizar todos os fios de uma vez — em orders, em events, em todo lugar. E atributos naturais «eternos» quase não existem: as pessoas mudam de email e de sobrenome, números de telefone são reaproveitados, até ISBNs são reeditados. Um id substituto nunca muda — justamente porque não significa nada.
Requisitos para qualquer chave primária: única, não NULL, estável. Deixe as chaves naturais para tabelas de referência pequenas e imutáveis — o código de moeda 'RUB' da ISO 4217, por exemplo. E a unicidade de um candidato natural como email você garante com uma restrição UNIQUE à parte, como no exemplo acima: as conexões se mantêm, os dados continuam consistentes, e o comprador ainda pode trocar de email.
Adiantando: a sintaxe para criar tabelas e restrições (CREATE TABLE, PRIMARY KEY, UNIQUE) é tema do Capítulo 9. Aqui, observe a estrutura da chave, não o comando: um id substituto virou a chave primária, enquanto o email fica ao lado como UNIQUE.
Interview question
Pergunta de entrevista: qual é a diferença entre uma chave substituta e uma natural, e qual você escolheria para uma tabela de usuários?
Resposta forte: a natural é um atributo real e único (email, ISBN); a substituta é um identificador artificial (uma coluna IDENTITY ou um ). Para usuários, eu escolheria a substituta: uma chave primária não deve mudar, porque as chaves estrangeiras a referenciam, e as pessoas mudam de email. A unicidade do email, nesse caso, é garantida por uma restrição UNIQUE à parte. Uma chave natural se justifica em tabelas de referência estáveis, como os códigos de moeda da ISO 4217.