Hoje a gente vai se aprofundar num tema super importante: modelagem de relações entre tabelas. Afinal, normalização não é só sobre dados atômicos e tirar redundância, mas também sobre criar as relações certas entre as tabelas.
Se banco de dados é um sistema organizado pra guardar informação, as relações entre tabelas são tipo as pontes lógicas que mostram como os dados se conectam. Imagina uma biblioteca, onde as infos dos livros ficam separadas das infos dos autores, mas cada livro "sabe" quem é o autor por uma relação especial. Ou pensa num e-commerce: os dados dos produtos existem separados dos dados dos clientes, mas quando alguém faz um pedido, o sistema liga o cliente aos produtos pelo meio da tabela de pedidos.
Num consultório médico, pacientes estão ligados aos seus prontuários, médicos ao horário de atendimento, e remédios às prescrições. Essas relações ajudam o sistema a entender o que pertence a quê, sem ficar duplicando informação à toa.
Os tipos principais dessas relações funcionam igual na vida real: passaporte pertence só a uma pessoa (um-para-um), um professor pode dar várias disciplinas (um-para-muitos), e estudantes podem se inscrever em várias matérias, enquanto cada matéria tem vários estudantes (muitos-para-muitos).
Um-para-um (1:1)
Essa é a relação onde um registro na tabela "A" corresponde exatamente a um registro na tabela "B". Por exemplo, temos as tabelas "Funcionários" e "Dados do Passaporte". Um funcionário só pode ter um passaporte, e cada passaporte pertence a um único funcionário.
Exemplo:
Funcionários
| id | nome | cargo |
|---|---|---|
| 1 | Otto Lin | gerente |
Dados do Passaporte
| id | funcionario_id | número do passaporte |
|---|---|---|
| 1 | 1 | 123456789 |
Aqui a relação rola pelo foreign key funcionario_id, que aponta pro id na tabela "Funcionários".
Um-para-muitos (1:N)
Esse é o tipo de relação mais comum. Aqui cada registro da tabela "A" pode estar ligado a vários registros da tabela "B", mas cada registro da "B" só está ligado a um da "A". Por exemplo, temos as tabelas "Professores" e "Cursos". Um professor pode dar várias disciplinas.
Exemplo:
Professores
| id | nome |
|---|---|
| 1 | Anna Song |
| 2 | Alex Min |
Cursos
| id | nome do curso | professor_id |
|---|---|---|
| 1 | Fundamentos de SQL | 1 |
| 2 | Administração de DB | 1 |
| 3 | Programação em Python | 2 |
A relação é feita pelo foreign key professor_id na tabela "Cursos".
Muitos-para-muitos (M:N)
Quando tem muita coisa pra todo lado, é divertido mas dá trabalho. Aqui cada registro na tabela "A" pode estar ligado a vários registros da "B", e vice-versa. Por exemplo, estudantes podem se inscrever em vários cursos, e cada curso pode ter vários estudantes.
Exemplo:
Estudantes
| id | nome |
|---|---|
| 1 | Otto Lin |
| 2 | Maria Chi |
Cursos
| id | nome do curso |
|---|---|
| 1 | Fundamentos de SQL |
| 2 | Administração de DB |
Pra ligar tudo, a gente precisa de uma tabela intermediária, que vai guardar as ligações entre estudantes e cursos:
Matrículas
| id | estudante_id | curso_id |
|---|---|---|
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 2 | 1 |
Modelando relações usando foreign keys
Foreign key é aquela coluna (ou conjunto de colunas) que aponta pra uma coluna de primary key em outra tabela. É a base pra criar relações entre tabelas.
Exemplo de foreign key:
CREATE TABLE Cursos (
id SERIAL PRIMARY KEY,
nome VARCHAR(255)
);
CREATE TABLE Matrículas (
id SERIAL PRIMARY KEY,
estudante_id INT,
curso_id INT,
FOREIGN KEY (curso_id) REFERENCES Cursos(id)
);
Como evitar erro na hora de criar foreign key? Primeiro, confere se os tipos de dados das colunas batem certinho — senão o banco nem deixa criar a relação. E pensa antes o que deve acontecer quando apagar registros. Tipo, se você apaga uma linha da tabela mãe, o que faz com as filhas? Uma opção comum é usar ON DELETE CASCADE, assim os dados ligados são apagados junto com o principal. Isso ajuda a manter tudo em ordem e não deixar "links pendurados".
Implementando relação "Muitos-para-muitos"
Pega esse exemplo: temos estudantes e cursos. Um estudante pode estar em vários cursos, e um curso pode ter vários estudantes. Pra fazer a relação M:N, criamos três tabelas: Estudantes, Cursos e Matrículas.
CREATE TABLE Estudantes (
id SERIAL PRIMARY KEY,
nome VARCHAR(255)
);
CREATE TABLE Cursos (
id SERIAL PRIMARY KEY,
nome VARCHAR(255)
);
CREATE TABLE Matrículas (
id SERIAL PRIMARY KEY,
estudante_id INT,
curso_id INT,
FOREIGN KEY (estudante_id) REFERENCES Estudantes(id),
FOREIGN KEY (curso_id) REFERENCES Cursos(id)
);
Agora dá pra adicionar registros na tabela Matrículas pra ligar estudantes e cursos.
Exercício prático
Cria aí a estrutura de banco pra um sistema de gestão de cursos. Você vai precisar das tabelas Estudantes, Cursos e Matrículas. Faz todas as relações entre elas. Depois coloca uns dados de exemplo de estudantes, cursos e matrículas. Bora ver como faz isso na prática.
- Cria as tabelas:
CREATE TABLE Estudantes (
id SERIAL PRIMARY KEY,
nome VARCHAR(255)
);
CREATE TABLE Cursos (
id SERIAL PRIMARY KEY,
nome VARCHAR(255)
);
CREATE TABLE Matrículas (
id SERIAL PRIMARY KEY,
estudante_id INT,
curso_id INT,
FOREIGN KEY (estudante_id) REFERENCES Estudantes(id),
FOREIGN KEY (curso_id) REFERENCES Cursos(id)
);
- Insere os dados:
INSERT INTO Estudantes (nome) VALUES ('Otto Lin'), ('Maria Chi');
INSERT INTO Cursos (nome) VALUES ('Fundamentos de SQL'), ('Administração de DB');
INSERT INTO Matrículas (estudante_id, curso_id) VALUES (1, 1), (1, 2), (2, 1);
- Confere os dados:
SELECT
Estudantes.nome AS estudante,
Cursos.nome AS curso
FROM Matrículas
JOIN Estudantes ON Matrículas.estudante_id = Estudantes.id
JOIN Cursos ON Matrículas.curso_id = Cursos.id;
Resultado:
| estudante | curso |
|---|---|
| Otto Lin | Fundamentos de SQL |
| Otto Lin | Administração de DB |
| Maria Chi | Fundamentos de SQL |
Dificuldades e detalhes de modelar relações
Quando você modela relações entre tabelas, podem rolar uns perrengues, tipo:
- Erros ao apagar dados (por exemplo, tem registros na tabela filha que dependem de um registro da tabela mãe).
- Performance das queries quando tem muito dado. Relações M:N são especialmente "pesadas", porque exigem mais joins.
Pra resolver isso, ajuda:
- Usar índices nos foreign keys
- Ter uma estrutura de banco bem pensada.
- Equilibrar normalização e performance.
A gente viu modelagem de relações entre tabelas num nível bem básico e botou em prática criando a estrutura de um sistema de cursos. Seria massa mostrar um exemplo grandão, mas não consegui pensar em como fazer isso sem ficar chato e complicado. Acho que não ia ajudar muito. Vou tentar voltar nesse assunto mais pro final do curso.
GO TO FULL VERSION