Definição
O que é Modelagem de Dados?
Modelagem de dados é o processo de criar uma representação visual e lógica das estruturas de dados de um sistema. O Diagrama Entidade-Relacionamento (DER ou ERD) é a ferramenta mais utilizada para essa tarefa.
O modelo ER foi proposto por Peter Chen em 1976 e se tornou o padrão da indústria para projetar bancos de dados relacionais. Ele permite visualizar como os dados se organizam antes de criar as tabelas físicas no banco.
Níveis de Abstração:
Modelo Conceitual
Visão de alto nível, foco no negócio. Independente de tecnologia.
Modelo Lógico
Define tabelas, colunas, tipos de dados e relacionamentos.
Modelo Físico
Específico do SGBD (Oracle), inclui índices, partições, tablespaces.
Componentes do Modelo ER
Entidades
Representam objetos do mundo real sobre os quais queremos armazenar informações.
- CLIENTE, PRODUTO, PEDIDO
- FUNCIONARIO, DEPARTAMENTO
- Representadas por retângulos
Atributos
São as características ou propriedades de uma entidade.
- Cliente: nome, cpf, email
- Produto: codigo, descricao, preco
- Representados por elipses
Relacionamentos
Definem como as entidades se conectam entre si.
- Cliente FAZ Pedido
- Funcionário TRABALHA_EM Departamento
- Representados por losangos
Cardinalidade
Define a quantidade de instâncias em um relacionamento.
- 1:1 - Um para um
- 1:N - Um para muitos
- N:N - Muitos para muitos
Tipos de Cardinalidade em Detalhe
1:1 (Um para Um)
Uma instância de A se relaciona com no máximo uma instância de B, e vice-versa.
FUNCIONARIO
──────
1:1
──────
CRACHA
Cada funcionário tem exatamente um crachá, cada crachá pertence a um funcionário.
1:N (Um para Muitos)
Uma instância de A pode se relacionar com várias instâncias de B.
DEPARTAMENTO
──────
1:N
──────
FUNCIONARIO
Um departamento tem vários funcionários, cada funcionário pertence a um departamento.
N:N (Muitos para Muitos)
Várias instâncias de A podem se relacionar com várias instâncias de B.
ALUNO
──────
N:N
──────
DISCIPLINA
Um aluno cursa várias disciplinas, uma disciplina tem vários alunos.
Importante: Relacionamentos N:N requerem uma tabela associativa no modelo físico!
Aplicação Prática
Caso Prático: Sistema de E-commerce
Vamos modelar um sistema de e-commerce simples, partindo dos requisitos até o modelo físico no Oracle.
Requisitos de Negócio:
- Clientes podem fazer vários pedidos
- Cada pedido pertence a um único cliente
- Um pedido contém vários produtos
- Cada produto pode estar em vários pedidos
- Produtos são organizados em categorias
- Uma categoria pode ter várias subcategorias
Entidades Identificadas:
Relacionamentos:
- CLIENTE 1:N PEDIDO (um cliente faz vários pedidos)
- PEDIDO N:N PRODUTO (via ITEM_PEDIDO)
- CATEGORIA 1:N PRODUTO (uma categoria tem vários produtos)
- CATEGORIA 1:N CATEGORIA (autorelacionamento para subcategorias)
Do Modelo ER para o Modelo Físico (Oracle)
-- Tabela de Categorias (com autorelacionamento para hierarquia)
CREATE TABLE categorias (
id_categoria NUMBER(10) PRIMARY KEY,
nome VARCHAR2(100) NOT NULL,
descricao VARCHAR2(500),
categoria_pai_id NUMBER(10) REFERENCES categorias(id_categoria),
ativo CHAR(1) DEFAULT 'S' CHECK (ativo IN ('S', 'N'))
);
-- Tabela de Clientes
CREATE TABLE clientes (
id_cliente NUMBER(10) PRIMARY KEY,
nome VARCHAR2(150) NOT NULL,
cpf CHAR(11) UNIQUE NOT NULL,
email VARCHAR2(100) UNIQUE NOT NULL,
telefone VARCHAR2(15),
data_cadastro DATE DEFAULT SYSDATE,
status VARCHAR2(20) DEFAULT 'ATIVO' CHECK (status IN ('ATIVO', 'INATIVO', 'BLOQUEADO'))
);
-- Tabela de Produtos
CREATE TABLE produtos (
id_produto NUMBER(10) PRIMARY KEY,
codigo_sku VARCHAR2(50) UNIQUE NOT NULL,
nome VARCHAR2(200) NOT NULL,
descricao CLOB,
preco NUMBER(10,2) NOT NULL CHECK (preco > 0),
estoque NUMBER(10) DEFAULT 0,
categoria_id NUMBER(10) NOT NULL REFERENCES categorias(id_categoria),
data_cadastro DATE DEFAULT SYSDATE,
ativo CHAR(1) DEFAULT 'S' CHECK (ativo IN ('S', 'N'))
);
-- Tabela de Pedidos
CREATE TABLE pedidos (
id_pedido NUMBER(10) PRIMARY KEY,
cliente_id NUMBER(10) NOT NULL REFERENCES clientes(id_cliente),
data_pedido TIMESTAMP DEFAULT SYSTIMESTAMP,
status VARCHAR2(20) DEFAULT 'PENDENTE'
CHECK (status IN ('PENDENTE', 'CONFIRMADO', 'ENVIADO', 'ENTREGUE', 'CANCELADO')),
valor_total NUMBER(12,2),
endereco_entrega VARCHAR2(500)
);
-- Tabela Associativa: Itens do Pedido (resolve relacionamento N:N)
CREATE TABLE itens_pedido (
id_pedido NUMBER(10) REFERENCES pedidos(id_pedido),
id_produto NUMBER(10) REFERENCES produtos(id_produto),
quantidade NUMBER(10) NOT NULL CHECK (quantidade > 0),
preco_unitario NUMBER(10,2) NOT NULL,
desconto NUMBER(5,2) DEFAULT 0,
PRIMARY KEY (id_pedido, id_produto)
);
-- Índices para melhorar performance
CREATE INDEX idx_pedidos_cliente ON pedidos(cliente_id);
CREATE INDEX idx_pedidos_data ON pedidos(data_pedido);
CREATE INDEX idx_produtos_categoria ON produtos(categoria_id);
CREATE INDEX idx_itens_produto ON itens_pedido(id_produto);
-- Comentários nas tabelas (documentação)
COMMENT ON TABLE clientes IS 'Cadastro de clientes do e-commerce';
COMMENT ON COLUMN clientes.cpf IS 'CPF do cliente sem formatação';
COMMENT ON TABLE itens_pedido IS 'Tabela associativa entre pedidos e produtos';
Normalização: As 3 Formas Normais
1ª Forma Normal (1FN)
Eliminar grupos repetitivos - cada célula deve conter apenas um valor atômico.
✓ Correto: Criar tabela TELEFONES_CLIENTE separada
2ª Forma Normal (2FN)
Eliminar dependências parciais - atributos devem depender de toda a chave primária.
✓ Correto: nome_produto fica na tabela PRODUTOS
3ª Forma Normal (3FN)
Eliminar dependências transitivas - atributos não-chave não devem depender de outros atributos não-chave.
✓ Correto: Criar tabela CIDADES com cidade_id, nome, estado
Resultado Esperado
O que você deve dominar após este tópico:
Ler diagramas ER
Interpretar modelos existentes de qualquer sistema
Identificar entidades e atributos
Extrair requisitos de negócio para modelo de dados
Definir cardinalidades
Escolher 1:1, 1:N ou N:N corretamente
Converter ER para SQL
Transformar modelo lógico em CREATE TABLE
Aplicar normalização
Eliminar redundâncias até 3FN
Usar ferramentas
Conhecer Oracle SQL Developer Data Modeler
Exercícios Práticos
Exercício 1: Identificar Cardinalidades
Determine a cardinalidade correta para os seguintes relacionamentos:
- AUTOR e LIVRO (um autor pode escrever vários livros, um livro pode ter vários autores)
- PAIS e ESTADO (um país tem vários estados, um estado pertence a um país)
- PESSOA e RG (cada pessoa tem um RG único)
- MEDICO e PACIENTE (um médico atende vários pacientes, um paciente consulta vários médicos)
Ver Solução
- N:N - Requer tabela associativa AUTOR_LIVRO
- 1:N - FK país_id na tabela ESTADO
- 1:1 - Pode ser FK em PESSOA ou tabela separada RG
- N:N - Requer tabela associativa CONSULTAS
Exercício 2: Modelar Sistema de Biblioteca
Crie o modelo físico (CREATE TABLE) para uma biblioteca com:
- Livros (podem ter múltiplos exemplares)
- Autores (um livro pode ter vários autores)
- Usuários (leitores)
- Empréstimos (controle de quem pegou qual exemplar)
Ver Solução
-- Autores
CREATE TABLE autores (
id_autor NUMBER PRIMARY KEY,
nome VARCHAR2(150) NOT NULL,
pais VARCHAR2(50)
);
-- Livros
CREATE TABLE livros (
id_livro NUMBER PRIMARY KEY,
isbn VARCHAR2(20) UNIQUE NOT NULL,
titulo VARCHAR2(300) NOT NULL,
editora VARCHAR2(100),
ano_pub NUMBER(4)
);
-- Relacionamento N:N entre Livros e Autores
CREATE TABLE livros_autores (
id_livro NUMBER REFERENCES livros(id_livro),
id_autor NUMBER REFERENCES autores(id_autor),
PRIMARY KEY (id_livro, id_autor)
);
-- Exemplares (cada livro pode ter vários exemplares)
CREATE TABLE exemplares (
id_exemplar NUMBER PRIMARY KEY,
id_livro NUMBER NOT NULL REFERENCES livros(id_livro),
codigo VARCHAR2(20) UNIQUE NOT NULL,
status VARCHAR2(20) DEFAULT 'DISPONIVEL'
CHECK (status IN ('DISPONIVEL', 'EMPRESTADO', 'MANUTENCAO'))
);
-- Usuários
CREATE TABLE usuarios (
id_usuario NUMBER PRIMARY KEY,
nome VARCHAR2(150) NOT NULL,
email VARCHAR2(100) UNIQUE NOT NULL,
telefone VARCHAR2(15)
);
-- Empréstimos
CREATE TABLE emprestimos (
id_emprestimo NUMBER PRIMARY KEY,
id_exemplar NUMBER NOT NULL REFERENCES exemplares(id_exemplar),
id_usuario NUMBER NOT NULL REFERENCES usuarios(id_usuario),
data_emprestimo DATE DEFAULT SYSDATE,
data_prevista DATE NOT NULL,
data_devolucao DATE
);
Exercício 3: Normalização
A tabela abaixo está desnormalizada. Normalize-a até a 3ª Forma Normal:
CREATE TABLE vendas (
id_venda NUMBER,
data_venda DATE,
vendedor_nome VARCHAR2(100),
vendedor_cpf VARCHAR2(14),
vendedor_depto VARCHAR2(50),
depto_gerente VARCHAR2(100),
produto_codigo VARCHAR2(20),
produto_nome VARCHAR2(100),
produto_categoria VARCHAR2(50),
quantidade NUMBER,
preco_unitario NUMBER
);
Ver Solução
-- Departamentos (3FN: gerente não depende da venda)
CREATE TABLE departamentos (
id_depto NUMBER PRIMARY KEY,
nome VARCHAR2(50) NOT NULL,
gerente VARCHAR2(100)
);
-- Vendedores (2FN: dados do vendedor em tabela própria)
CREATE TABLE vendedores (
id_vendedor NUMBER PRIMARY KEY,
nome VARCHAR2(100) NOT NULL,
cpf VARCHAR2(14) UNIQUE NOT NULL,
id_depto NUMBER REFERENCES departamentos(id_depto)
);
-- Categorias (3FN: categoria independente)
CREATE TABLE categorias (
id_categoria NUMBER PRIMARY KEY,
nome VARCHAR2(50) NOT NULL
);
-- Produtos (2FN: dados do produto separados)
CREATE TABLE produtos (
id_produto NUMBER PRIMARY KEY,
codigo VARCHAR2(20) UNIQUE NOT NULL,
nome VARCHAR2(100) NOT NULL,
id_categoria NUMBER REFERENCES categorias(id_categoria)
);
-- Vendas (tabela principal limpa)
CREATE TABLE vendas (
id_venda NUMBER PRIMARY KEY,
data_venda DATE DEFAULT SYSDATE,
id_vendedor NUMBER REFERENCES vendedores(id_vendedor)
);
-- Itens da Venda (resolve N:N e armazena preço histórico)
CREATE TABLE itens_venda (
id_venda NUMBER REFERENCES vendas(id_venda),
id_produto NUMBER REFERENCES produtos(id_produto),
quantidade NUMBER NOT NULL,
preco_unitario NUMBER NOT NULL,
PRIMARY KEY (id_venda, id_produto)
);