5

Relacionamentos entre Tabelas

Intermediário • 60 minutos • Conceitos importantes

Entenda como conectar tabelas usando chaves estrangeiras e como isso organiza melhor seus dados, evitando duplicação e mantendo consistência.

Objetivos de Aprendizagem

O que são Relacionamentos?

Relacionamentos conectam dados entre diferentes tabelas, evitando repetição e mantendo a organização. É como ter gavetas organizadas em vez de tudo misturado em uma caixa.

Exemplo do mundo real:

Uma loja tem clientes e pedidos. Em vez de repetir os dados do cliente em cada pedido, criamos uma tabela de clientes e conectamos os pedidos a ela.

Problema: Dados Duplicados

❌ Tabela mal projetada (com duplicação):

pedido_id cliente_nome cliente_email cliente_telefone produto
1 João Silva joao@email.com (11) 99999-9999 Notebook
2 João Silva joao@email.com (11) 99999-9999 Mouse

Problemas: dados repetidos, desperdício de espaço, difícil de manter

Solução: Tabelas Relacionadas

✅ Design correto (com relacionamento):

Tabela: clientes
id nome email
1 João Silva joao@email.com
Tabela: pedidos
id cliente_id produto
1 1 Notebook
2 1 Mouse

Vantagens: sem duplicação, fácil manutenção, dados consistentes

Chaves Estrangeiras (Foreign Keys)

Uma chave estrangeira é uma coluna que aponta para a chave primária de outra tabela. É como um "endereço" que diz onde encontrar informações relacionadas.

Conceitos importantes:

  • Chave Primária (PK): Identifica unicamente cada registro
  • Chave Estrangeira (FK): Referencia a PK de outra tabela
  • Integridade Referencial: Garante que as referências sejam válidas

Criando uma Chave Estrangeira

-- Primeiro, criar a tabela "pai" (clientes)
CREATE TABLE clientes (
    id SERIAL PRIMARY KEY,
    nome VARCHAR(100) NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL,
    telefone VARCHAR(20)
);

-- Depois, criar a tabela "filha" (pedidos)
CREATE TABLE pedidos (
    id SERIAL PRIMARY KEY,
    cliente_id INTEGER NOT NULL,
    produto VARCHAR(100) NOT NULL,
    quantidade INTEGER DEFAULT 1,
    data_pedido TIMESTAMP DEFAULT NOW(),
    
    -- Definir a chave estrangeira
    FOREIGN KEY (cliente_id) REFERENCES clientes(id)
);

🔗 Como funciona:

  • cliente_id na tabela pedidos
  • • Aponta para id na tabela clientes
  • • Garante que o cliente existe
  • • Impede exclusão de clientes com pedidos

⚠️ Regras importantes:

  • • FK deve referenciar uma PK existente
  • • Não pode inserir FK inexistente
  • • Não pode deletar PK referenciada
  • • Mantém consistência dos dados

Tipos de Relacionamentos

Existem três tipos principais de relacionamentos entre tabelas. Cada um serve para situações diferentes.

Um para Um (1:1)

Cada registro de uma tabela se relaciona com exatamente um registro de outra tabela.

Exemplo: Usuário ↔ Perfil

Cada usuário tem exatamente um perfil, e cada perfil pertence a exatamente um usuário.

CREATE TABLE usuarios (
    id SERIAL PRIMARY KEY,
    email VARCHAR(100) UNIQUE NOT NULL
);

CREATE TABLE perfis (
    id SERIAL PRIMARY KEY,
    usuario_id INTEGER UNIQUE NOT NULL,
    nome_completo VARCHAR(200),
    bio TEXT,
    FOREIGN KEY (usuario_id) REFERENCES usuarios(id)
);

Um para Muitos (1:N)

Um registro de uma tabela pode se relacionar com vários registros de outra tabela.

Exemplo: Cliente → Pedidos

Um cliente pode ter vários pedidos, mas cada pedido pertence a apenas um cliente.

CREATE TABLE clientes (
    id SERIAL PRIMARY KEY,
    nome VARCHAR(100) NOT NULL
);

CREATE TABLE pedidos (
    id SERIAL PRIMARY KEY,
    cliente_id INTEGER NOT NULL,
    total DECIMAL(10,2),
    FOREIGN KEY (cliente_id) REFERENCES clientes(id)
);

Muitos para Muitos (N:N)

Vários registros de uma tabela podem se relacionar com vários registros de outra tabela.

Exemplo: Produtos ↔ Categorias

Um produto pode ter várias categorias, e uma categoria pode ter vários produtos.

CREATE TABLE produtos (
    id SERIAL PRIMARY KEY,
    nome VARCHAR(100) NOT NULL
);

CREATE TABLE categorias (
    id SERIAL PRIMARY KEY,
    nome VARCHAR(50) NOT NULL
);

-- Tabela de junção (junction table)
CREATE TABLE produto_categorias (
    produto_id INTEGER NOT NULL,
    categoria_id INTEGER NOT NULL,
    PRIMARY KEY (produto_id, categoria_id),
    FOREIGN KEY (produto_id) REFERENCES produtos(id),
    FOREIGN KEY (categoria_id) REFERENCES categorias(id)
);

Nota: Relacionamentos N:N precisam de uma tabela intermediária (tabela de junção) para funcionar.

Exemplo Prático: Sistema de E-commerce

Vamos criar um sistema simples de e-commerce para entender como os relacionamentos funcionam na prática.

