O esquema do «Kotomarket»
O que você vai aprender
- encontrar a tabela certa entre as cinco do «Kotomarket»:
users,products,orders,order_items,events - ler um diagrama ER: determinar a cardinalidade de uma conexão (1:N, N:M, 1:1) pela posição da chave estrangeira
- decompor uma conexão «muitos para muitos» usando uma tabela intermediária com duas FK — como
order_itemscomorder_id+product_id - explicar por que o conteúdo de um pedido não deve ser guardado como uma string de ids dentro de
orders
Hoje QUERY traz para a mesa principal o índice inteiro de uma só vez. Cinco planos luminosos pairam no ar, girando devagar — um mapa do mundo que sobreviveu. Ao lado, cintila o registro de conservação anexado ao instantâneo, com uma linha sublinhada: «Entrego cinco tabelas e o rastro de uma sexta. — K.» Você conta os planos. Exatamente cinco. Onde está o rastro?
QUERY: Não se distraia com rastros. Primeiro aprenda estas cinco bem o bastante para encontrar o caminho de olhos fechados — o resto o arquivo mostra quando te julgar pronto.
As cinco tabelas do «Kotomarket»
Daqui em diante, vamos trabalhar com este banco — um instantâneo de uma loja virtual de 2024. Use-o como um mapa da loja: quem entrou, o que estava na vitrine, o que foi comprado e quais ações aconteceram antes da compra.
| Tabela | O que guarda |
|---|---|
users | compradores: id, nome, cidade e data de cadastro |
products | itens da vitrine: id, nome, categoria, preço e estoque |
orders | pedidos: id, user_id, data, status e total |
order_items | conteúdo dos pedidos: qual produto, quantas unidades e a que preço |
events | eventos comportamentais: visualizações, adições ao carrinho e compras |
As conexões são lidas assim: um user → muitos orders; um order → muitos order_items; um product → muitos order_items. Se você se perder, abra o esquema à direita — ele é como a planta do salão de vendas.
Vamos espiar a tabela de pedidos: em cada linha há um user_id — uma referência ao comprador. É assim que uma tabela se conecta a outra, e o mapa deixa de ser cinco ilhas separadas.

Kotomarket’s five tables
From here on we’ll be working with this database — a of an online shop from 2024. Hold it like a map of the store: who walked in, what’s on the shelves, what they bought, and what they did before buying.
| Table | What it holds |
|---|---|
users | buyers: id, name, city, and signup date |
products | storefront items: id, name, category, price, and stock |
orders | orders: id, user_id, date, status, and total |
order_items | order contents: which product, how many, and at what price |
events | behavioral events: views, add-to-carts, and purchases |
The links read like this: one user → many orders; one order → many order_items; one product → many order_items. If you get lost, open the schema on the right — it’s like the floor plan of the shop.
Let’s peek into the orders table: every row has a user_id — a reference to a buyer. That’s how one table links to another, and the map stops being five separate islands.
user_id:| id | user_id | status | total_amount |
|---|---|---|---|
| 1 | 18 | paid | 5980.00 |
| 2 | 10 | paid | 19750.00 |
| 3 | 26 | cancelled | 9560.00 |
| 4 | 26 | paid | 15530.00 |
| 5 | 8 | paid | 26710.00 |
| 6 | 37 | paid | 42110.00 |
Como ler um diagrama ER
O mapa que QUERY desdobrou é o que a indústria chama de diagrama ER (entity–relationship): os retângulos são tabelas, as linhas entre eles são conexões por chaves estrangeiras. O mais importante em uma linha é a cardinalidade: quantas linhas de um lado correspondem a quantas do outro.
- 1:N, um para muitos — a conexão mais comum. Um comprador, muitos pedidos. A chave estrangeira sempre fica do lado dos «muitos»: o
user_idé guardado emorders, e não o contrário. Esta é a regra de leitura: achou a FK, achou o lado N. - N:M, muitos para muitos — um pedido tem muitos produtos, e um produto aparece em muitos pedidos. Uma conexão assim não pode ser representada diretamente em um banco relacional: não há onde colocar a chave estrangeira. Ela é decomposta em uma tabela intermediária — no nosso caso,
order_items. Cada linha dela carrega um par de referências,order_id+product_id, e transforma uma única conexão N:M em duas conexões 1:N. De quebra, a própria conexão ganha atributos — a quantidade de unidades e o preço no momento da compra. - 1:1, um para um — mais raro: campos pesados ou privados, por exemplo, são movidos para uma tabela separada com a mesma chave.
-- A resolução N:M em ação: pares «pedido — produto» de order_items
SELECT order_id, product_id, quantity
FROM order_items
LIMIT 6;
Pegadinha: guardar o conteúdo de um pedido direto em orders — como uma string '7,12,3' ou um array de identificadores. Não dá para proteger esses dados com uma chave estrangeira, contá-los de forma confiável nem juntá-los com a vitrine sem acrobacias. Viu uma conexão «muitos para muitos» — crie uma tabela intermediária com duas chaves estrangeiras, como order_items.
Interview question
Pergunta de entrevista: como implementar uma conexão «muitos para muitos» em um banco relacional?
Resposta forte: por meio de uma tabela intermediária com duas chaves estrangeiras para as tabelas conectadas — como order_items com order_id e product_id: ela transforma N:M em duas conexões 1:N. De quebra, guarda atributos da própria conexão — quantidade, preço no momento da compra. A chave primária dessa tabela pode ser composta pelas duas FK ou ser um id substituto.