SQL legível — um guia de estilo prático para formatar consultas
Como organizar SELECT, JOIN, WHERE e CTEs para a consulta ficar fácil de ler e revisar, por que o dialeto importa ao formatar e os hábitos que evitam bugs.
Por Felipe YamaokaPublicado em 5 de novembro de 20265 min de leitura
A consulta de uma linha no log
Mais cedo ou mais tarde você precisa depurar uma consulta assim, copiada do log do ORM ou de uma ferramenta de monitoramento:
select u.id, u.name, count(o.id) as orders from users u left join orders o on o.user_id = u.id where u.active = 1 and o.created_at >= '2026-01-01' group by u.id, u.name having count(o.id) > 5 order by orders desc limit 10Funciona, mas ler exige ir e voltar para achar onde termina a condição do join e onde começa o filtro. A mesma consulta, formatada:
SELECT
u.id,
u.name,
count(o.id) AS orders
FROM
users u
LEFT JOIN orders o ON o.user_id = u.id
WHERE
u.active = 1
AND o.created_at >= '2026-01-01'
GROUP BY
u.id,
u.name
HAVING
count(o.id) > 5
ORDER BY
orders DESC
LIMIT
10Agora cada cláusula tem o seu bloco e cada condição a sua linha. Dá para ver de relance que o filtro em o.created_at está no WHERE, o que transforma o LEFT JOIN num inner join sem ninguém perceber: usuários sem pedidos recentes somem do resultado. Esse tipo de bug se esconde no SQL de uma linha e salta aos olhos no SQL formatado. Este guia cobre as convenções que tornam isso possível.
Formatar muda o layout, não o significado
Um formatador só mexe em espaços, quebras de linha e, se você pedir, na caixa das palavras-chave. Os tokens e a ordem deles continuam iguais, então a consulta formatada devolve exatamente o mesmo resultado. Por isso é seguro formatar qualquer consulta, inclusive uma que você ainda não entendeu direito, e o diff da revisão de código passa a mostrar lógica, e não espaçamento.
As convenções que mais importam
Não existe um estilo oficial de SQL, mas a maioria dos guias concorda em algumas regras:
- Uma cláusula por bloco.
SELECT,FROM,WHERE,GROUP BY,HAVING,ORDER BYeLIMITcomeçam na margem esquerda, e o conteúdo vem indentado embaixo. - Uma coluna por linha no
SELECT. Acrescentar, tirar ou comentar uma coluna vira uma mudança de uma linha, e o diff fica pequeno. - Uma condição por linha, com o operador na frente. Começar as linhas com
ANDeORdeixa a lógica visível e fácil de comentar. - Join com a condição na mesma linha.
LEFT JOIN orders o ON o.user_id = u.idmantém cada relacionamento legível como uma unidade. - Caixa consistente nas palavras-chave. Palavras-chave em maiúsculas (
SELECT,FROM) são a convenção mais comum, porque separam a linguagem dos nomes de tabelas e colunas. Minúsculas também funcionam; o que atrapalha é misturar. - Aliases com significado.
uparauserseoparaordersfuncionam numa consulta curta. Numa longa,clientes cenotas_fiscais nfsão melhores quet1et2.
O tamanho da indentação é questão de gosto: dois espaços, quatro ou tab, desde que o projeto inteiro use o mesmo.
Subconsultas e CTEs
Subconsultas aninhadas são onde a legibilidade costuma desmoronar. Uma CTE (common table expression), introduzida com WITH, permite dar nome a um resultado intermediário e ler a consulta de cima para baixo:
WITH
recent AS (
SELECT
user_id,
sum(total) AS spent
FROM
orders
WHERE
created_at >= '2026-01-01'
GROUP BY
user_id
)
SELECT
u.name,
r.spent
FROM
users u
JOIN recent r ON r.user_id = u.id
WHERE
r.spent > 1000
ORDER BY
r.spent DESCCada CTE é indentada como uma consulta própria. Um bom nome, como recent aqui, documenta o que a etapa faz melhor do que um comentário.
Por que o dialeto importa
SQL parece igual em todo lugar até deixar de parecer. Cada banco tem a sua sintaxe para citar identificadores, para parâmetros e para algumas funções, e o formatador precisa saber qual você usa para ler a consulta direito:
- SQL Server cita identificadores com colchetes:
[dbo].[users]. - MySQL envolve os identificadores em crases, o mesmo caractere usado para código no Markdown.
- PostgreSQL usa aspas duplas para identificadores e
$1,$2para parâmetros. - SQLite aceita vários estilos, por compatibilidade.
Passe select [id] from [dbo].[users] para um formatador configurado como SQL padrão e ele falha no primeiro colchete; configure como SQL Server (T-SQL) e ele formata sem problema. O Formatador SQL deste site aceita SQL padrão, PostgreSQL, MySQL, SQL Server e SQLite, e quando não consegue ler a consulta mostra a linha e a coluna do problema, como uma aspa sem fechamento em where name = 'Ana.
Hábitos que evitam bugs
Formatar é sobre leitura, mas alguns hábitos de escrita andam junto:
- Liste as colunas em vez de
SELECT *no código da aplicação. Uma coluna nova na tabela não deveria mudar, sem ninguém ver, o que o seu código recebe. - Qualifique as colunas com o alias da tabela em qualquer consulta com join.
o.created_atnão fica ambíguo quando alguém acrescenta umcreated_atem outra tabela. - Coloque condição de join no
ONe filtro noWHERE, e pense duas vezes quando uma condição doWHEREusa o lado opcional de umLEFT JOIN, como no exemplo do começo. - Use parâmetros, nunca concatenação de texto, para valores que vêm do usuário. Isso evita SQL injection e deixa o banco reaproveitar planos de execução.
- Escreva
ORDER BYsempre que a ordem importar. Sem ele, o banco pode devolver as linhas em qualquer ordem, e essa ordem pode mudar.
Formatação no fluxo do time
Combinar um estilo é mais fácil quando ninguém precisa cobrar na mão. Guarde as consultas em arquivos .sql, rode um formatador antes do commit e revise a versão formatada. Para conferências rápidas, como uma consulta colada de um log ou da mensagem de um colega, um formatador online que roda no navegador resolve, desde que a consulta não saia da sua máquina. Consultas podem ter nomes de tabelas, dados de clientes em literais, como CPF e e-mail, e a estrutura interna do sistema, então evite ferramentas que fazem upload delas.
Erros comuns
- Revisar consultas longas de uma linha sem formatar antes.
- Misturar palavras-chave em maiúsculas e minúsculas no mesmo código.
- Formatar com o dialeto errado e "corrigir" erros que não existem.
- Usar
SELECT *no código da aplicação. - Filtrar sem querer o lado opcional de um
LEFT JOINnoWHERE. - Montar consultas concatenando entrada do usuário.
Resumo
SQL legível coloca cada cláusula no seu bloco, cada coluna e cada condição na sua linha e as palavras-chave numa caixa consistente. Formatar nunca muda o que a consulta faz, então formate à vontade, mas escolha o dialeto certo para o formatador entender os seus identificadores e parâmetros. Somado a colunas explícitas, nomes qualificados e parâmetros, isso transforma consultas em código fácil de revisar.
Leia também
Base64 não é criptografia — o que é, quando usar e a variante URL-safe
Como o Base64 transforma bytes em texto, por que ele não esconde nada, como tratar acentos e emoji do jeito certo e quando usar o alfabeto URL-safe.
5 de novembro de 20265 min de leituraFerramenta: Codificador/Decodificador Base64
A regex que trava o navegador — backtracking catastrófico explicado
Por que uma expressão regular curta pode levar segundos ou travar a página, como reconhecer quantificadores aninhados e como reescrever o padrão.
5 de novembro de 20266 min de leituraFerramenta: Testador de Regex