-- 1. Tabela de categorias
CREATE TABLE categorias (
    id SERIAL PRIMARY KEY,
    nome VARCHAR(50) NOT NULL UNIQUE,
    descricao TEXT
);

-- 2. Tabela de produtos (relacionamento 1:N com categorias)
CREATE TABLE produtos (
    id SERIAL PRIMARY KEY,
    nome VARCHAR(100) NOT NULL,
    preco DECIMAL(10,2) NOT NULL,
    categoria_id INTEGER NOT NULL,
    em_estoque BOOLEAN DEFAULT true,
    
    FOREIGN KEY (categoria_id) REFERENCES categorias(id)
);

-- 3. Tabela de clientes
CREATE TABLE clientes (
    id SERIAL PRIMARY KEY,
    nome VARCHAR(100) NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL,
    telefone VARCHAR(20)
);

-- 4. Tabela de pedidos (relacionamento 1:N com clientes)
CREATE TABLE pedidos (
    id SERIAL PRIMARY KEY,
    cliente_id INTEGER NOT NULL,
    data_pedido TIMESTAMP DEFAULT NOW(),
    status VARCHAR(20) DEFAULT 'pendente',
    total DECIMAL(10,2),
    
    FOREIGN KEY (cliente_id) REFERENCES clientes(id)
);

-- 5. Tabela de itens do pedido (relacionamento N:N entre pedidos e produtos)
CREATE TABLE itens_pedido (
    id SERIAL PRIMARY KEY,
    pedido_id INTEGER NOT NULL,
    produto_id INTEGER NOT NULL,
    quantidade INTEGER NOT NULL DEFAULT 1,
    preco_unitario DECIMAL(10,2) NOT NULL,
    
    FOREIGN KEY (pedido_id) REFERENCES pedidos(id),
    FOREIGN KEY (produto_id) REFERENCES produtos(id)
);

Inserindo Dados com Relacionamentos

-- Inserir categorias primeiro
INSERT INTO categorias (nome, descricao) VALUES 
('Eletrônicos', 'Produtos eletrônicos e gadgets'),
('Casa', 'Produtos para casa e decoração');

-- Inserir produtos (referenciando categorias)
INSERT INTO produtos (nome, preco, categoria_id) VALUES 
('Smartphone', 899.99, 1),  -- categoria_id 1 = Eletrônicos
('Notebook', 2499.99, 1),   -- categoria_id 1 = Eletrônicos
('Sofá', 1299.99, 2);       -- categoria_id 2 = Casa

-- Inserir cliente
INSERT INTO clientes (nome, email, telefone) VALUES 
('Maria Silva', 'maria@email.com', '(11) 98765-4321');

-- Criar pedido
INSERT INTO pedidos (cliente_id, total) VALUES 
(1, 3399.98);  -- cliente_id 1 = Maria Silva

-- Adicionar itens ao pedido
INSERT INTO itens_pedido (pedido_id, produto_id, quantidade, preco_unitario) VALUES 
(1, 1, 1, 899.99),   -- 1 Smartphone
(1, 2, 1, 2499.99);  -- 1 Notebook

🎯 Ordem de inserção importante:

  1. 1. Primeiro as tabelas "pai" (categorias, clientes)
  2. 2. Depois as tabelas "filha" (produtos, pedidos)
  3. 3. Por último as tabelas de junção (itens_pedido)

Exercício Prático

Vamos praticar relacionamentos!

Complete o design de um sistema de biblioteca:

1. Que tipo de relacionamento existe entre "Autor" e "Livro"?

Um autor pode escrever vários livros, mas cada livro tem apenas um autor principal.

2. Complete a criação da tabela "livros":

CREATE TABLE livros (
    id SERIAL PRIMARY KEY,
    titulo VARCHAR(200) NOT NULL,
    autor_id INTEGER NOT NULL,
    ano_publicacao INTEGER,
    
    FOREIGN KEY (autor_id) _______ _______(id)
);

3. Que tipo de relacionamento existe entre "Livro" e "Categoria"?

Um livro pode pertencer a várias categorias (ficção, romance, aventura), e uma categoria pode ter vários livros.

4. Para um relacionamento N:N, precisamos de:

Boas Práticas

✅ Faça assim

  • • Use nomes descritivos para FKs (cliente_id, produto_id)
  • • Sempre defina NOT NULL em FKs obrigatórias
  • • Crie índices em colunas de FK para performance
  • • Documente os relacionamentos
  • • Use SERIAL para chaves primárias

💡 Dicas

  • • Desenhe o diagrama antes de criar as tabelas
  • • Comece pelas tabelas "pai" (sem dependências)
  • • Teste a inserção de dados para validar o design
  • • Use ferramentas visuais para modelagem

❌ Evite

  • • FKs com nomes genéricos (id, fk1, ref)
  • • Relacionamentos circulares desnecessários
  • • Muitas tabelas de junção
  • • FKs opcionais sem justificativa
  • • Duplicação de dados entre tabelas

⚠️ Cuidados

  • • FKs podem impedir exclusões
  • • Relacionamentos afetam performance
  • • Ordem de inserção/exclusão importa
  • • Mudanças de schema são mais complexas

Resumo da Aula

  • Relacionamentos conectam tabelas e evitam duplicação de dados
  • Chaves estrangeiras garantem integridade referencial
  • Existem três tipos: 1:1, 1:N e N:N
  • Relacionamentos N:N precisam de tabela intermediária
  • A ordem de criação e inserção de dados é importante
Aula Anterior: Consultando Dados Próxima Aula: Consultas com JOIN