Boas Práticas de SQL: Consultas Legíveis e Fáceis de Manter
Lição 10.1 · Tempo de leitura: ~8 min
As boas práticas de SQL são os hábitos de formatação e de nomes que tornam uma consulta fácil de ler, rever e alterar. Nesta lição, você vai aprender a dispor as cláusulas e as colunas, a dar nomes a tabelas, colunas e aliases, quando os comentários ajudam, que hábitos evitam erros e como transformar uma consulta numa só linha em código que a sua equipe consegue manter.
No módulo anterior, você trabalhou com views e tabelas temporárias, e as suas consultas cresceram para muitas junções e vários passos. Nesse tamanho, a qualidade do código importa tanto quanto a correção: o SQL é lido muito mais vezes do que é escrito, pelos colegas na revisão e por você mesmo algumas semanas depois.
Um código bem estruturado torna os erros visíveis, acelera as revisões e facilita a evolução das consultas. Nenhuma destas regras muda o que o banco de dados faz; mudam a rapidez com que uma pessoa entende a consulta.
Por Que o Estilo de Código Importa
Uma consulta de 5 a 10 linhas entende-se num relance. Um relatório com muitos JOIN, subconsultas ou CTEs não, e um estilo consistente ajuda-o a:
- Encontrar erros mais depressa: um filtro errado ou uma condição de junção em falta salta à vista num código limpo.
- Estender consultas com segurança: uma nova coluna ou condição tem um lugar óbvio.
- Trabalhar em equipe: todos leem o código com a mesma disposição, e as revisões focam-se na lógica e não no estilo.
Formatação e Indentação
O SQL ignora espaços e a capitalização das palavras-chave, por isso a disposição depende de você. Estas são as convenções mais usadas.
Palavras-Chave em Maiúsculas
Escreva as palavras-chave do SQL (SELECT, FROM, WHERE, JOIN, GROUP BY) em maiúsculas e os nomes em minúsculas. Assim a estrutura da consulta destaca-se dos dados que ela usa.
-- Difícil de percorrer
select title, rental_rate from film where rating = 'G';
-- Mais fácil de percorrer
SELECT title, rental_rate
FROM film
WHERE rating = 'G';
Resultado: as duas consultas devolvem os mesmos 178 filmes; só a disposição muda.
Uma Cláusula por Linha
Comece cada cláusula principal numa nova linha. Quando o SELECT ou o GROUP BY têm muitas colunas, coloque cada uma na sua linha, indentada:
SELECT
customer_id,
first_name,
last_name,
email
FROM customer
WHERE active = 1
ORDER BY last_name;
Com uma coluna por linha, acrescentar ou remover uma coluna altera uma só linha, e o diff na revisão mostra exatamente essa linha.
Convenções de Nomes
Minúsculas e snake_case
O padrão de facto são nomes em minúsculas com sublinhados entre as palavras: customer_orders, total_amount, e não CustomerOrders ou TotalAmount. Os bancos de dados tratam a capitalização dos identificadores de formas diferentes: o PostgreSQL converte nomes sem aspas para minúsculas, e o MySQL em Linux distingue maiúsculas de minúsculas nos nomes de tabelas. O snake_case evita estas surpresas.
Prefixos Consistentes
Algumas equipes marcam os tipos de objeto com prefixos, como v_ para views (v_active_customers) e tmp_ para tabelas temporárias (tmp_monthly_report). O Sakila não usa prefixos: as suas views chamam-se customer_list, film_list, sales_by_film_category. As duas abordagens funcionam; o importante é escolher uma regra para todo o banco.
SELECT category, total_sales
FROM sales_by_film_category
ORDER BY total_sales DESC
LIMIT 3;
Resultado: as três categorias com mais vendas: Sports, Sci-Fi e Animation.
Aliases Claros
Aliases de Tabelas
Use aliases curtos mas com significado, como as primeiras letras do nome da tabela. Aliases como t1, t2, a, b obrigam o leitor a procurar o que cada um significa:
-- Pouco claro: o que são t1 e t2?
SELECT t1.first_name, t2.amount
FROM customer t1
JOIN payment t2 ON t1.customer_id = t2.customer_id;
-- Claro
SELECT c.first_name, p.amount
FROM customer c
JOIN payment p ON c.customer_id = p.customer_id;
Nomes para Colunas Calculadas
Dê um nome a cada agregação e expressão com AS. Uma coluna de relatório chamada COUNT(*) é difícil de usar numa aplicação ou numa folha de cálculo:
SELECT
c.name AS category_name,
COUNT(*) AS film_count,
AVG(f.replacement_cost) AS avg_replacement_cost
FROM film f
JOIN film_category fc ON f.film_id = fc.film_id
JOIN category c ON fc.category_id = c.category_id
GROUP BY c.name
ORDER BY film_count DESC;
Resultado: 16 categorias com nomes de colunas claros; Sports tem mais filmes, 74.
Comentários
Os comentários explicam por que o código faz algo quando o motivo não é óbvio a partir do próprio código: uma regra de negócio, um filtro invulgar, um problema conhecido nos dados.
- Comentários de uma linha (
--) explicam um filtro ou uma fórmula. - Comentários de bloco (
/* ... */) descrevem a finalidade de um script.
/*
Relatório: gastos dos clientes em julho de 2005
Usado por: newsletter mensal de marketing
*/
SELECT
customer_id,
SUM(amount) AS july_spent
FROM payment
WHERE payment_date >= '2005-07-01' -- o mês inteiro,
AND payment_date < '2005-08-01' -- incluindo 31 de julho depois da meia-noite
GROUP BY customer_id
ORDER BY july_spent DESC;
Resultado: 599 clientes com os seus gastos em julho de 2005.
Não comente o que o código já diz: -- seleciona customer id por cima de SELECT customer_id só acrescenta ruído, e comentários desatualizados são piores do que nenhum.
Hábitos Que Tornam as Consultas Mais Seguras
- Liste as colunas necessárias em vez de
SELECT *em relatórios, views e código de aplicações. Assim, uma nova coluna na tabela não muda nem torna mais lento o seu resultado. - Use
JOIN ... ONexplícito em vez de listar tabelas separadas por vírgulas noFROM. A condição de junção fica junto à tabela e é mais difícil de esquecer. - Prefira intervalos de datas semiabertos (
>= início AND < fim) aBETWEENem colunas de data e hora, como no exemplo acima. - Combine um estilo e automatize-o. Formatadores e linters como o SQLFluff aplicam as regras por você, e as revisões deixam de discutir espaços.
Exemplo Prático: Limpar uma Consulta Confusa
Antes: tudo numa linha, sem nomes para as colunas calculadas:
select f.title,c.name,count(r.rental_id) from film f join film_category fc on f.film_id=fc.film_id join category c on fc.category_id=c.category_id join inventory i on f.film_id=i.film_id join rental r on i.inventory_id=r.inventory_id group by f.title,c.name having count(r.rental_id)>30 order by count(r.rental_id) desc;
Depois: uma cláusula por linha, junções alinhadas, colunas com nome:
SELECT
f.title,
c.name AS category_name,
COUNT(r.rental_id) AS rental_count
FROM film f
JOIN film_category fc ON f.film_id = fc.film_id
JOIN category c ON fc.category_id = c.category_id
JOIN inventory i ON f.film_id = i.film_id
JOIN rental r ON i.inventory_id = r.inventory_id
GROUP BY f.title, c.name
HAVING COUNT(r.rental_id) > 30
ORDER BY rental_count DESC;
Resultado: as duas versões devolvem os mesmos 16 filmes alugados mais de 30 vezes, liderados por BUCKET BROTHERHOOD com 34 aluguéis.
Na segunda versão vê-se num relance que tabelas são juntadas e como, o que é contado e como o resultado é filtrado e ordenado.
Principais conclusões:
- Escreva as palavras-chave em maiúsculas e os nomes em minúsculas, em
snake_case. - Comece cada cláusula numa nova linha e escreva listas longas de colunas uma por linha.
- Use aliases de tabelas com significado e dê nome a cada coluna calculada com
AS. - Comente o porquê, não o quê: regras de negócio e filtros pouco óbvios.
- Liste as colunas em vez de
SELECT *, useJOIN ... ONexplícito e intervalos de datas semiabertos. - Combine na equipe um único estilo e aplique-o com um formatador ou linter.
Perguntas Frequentes
As palavras-chave do SQL têm de estar em maiúsculas?
Não. Os bancos de dados aceitam palavras-chave em qualquer capitalização. As maiúsculas são uma convenção que torna a estrutura das consultas longas mais visível; o mais importante é que toda a equipe use o mesmo estilo.
O que torna o código SQL fácil de manter?
Formatação consistente, nomes e aliases claros, colunas calculadas com nome e comentários curtos onde a lógica não é óbvia. Esse código é mais fácil de rever, alterar e depurar, também por quem não o escreveu.
Por que evitar SELECT * em consultas de produção?
SELECT * devolve todas as colunas, incluindo as acrescentadas à tabela mais tarde. Isso pode quebrar aplicações que esperam um conjunto fixo de colunas, transferir mais dados do que o necessário e impedir o uso de índices de cobertura. Liste as colunas de que precisa.
Como limpar uma consulta SQL confusa?
Divida-a em cláusulas em linhas separadas (SELECT, FROM, JOIN, WHERE, GROUP BY, ORDER BY), indente as listas de colunas, substitua os aliases pouco claros, dê nome às colunas calculadas e acrescente um comentário onde a lógica precisa de explicação. Execute a versão antiga e a nova para confirmar que os resultados coincidem.