QA Learning / PostgreSQL

Módulo 1: Ler dados no Postgres

SELECT, WHERE, ORDER BY, LIMIT/OFFSET, DISTINCT e as manias do Postgres

Antes de começar

O básico de leitura é idêntico ao da Trilha 1: SELECT colunas FROM tabela WHERE condição. O que muda no Postgres são detalhes que, se você não souber, travam sua query:

  • Aspas. Texto vai entre aspas simples: 'SP'. Aspas duplas são pra nome de coluna/tabela ("Nome Estranho"). Se você escrever "SP" o Postgres procura uma coluna chamada SP e dá erro.
  • Cast rápido com ::: '2025-03-01'::date, valor_total::int. É o jeito curto de CAST(x AS tipo).
  • LIMIT n OFFSET m: pega n linhas, pulando as m primeiras (paginação).
  • ILIKE: igual ao LIKE, mas ignora maiúsc./minúsc. (só existe no Postgres).

Olhar de QA: toda investigação começa com um SELECT ... WHERE: "me mostra as linhas onde algo está estranho".

Dois exemplos pra ver funcionando

Já rodam sozinhos quando o banco carrega. Mexe à vontade e clique Rodar de novo.

Teoria

  • SELECT colunas FROM tabela: o quê e de onde. SELECT * = todas as colunas.
  • WHERE condição: filtra linhas. = <> > < >= <=, AND, OR, NOT.
  • BETWEEN a AND b: intervalo inclusivo. IN (v1, v2, …): valor numa lista.
  • LIKE 'Silva%' / ILIKE '%silva%': texto por padrão, % = qualquer coisa, _ = 1 caractere. ILIKE ignora caixa.
  • ORDER BY coluna ASC|DESC: ordena. LIMIT n: corta nas n primeiras. OFFSET m: pula m.
  • DISTINCT: remove linhas repetidas do resultado.
  • AS: apelido de coluna, preco * 0.9 AS preco_promo.

Exemplos de aplicação

Um exemplo montado pra cada item da teoria acima. Não precisa rodar, é pra ver a cara do recurso e entender cada pedaço. Os valores são ilustrativos.

SELECT ... FROM tabela

SELECT nome, categoria, preco
FROM produtos;

SELECT diz quais colunas aparecem; FROM produtos diz de qual tabela. SELECT * traria todas. Igual ao SQLite. A diferença do Postgres começa nos tipos das colunas (aqui preco é numeric de verdade, não "número solto").

WHERE + operadores

SELECT id, status, valor_total
FROM pedidos
WHERE status <> 'cancelado' AND valor_total >= 1000;

Passa só quem satisfaz as duas condições (AND). No Postgres, texto tem que ir entre aspas simples. Aspas duplas significam nome de coluna e dariam erro.

BETWEEN / IN

SELECT nome, data_cadastro
FROM clientes
WHERE data_cadastro BETWEEN DATE '2025-01-01' AND DATE '2025-03-31'
  AND estado IN ('SP', 'RJ', 'MG');

BETWEEN a AND b é intervalo inclusivo nas duas pontas. IN (...) testa se o valor é um da lista. Como data_cadastro é date, dá pra escrever DATE '2025-01-01' pra deixar claro que é data, não texto.

LIKE / ILIKE

SELECT nome, email
FROM clientes
WHERE nome ILIKE '%silva%';

LIKE compara texto com molde: % = qualquer sequência, _ = 1 caractere. ILIKE é a versão que ignora maiúscula/minúscula: '%silva%' pega "Silva", "SILVA", "da Silva". Isso é do Postgres; no SQLite não existe ILIKE.

ORDER BY / LIMIT / OFFSET

SELECT id, valor_total
FROM pedidos
ORDER BY valor_total DESC
LIMIT 10 OFFSET 10;

ORDER BY ... DESC ordena do maior pro menor. LIMIT 10 pega 10 linhas; OFFSET 10 pula as 10 primeiras antes disso, ou seja, esta query traz do 11º ao 20º pedido mais caro. É o padrão de paginação.

DISTINCT

SELECT DISTINCT estado
FROM clientes
ORDER BY estado;

Colapsa linhas repetidas: em vez do estado de cada cliente, devolve cada estado uma vez. Bom pra saber "quais valores existem nessa coluna".

AS (apelido)

SELECT nome,
       preco AS preco_cheio,
       preco * 0.9 AS preco_promo
FROM produtos;

AS renomeia a coluna no resultado: troca um nome ou dá nome a coluna calculada (preco * 0.9). O AS é opcional (preco AS preco_cheio = preco preco_cheio), mas escrever deixa claro.

Pegadinhas deste módulo

Os erros que quase todo mundo comete aqui. Ler agora poupa meia hora de confusão depois, e alguns deles são a causa de relatório errado em projeto real.

  • Texto diferencia maiúscula de minúscula. WHERE cidade = 'campinas' não acha 'Campinas' e devolve zero linhas sem dar erro. Zero linha não é sinal de que está tudo certo: é sinal de que você precisa conferir a condição.
  • LIMIT sem ORDER BY não significa nada. "As 5 primeiras" de um resultado não ordenado são 5 linhas quaisquer, e podem mudar entre execuções. Se o enunciado fala em "maiores" ou "mais recentes", tem que haver ORDER BY.
  • LIKE '%Silva%' ≠ LIKE 'Silva'. Sem os %, o LIKE vira uma igualdade. É a causa mais comum de "minha busca não acha nada".
  • Aspas simples para texto, nada para número. WHERE preco > '500' pode funcionar por acidente e comparar como texto, e aí '90' fica maior que '500', porque 9 vem depois de 5 no alfabeto.
  • BETWEEN inclui as duas pontas. BETWEEN 100 AND 200 pega o 100 e o 200. Quando o requisito diz "acima de 100", BETWEEN está errado, e essa diferença de uma linha é exatamente o tipo de defeito que a análise de valor limite procura.
  • No Postgres, tipo importa de verdade. Diferente do SQLite, comparar texto com número dá erro em vez de resultado estranho. Isso é bom: o erro aparece na hora, em vez de virar número errado no relatório.

Prática

Escreva a query e clique Rodar (ou Ctrl+Enter). Tenta antes de abrir a resposta.

carregando banco…

Query livre

Espaço pra explorar. (No Postgres a lista de tabelas fica em information_schema.)

Terminou este módulo? Marque: o ✓ aparece no índice da trilha e a barra de progresso anda no começo do site. Fica salvo só no seu navegador.