0
Promoção de Volta das Aulas ! Cursos com 25% OFF no menu "Cursos"
setembro 23, 2025
0
César Fontanella

Banco de Dados: Entendendo a Estrutura no SQL para Iniciantes

Bancos de dados relacionais sustentam redes sociais, e-commerce, ERPs e apps mobile. Antes de escrever sua primeira consulta SQL, entender como os dados são organizados (tabelas, chaves, tipos, relacionamentos) economiza horas de depuração e evita modelos frágeis. Este guia apresenta os blocos fundamentais que você usará diariamente.


O que é um banco de dados relacional?

Um SGBD relacional (PostgreSQL, MySQL, SQL Server, Oracle) organiza dados em tabelas (como planilhas):

  • Linhas (registros/tuplas): cada ocorrência de dado.
  • Colunas (campos/atributos): características do registro.
  • Esquema (schema): definição formal da estrutura (tabelas, colunas, tipos, chaves).
  • Instância: o conjunto de dados carregados naquele momento.

Exemplo de tabela clientes:

id_clientenomeemailcriado_em
1Ana Lima[email protected]2025-09-10
2João Luz[email protected]2025-09-12

Tipos de dados: a base da integridade

Escolher o tipo certo garante validação e performance:

  • INTEGER/BIGINT – inteiros/identificadores.
  • DECIMAL(p,s)/NUMERIC – valores financeiros (evite FLOAT p/ dinheiro).
  • VARCHAR(n)/TEXT – textos.
  • DATE/TIME/TIMESTAMP – datas e horários.
  • BOOLEAN – verdadeiro/falso.
  • UUID – identificador global único (alguns SGBDs).

Boa prática: modele o tipo mais restrito que atende ao dado. Isso reduz armazenamento e previne entradas inválidas.


Chaves: primária, única e estrangeira

  • Chave Primária (PK): identifica exclusivamente cada linha.
  • Chave Única (UNIQUE): impede duplicidade em uma coluna/grupo (ex.: email).
  • Chave Estrangeira (FK): cria o relacionamento entre tabelas garantindo referencial (ex.: cada pedido deve apontar para um cliente válido).

Modelando um mini-ERP (clientes ↔ pedidos ↔ itens)

CREATE TABLE clientes (
  id_cliente     BIGSERIAL PRIMARY KEY,
  nome           VARCHAR(120) NOT NULL,
  email          VARCHAR(180) UNIQUE NOT NULL,
  criado_em      TIMESTAMP NOT NULL DEFAULT NOW()
);

CREATE TABLE pedidos (
  id_pedido      BIGSERIAL PRIMARY KEY,
  id_cliente     BIGINT NOT NULL REFERENCES clientes(id_cliente)
                  ON UPDATE CASCADE ON DELETE RESTRICT,
  status         VARCHAR(20) NOT NULL CHECK (status IN ('novo','pago','enviado','cancelado')),
  criado_em      TIMESTAMP NOT NULL DEFAULT NOW()
);

CREATE TABLE itens_pedido (
  id_item        BIGSERIAL PRIMARY KEY,
  id_pedido      BIGINT NOT NULL REFERENCES pedidos(id_pedido) ON DELETE CASCADE,
  sku            VARCHAR(40) NOT NULL,
  qtde           INTEGER NOT NULL CHECK (qtde > 0),
  preco_unit     DECIMAL(12,2) NOT NULL CHECK (preco_unit >= 0)
);
  • ON DELETE CASCADE apaga itens quando o pedido é removido.
  • ON DELETE RESTRICT impede excluir um cliente com pedidos ativos.

Relacionamentos e cardinalidade

  • 1:1 – um cliente ↔ uma carteira digital (raro).
  • 1:N – um cliente → muitos pedidos (mais comum).
  • N:M – pedidos ↔ cupons (tabela associativa pedido_cupom).
CREATE TABLE pedido_cupom (
  id_pedido BIGINT NOT NULL REFERENCES pedidos(id_pedido) ON DELETE CASCADE,
  codigo    VARCHAR(20) NOT NULL,
  PRIMARY KEY (id_pedido, codigo)
);

Normalização (e quando desnormalizar)

Normalização reduz redundâncias e anomalias:

  • 1NF: sem colunas multivalor; linhas atômicas.
  • 2NF: colunas dependem da PK inteira (evita dependência parcial).
  • 3NF: sem dependências transitivas (A → B → C).

Trade-off: às vezes desnormalizar (armazenar um subtotal, por ex.) melhora leitura. Faça isso conscientemente e com validações/rotinas para manter consistência.


Restrições e regras de negócio no banco

  • NOT NULL – obriga valor.
  • CHECK – valida domínio (status IN (…), qtde > 0).
  • DEFAULT – valor padrão (NOW()/CURRENT_DATE).
  • UNIQUE – evita duplicados.
  • FOREIGN KEY – garante integridade referencial.

Centralizar regras no banco previne inconsistências caso existam múltiplos serviços/clientes acessando os dados.


Índices: quando e por quê

Índices aceleram filtros e junções (normalmente B-tree):

CREATE INDEX idx_pedidos_cliente ON pedidos(id_cliente);
CREATE INDEX idx_itens_pedido_pedido ON itens_pedido(id_pedido);
  • Crie índices nas colunas mais filtradas (FKs, buscas por e-mail, datas).
  • Evite excesso: cada índice custa escrita (INSERT/UPDATE/DELETE mais lentos).

Nulos, valores padrão e consistência

  • NULL significa “desconhecido/ausente” (não é zero nem vazio).
  • Comparações com NULL usam IS NULL/IS NOT NULL.
  • Prefira NOT NULL + DEFAULT quando há valor sensato.

Exemplo prático: do modelo à consulta

Pergunta: “Quais pedidos pagos do cliente com e-mail [email protected] nos últimos 30 dias?”

SELECT p.id_pedido, p.criado_em, SUM(i.qtde * i.preco_unit) AS total
FROM pedidos p
JOIN clientes c       ON c.id_cliente = p.id_cliente
JOIN itens_pedido i   ON i.id_pedido  = p.id_pedido
WHERE c.email  = '[email protected]'
  AND p.status = 'pago'
  AND p.criado_em >= NOW() - INTERVAL '30 days'
GROUP BY p.id_pedido, p.criado_em
ORDER BY p.criado_em DESC;

Boas práticas para quem está começando

  1. Nomeie de forma clara (snake_case, sem abreviações obscuras).
  2. Defina PKs desde o início (surrogate keys como BIGSERIAL/UUID).
  3. Planeje FKs – relações explícitas facilitam junções corretas.
  4. Adicione índices com parcimônia – meça antes/depois.
  5. Documente o esquema (diagramas ER, comentários no banco).
  6. Semeie dados de exemplo para testar cenários reais.

FAQ rápido

PK vs UNIQUE? PK identifica a linha e não aceita NULL; UNIQUE só restringe duplicidade e pode aceitar NULL (depende do SGBD).
Quando usar UUID? Em sistemas distribuídos/microserviços, quando você precisa gerar IDs sem coordenação central.
Dinheiro com FLOAT? Evite; use DECIMAL/NUMERIC para exatidão.

Este artigo foi inspirado no Capítulo 1 – “Understanding Database Structure” do livro SQL: QuickStart Guide – The Simplified Beginner’s Guide to SQL, de Walter Shields.