SQL para Iniciantes (2026): Guia Prático com Formatação, Exemplos e Boas Práticas
SQL é a linguagem com maior longevidade em tech: 50 anos depois, continua sendo a forma universal de conversar com bancos de dados. Este guia cobre os comandos essenciais, a ordem lógica que importa, formatação consistente e os erros que iniciantes cometem sem perceber.
Por Vitor Morais
Fundador do MochaLabz ·
Formate SQL automaticamente
Cole qualquer query e receba formatação padronizada com syntax highlighting.
Usar formatador →SQL — Structured Query Language — é a linguagem padrão de bancos de dados relacionais desde 1974. Meio século depois, continua sendo o que todo dev, analista e PM precisa entender em algum nível. Este guia parte do zero e cobre o que é essencial para sair lendo e escrevendo SQL em um mês.
Foco no prático: comandos essenciais, ordem lógica que importa, formatação que torna queries legíveis, diferenças entre os principais bancos e os erros clássicos que fazem código novo travar em produção.
Os 6 comandos essenciais
| Critério | O que faz | Quando usa |
|---|---|---|
| SELECT | Lê dados | Consultas, relatórios, exports |
| INSERT | Adiciona linha | Novos registros |
| UPDATE | Modifica linha existente | Edição de registro |
| DELETE | Remove linha | Limpeza, soft-delete via flag |
| CREATE | Cria tabela, índice, view | Schema inicial, migrations |
| ALTER | Modifica estrutura existente | Adicionar coluna, mudar tipo |
O SELECT: o comando mais usado
90% do tempo em SQL é escrever SELECT. Anatomia básica:
SELECT coluna1, coluna2
FROM tabela
WHERE condicao
ORDER BY coluna1
LIMIT 10;Variações comuns
-- Todas as colunas (evite em produção)
SELECT * FROM usuarios;
-- Aliases com AS
SELECT u.nome AS nome_usuario, u.email AS contato FROM usuarios u;
-- Concatenação
SELECT nome || ' ' || sobrenome AS nome_completo FROM usuarios;
-- Funções comuns
SELECT UPPER(nome), LOWER(email), LENGTH(telefone) FROM usuarios;
-- Data
SELECT NOW() AS agora, CURRENT_DATE AS hoje;Atenção
SELECT * parece prático, mas em produção é armadilha: retorna colunas que você não usa, aumenta rede, quebra código quando adicionam nova coluna. Liste sempre as colunas explicitamente em queries de produção. Em exploração ad-hoc, tudo bem.WHERE: filtrando resultados
WHERE filtra linhas antes de retornar. Operadores essenciais:
| Critério | Exemplo | Uso |
|---|---|---|
| =, !=, <> | WHERE id = 42 | Igualdade |
| <, >, <=, >= | WHERE idade >= 18 | Comparação |
| LIKE | WHERE nome LIKE 'João%' | Busca textual simples |
| IN | WHERE status IN ('ativo', 'pendente') | Lista de valores |
| BETWEEN | WHERE preco BETWEEN 10 AND 100 | Intervalo |
| IS NULL / IS NOT NULL | WHERE deleted_at IS NULL | Ausência de valor |
| AND, OR, NOT | WHERE a = 1 AND b = 2 | Combinações |
Dica
% no início (LIKE '%João') não usa índice e fica lento. Para busca textual em escala, use full-text search do próprio banco (Postgres tsvector) ou serviço externo (ElasticSearch, Algolia).ORDER BY e LIMIT
-- Ordenar por uma coluna
SELECT * FROM produtos ORDER BY preco DESC;
-- Múltiplas colunas com direções diferentes
SELECT * FROM pedidos
ORDER BY criado_em DESC, total DESC;
-- NULLs primeiro ou por último (Postgres)
SELECT * FROM usuarios
ORDER BY ultimo_login DESC NULLS LAST;
-- LIMIT + OFFSET (paginação clássica)
SELECT * FROM posts
ORDER BY criado_em DESC
LIMIT 20 OFFSET 40; -- página 3 com 20 por páginaOrdem lógica vs ordem de execução
A ordem que você escreve não é a ordem que o banco executa. Isso explica por que você não pode usar alias do SELECT no WHERE.
| Critério | Ordem de escrita | Ordem de execução |
|---|---|---|
| 1 | SELECT | FROM |
| 2 | FROM | JOIN |
| 3 | JOIN | WHERE |
| 4 | WHERE | GROUP BY |
| 5 | GROUP BY | HAVING |
| 6 | HAVING | SELECT |
| 7 | ORDER BY | ORDER BY |
| 8 | LIMIT | LIMIT |
JOIN: unindo tabelas
JOIN combina linhas de duas tabelas por uma condição. Os tipos principais:
-- INNER JOIN: apenas matches em ambas as tabelas
SELECT u.nome, p.total
FROM usuarios u
INNER JOIN pedidos p ON p.usuario_id = u.id;
-- LEFT JOIN: todos da esquerda, com NULL onde não há match
SELECT u.nome, p.total
FROM usuarios u
LEFT JOIN pedidos p ON p.usuario_id = u.id;
-- RIGHT JOIN: espelho, raramente usado
SELECT u.nome, p.total
FROM usuarios u
RIGHT JOIN pedidos p ON p.usuario_id = u.id;
-- FULL OUTER JOIN: tudo de ambos
SELECT u.nome, p.total
FROM usuarios u
FULL OUTER JOIN pedidos p ON p.usuario_id = u.id;Agregações: GROUP BY e funções
Para responder perguntas tipo “quantos pedidos por usuário?”, use GROUP BY.
-- Contar pedidos por usuário
SELECT
usuario_id,
COUNT(*) AS total_pedidos,
SUM(valor) AS receita_total,
AVG(valor) AS ticket_medio,
MIN(criado_em) AS primeiro_pedido,
MAX(criado_em) AS ultimo_pedido
FROM pedidos
GROUP BY usuario_id
HAVING COUNT(*) >= 5 -- filtra AGREGAÇÃO (não usa WHERE)
ORDER BY receita_total DESC
LIMIT 10;Contexto
INSERT, UPDATE, DELETE
-- Inserir uma linha
INSERT INTO usuarios (nome, email, criado_em)
VALUES ('João', 'joao@exemplo.com', NOW());
-- Inserir várias linhas
INSERT INTO usuarios (nome, email)
VALUES
('Ana', 'ana@exemplo.com'),
('Bruno', 'bruno@exemplo.com'),
('Carla', 'carla@exemplo.com');
-- Atualizar
UPDATE usuarios
SET email = 'novo@exemplo.com', atualizado_em = NOW()
WHERE id = 42;
-- Deletar
DELETE FROM usuarios WHERE id = 42;
-- Soft delete (recomendado em produção)
UPDATE usuarios SET deleted_at = NOW() WHERE id = 42;Atenção
Boas práticas de formatação
SQL vive em arquivos de migration, notebooks, code review e relatórios. Formatação consistente muda legibilidade dramaticamente.
Estilo comum e recomendado
-- Palavras-chave em MAIÚSCULA, identificadores em minúscula
-- Vírgulas ao início da linha (facilita diff em PR)
-- Nova linha antes de FROM, WHERE, JOIN, GROUP BY, ORDER BY
-- Indentação consistente dentro de subquery
SELECT
u.id
, u.nome
, u.email
, COUNT(p.id) AS total_pedidos
, SUM(p.valor) AS receita_total
FROM usuarios u
LEFT JOIN pedidos p ON p.usuario_id = u.id
WHERE u.criado_em >= '2025-01-01'
AND u.status = 'ativo'
GROUP BY u.id, u.nome, u.email
HAVING COUNT(p.id) >= 3
ORDER BY receita_total DESC
LIMIT 50;Tipos de dados mais comuns
| Critério | Exemplo | Quando usar |
|---|---|---|
| INTEGER / BIGINT | 42, 1000000 | IDs, contagens, quantidades |
| DECIMAL / NUMERIC(p,s) | 19.99 | Dinheiro, preços (não use FLOAT) |
| VARCHAR(n) | 'João' | Textos com limite |
| TEXT | bloco grande | Textos longos sem limite prático |
| BOOLEAN | TRUE, FALSE | Flags binárias |
| TIMESTAMP / TIMESTAMPTZ | 2026-04-17 10:00:00+00 | Data + hora, com fuso |
| DATE | 2026-04-17 | Só data |
| UUID | c27a...e88f | IDs globais únicos |
| JSON / JSONB | {"k":"v"} | Documentos estruturados |
Atenção
0.1 + 0.2 = 0.30000...04 em float é o clássico bug que custa caro em ERP e financeiro.CREATE TABLE: definindo schema
CREATE TABLE usuarios (
id BIGSERIAL PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
nome VARCHAR(100) NOT NULL,
senha_hash VARCHAR(255) NOT NULL,
ativo BOOLEAN NOT NULL DEFAULT TRUE,
criado_em TIMESTAMPTZ NOT NULL DEFAULT NOW(),
atualizado_em TIMESTAMPTZ NOT NULL DEFAULT NOW(),
deleted_at TIMESTAMPTZ
);
CREATE INDEX idx_usuarios_email ON usuarios(email);
CREATE INDEX idx_usuarios_ativo ON usuarios(ativo) WHERE ativo = TRUE;NULL: a dor inevitável
NULL é o conceito mais escorregadio de SQL. Regras práticas:
NULL = NULLnão retorna TRUE — retorna NULL (unknown).- Use
IS NULLeIS NOT NULL, não= NULL. - Em operações aritméticas, NULL propaga:
5 + NULL= NULL. COALESCE(coluna, 'default')retorna o primeiro não-NULL.- Agregações ignoram NULL:
COUNT(coluna)não conta linhas com NULL;COUNT(*)conta todas.
Transações: tudo ou nada
Para operações que precisam ser atômicas, use transação:
BEGIN;
UPDATE contas SET saldo = saldo - 100 WHERE id = 1;
UPDATE contas SET saldo = saldo + 100 WHERE id = 2;
-- Se tudo deu certo
COMMIT;
-- Se algo deu errado
-- ROLLBACK;CTE (WITH): queries legíveis em vez de subqueries aninhadas
WITH pedidos_ativos AS (
SELECT usuario_id, SUM(valor) AS total
FROM pedidos
WHERE status = 'pago'
GROUP BY usuario_id
),
top_clientes AS (
SELECT usuario_id, total
FROM pedidos_ativos
WHERE total > 10000
)
SELECT u.nome, u.email, t.total
FROM top_clientes t
JOIN usuarios u ON u.id = t.usuario_id
ORDER BY t.total DESC;Diferenças entre PostgreSQL e MySQL
| Critério | PostgreSQL | MySQL |
|---|---|---|
| String concat | || | CONCAT() |
| Limit com offset | LIMIT n OFFSET m | LIMIT m, n ou LIMIT n OFFSET m |
| Auto-increment | SERIAL / GENERATED | AUTO_INCREMENT |
| Booleano | BOOLEAN nativo | TINYINT(1) |
| JSON queries | JSONB + operadores ricos | JSON + funções básicas |
| Window functions | Completas desde 2013 | Disponível desde 8.0 |
Erros clássicos que iniciantes cometem
- Esquecer WHERE em UPDATE/DELETE: atualiza ou deleta tudo.
- Comparar NULL com = : use IS NULL.
- SELECT * em tabela grande: mata performance e rede.
- Não usar LIMIT em exploratório: query que trava por 10 minutos retornando 10 milhões de linhas.
- JOIN sem ON: vira CROSS JOIN, explode linhas.
- Usar FLOAT para dinheiro: arredondamento quebra cobrança.
- Hardcode de senha ou dado sensível: logs e backups expõem.
- Confundir índices UNIQUE com PRIMARY KEY: UNIQUE permite NULL, PK não.
Roteiro dos primeiros 30 dias
Semana 1: fundamentos
Instale PostgreSQL ou use um playground online (DB Fiddle, SQLFiddle). Estude SELECT, WHERE, ORDER BY, LIMIT. Faça 30 queries em um dataset público (Sakila, Northwind, Chinook).
Semana 2: relacionamentos
Pratique JOINs com 2–3 tabelas. Entenda INNER vs LEFT vs FULL. Faça queries que respondam perguntas de negócio reais (top 10 clientes, produto mais vendido por mês).
Semana 3: agregações e CTE
Foque em GROUP BY, HAVING, funções agregadas. Resolva 20 problemas usando CTE (WITH) em vez de subquery aninhada. Aprenda window functions (ROW_NUMBER, RANK, LAG).
Semana 4: performance e schema
Crie tabelas, índices, constraints. Use EXPLAIN para ver planos de execução. Entenda transações e isolamento. Resolva 10 queries lentas e melhore performance em 10x.
SQL em uma frase
SQL parece intimidador pela sintaxe, mas vira segunda natureza após 100 queries escritas. É uma das 3 habilidades com maior ROI em carreira tech: funciona em qualquer empresa que tem banco de dados, que é literalmente toda empresa. Invista os 30 dias iniciais; o retorno acompanha você a vida inteira.
Perguntas frequentes
Qual banco escolher para aprender SQL?+
PostgreSQL é a melhor escolha para aprender em 2026. Open source, padrão da indústria, suporta recursos avançados (JSON, arrays, full-text search, window functions) e a documentação é excelente. MySQL continua muito presente em hospedagens baratas; SQLite é ideal para aprender local sem instalar servidor. Evite começar em bancos comerciais (SQL Server, Oracle) a menos que sua empresa use — sintaxes têm particularidades que confundem iniciante.
Preciso decorar comandos SQL?+
Não. Você precisa entender os 6 comandos essenciais (SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER) e os operadores lógicos. Tudo mais é composição. IDEs modernos (DBeaver, TablePlus, PgAdmin) oferecem autocomplete para funções e sintaxe. Depois de 100 queries escritas com consulta à documentação, você já lembra dos 20% que usa 80% do tempo.
Qual a ordem correta dos comandos em um SELECT?+
A ordem lógica é: SELECT, FROM, JOIN, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT. A ordem de execução interna é diferente (FROM e JOIN primeiro, SELECT penúltimo), o que explica por que você não pode usar alias do SELECT no WHERE. Memorizar a ordem lógica evita erros de sintaxe e facilita leitura de queries complexas.
Devo usar MAIÚSCULA nas palavras-chave SQL?+
É convenção e boa prática, mas tecnicamente SQL é case-insensitive para palavras-chave. SELECT e select funcionam igual. Escrever palavras-chave em MAIÚSCULA (SELECT, WHERE, JOIN) e identificadores em minúscula (usuarios, id_pedido) melhora legibilidade drasticamente em queries longas. Formatadores automáticos aplicam essa convenção.
JOIN ou subquery, qual usar?+
Em geral, JOIN é mais legível e o otimizador do banco costuma executar com mesmo plano. Use subquery quando a lógica de filtro é mais clara nela (ex.: “pegar produtos com preço acima da média”). CTE com WITH é a forma moderna e mais legível para queries complexas. Evite subqueries aninhadas de 3+ níveis — é sinal de que a lógica precisa de refatoração ou view.
NULL é diferente de vazio?+
Sim, drasticamente. NULL significa “ausência de valor”; string vazia ('') é um valor — uma string de tamanho zero. Em comparação, NULL = NULL retorna NULL (não TRUE!). Use IS NULL / IS NOT NULL, nunca = NULL. Função COALESCE(valor, 'default') é indispensável para tratar NULLs em queries que alimentam relatórios.
Como formatar SQL de forma consistente?+
Use formatador automático: SQLFluff, pgFormatter, ou o formatador do seu IDE (DBeaver, DataGrip, VSCode extension). Configure em uma convenção única (padrão mais comum: keywords em MAIÚSCULA, alinhamento vertical em SELECTs com múltiplas colunas, nova linha antes de FROM, WHERE, JOIN). Formatação consistente torna code review 10x mais rápido.
Por que queries ficam lentas com muitos dados?+
Principais razões: falta de índice na coluna do WHERE ou JOIN, SELECT * em tabela grande, funções aplicadas à coluna indexada (ex.: WHERE LOWER(nome) = ...), ausência de LIMIT em queries exploratórias, locks por transação longa. Use EXPLAIN para ver o plano de execução antes de acusar o banco. Em 99% dos casos, a query é o problema — não o servidor.
Artigos relacionados
UUID como Chave Primária: Vantagens, Problemas e Alternativas (2026)
Tudo sobre usar UUID como chave primária em PostgreSQL e MySQL: por que vale, problema de fragmentação do v4, como UUID v7 resolve, comparativo com BIGINT, ULID, NanoID, CUID2 e Snowflake.
DATETIME vs TIMESTAMP no Banco de Dados (Guia 2026): MySQL e PostgreSQL
Comparativo técnico completo: armazenamento, fuso horário, range, tamanho, comportamento em mudanças de TZ, TIMESTAMPTZ, problema 2038 e migração.
SQL JOINs: Guia Completo (2026) com INNER, LEFT, RIGHT, FULL e CROSS
Guia definitivo de SQL JOINs com diagramas, tabelas e exemplos prontos para PostgreSQL e MySQL. INNER, LEFT, RIGHT, FULL OUTER, CROSS, SELF JOIN, ON vs USING, anti-join, semi-join e armadilhas de performance.
Performance SQL com Índices: Guia Completo 2026 (PostgreSQL e MySQL)
Aprenda a usar índices em SQL para acelerar queries de segundos para milissegundos. Tipos de índice (B-tree, GIN, GiST, BRIN), índices compostos, parciais, funcionais, EXPLAIN ANALYZE, anti-padrões e checklist de manutenção.