SQLWHEREtutorialbeginner

O que é WHERE no SQL? Filtragem de linhas para iniciantes

WHERE é o filtro de linhas no SQL. Em linguagem simples e com muitos exemplos: =, IN, BETWEEN, LIKE, IS NULL e AND/OR. Tabelas antes e depois, armadilhas para iniciantes e uma prática rápida no final.

8 min de leituraSQL · WHERE · tutorial · beginner

WHERE é um filtro de linhas. Sem ele, a sua consulta retorna todas as linhas da tabela. Com ele, apenas as linhas que você realmente quer.

Pense em uma tabela como um armário cheio de roupas. SELECT * FROM clothes significa "me dê tudo o que está aí". SELECT * FROM clothes WHERE color = 'red' significa "me dê apenas as peças vermelhas". WHERE é esse filtro.

Por que WHERE importa

As tabelas do mundo real guardam dezenas de milhares — às vezes milhões — de linhas. Retornar todas elas é:

  • Lento: o banco de dados faz mais trabalho e a rede transporta mais dados.
  • Inútil: você normalmente quer usuários, pedidos ou produtos específicos — não a tabela inteira.

WHERE corta o ruído do lado do banco de dados antes que os dados cheguem até você. É uma das primeiras ferramentas que todo desenvolvedor e analista de SQL aprende — sem ele você não vai longe.

Como funciona por baixo dos panos

Quando você escreve SELECT ... FROM users WHERE age > 18, o banco de dados faz algo simples:

  1. Lê cada linha de users uma a uma.
  2. Insere o valor age da linha na condição age > 18.
  3. Se a condição for TRUE, a linha vai para o resultado. Se for FALSE, é descartada.

WHERE é apenas um teste de sim/não aplicado a cada linha.

Sintaxe básica

SELECT name, age
FROM users
WHERE age > 18;

Linha por linha:

  • SELECT name, age — quais colunas você quer de volta.
  • FROM users — de qual tabela.
  • WHERE age > 18 — quais linhas manter (apenas pessoas com mais de 18 anos).

O resultado é uma lista de usuários adultos, apenas com o nome e a idade (sem e-mail, telefone ou qualquer outra coisa que não pedimos).

O que você pode colocar depois de WHERE

1. Comparações

  • = — igual
  • <> ou != — diferente
  • >, <, >=, <= — maior que, menor que, etc.
SELECT * FROM products WHERE price > 1000;
SELECT * FROM users    WHERE country = 'Russia';
SELECT * FROM orders   WHERE status <> 'cancelled';

Exemplo resolvido. Dada a tabela products:

idnameprice
1Mug350
2Kettle1200
3Microwave5000
4Spoon80

Consulta:

SELECT name, price FROM products WHERE price > 1000;

Resultado:

nameprice
Kettle1200
Microwave5000

Mug e Spoon ficaram de fora — o preço deles está abaixo de 1000.

2. Operadores lógicos AND, OR, NOT

  • AND — ambas as condições precisam ser verdadeiras
  • OR — pelo menos uma precisa ser verdadeira
  • NOT — nega uma condição
SELECT * FROM users
WHERE country = 'Russia' AND age >= 21;

SELECT * FROM orders
WHERE status = 'paid' OR status = 'shipped';

SELECT * FROM products
WHERE NOT in_stock;

AND versus OR, na prática. Tabela users:

idnamecountryage
1AnnaRussia25
2BobUSA30
3VeraRussia17
4GrishaRussia40

Consulta com AND (ambas as condições):

SELECT name FROM users WHERE country = 'Russia' AND age >= 21;

Resultado:

name
Anna
Grisha

Vera ficou de fora (17, abaixo de 21). Bob ficou de fora (não é Russia). Apenas Anna e Grisha satisfazem ambas as condições ao mesmo tempo.

A mesma consulta com OR (pelo menos uma):

SELECT name FROM users WHERE country = 'Russia' OR age >= 21;

Resultado:

name
Anna
Bob
Vera
Grisha

Agora os quatro correspondem. Anna, Vera, Grisha — Russia. Bob — 30 (≥ 21). Cada linha tem pelo menos uma condição verdadeira. Uma diferença reveladora entre AND e OR.

3. Um conjunto de valores: IN

Quando você quer verificar se um valor é uma de várias opções:

SELECT * FROM users
WHERE country IN ('Russia', 'Belarus', 'Kazakhstan');

É a forma abreviada de:

WHERE country = 'Russia' OR country = 'Belarus' OR country = 'Kazakhstan'

IN se lê de forma mais limpa, especialmente quando a lista cresce.

Também existe NOT IN:

SELECT * FROM users WHERE country NOT IN ('USA', 'Canada');

4. Um intervalo: BETWEEN

Ótimo para datas, números — qualquer coisa ordenável.

SELECT * FROM orders
WHERE created_at BETWEEN '2024-01-01' AND '2024-12-31';

SELECT * FROM products
WHERE price BETWEEN 100 AND 500;

Importante: BETWEEN inclui ambas as extremidades. BETWEEN 100 AND 500 é o mesmo que >= 100 AND <= 500. O 100 exato e o 500 exato também entram.

5. Busca de texto: LIKE

Para correspondências parciais de strings:

-- Todos com um endereço do gmail
SELECT * FROM users WHERE email LIKE '%@gmail.com';

-- Nomes que começam com 'A'
SELECT * FROM users WHERE name LIKE 'A%';

-- Nomes que contêm 'nn' em qualquer lugar
SELECT * FROM users WHERE name LIKE '%nn%';

Dois curingas no LIKE:

  • % — qualquer quantidade de caracteres (inclusive zero)
  • _ — exatamente um caractere

Exemplo com _: WHERE phone LIKE '+1 555___' — telefones que começam com +1 555 seguidos de três caracteres quaisquer.

6. NULL é uma coisa à parte

Esta é a armadilha mais comum para iniciantes. NULL no SQL não é um valor — é a ausência de um. "Desconhecido". "Não preenchido".

E você não pode compará-lo com =. Em lugar nenhum. Até NULL = NULL não retorna TRUE, mas sim NULL de novo ("desconhecido igual a desconhecido — quem sabe").

-- ERRADO: não retorna nada, mesmo que existam NULLs
SELECT * FROM users WHERE deleted_at = NULL;

-- CERTO
SELECT * FROM users WHERE deleted_at IS NULL;
SELECT * FROM users WHERE deleted_at IS NOT NULL;

Lembre-se: para NULL — apenas IS NULL e IS NOT NULL, nunca = nem <>.

Exemplo maior: antes e depois

Dada a tabela orders:

iduser_idamountstatuscountry
110500paidRussia
2111500paidUSA
312200cancelledRussia
4133000paidRussia
514800pendingRussia
6154500paidBelarus

Objetivo: "pedidos pagos da Russia, com valor acima de 1000".

Consulta:

SELECT id, amount
FROM orders
WHERE status = 'paid'
  AND country = 'Russia'
  AND amount > 1000;

Resultado:

idamount
43000

Quem ficou de fora e por quê:

  • #1: pago e da Russia, mas valor 500 — não passa em amount > 1000.
  • #2: pago e grande o suficiente, mas USA — não é Russia.
  • #3: cancelado — não está pago.
  • #5: pendente — não está pago.
  • #6: pago e grande o suficiente, mas Belarus — não é Russia.

Apenas o #4 satisfaz as três condições de uma vez (AND).

Agora troque AND por OR nos mesmos dados:

SELECT id, amount, country, status
FROM orders
WHERE status = 'paid'
   OR country = 'Russia'
   OR amount > 1000;

Resultado:

idamountcountrystatus
1500Russiapaid
21500USApaid
3200Russiacancelled
43000Russiapaid
5800Russiapending
64500Belaruspaid

Todas as seis linhas passam. Cada linha atende a pelo menos uma das três condições. Um lembrete sólido de quão diferentes são AND e OR.

Mais um: datas e texto

A mesma tabela orders, com datas e e-mail:

idcreated_atemailamount
12024-03-10anna@gmail.com500
22024-06-22bob@yandex.ru1500
32024-11-05vera@gmail.com200
42025-01-15grisha@mail.ru3000

Objetivo: "pedidos de 2024, apenas de usuários do gmail".

SELECT id, email, amount
FROM orders
WHERE created_at BETWEEN '2024-01-01' AND '2024-12-31'
  AND email LIKE '%@gmail.com';

Resultado:

idemailamount
1anna@gmail.com500
3vera@gmail.com200

O pedido #2 fica de fora (yandex.ru, não gmail). O #4 fica de fora (2025, não 2024).

Erros comuns de iniciante

1. Comparar NULL com =. Nunca funciona. Use IS NULL / IS NOT NULL.

2. As aspas. Strings e datas vão entre aspas simples '...'. Números não precisam de aspas. Aspas duplas "..." no PostgreSQL servem para identificadores (nomes de coluna), não para strings.

-- Certo
WHERE name = 'Alice' AND age = 30

-- Errado: isto procura uma coluna chamada Alice — erro
WHERE name = "Alice"

3. Confundir AND e OR. Use sempre parênteses nas condições compostas para tornar a precedência explícita:

-- Você quer: país Russia AND (homens com mais de 21 OR mulheres com mais de 18)
WHERE country = 'Russia'
  AND ((sex = 'M' AND age > 21) OR (sex = 'F' AND age > 18));

Sem parênteses, a lógica pode parar em um lugar completamente diferente do que você pretendia.

4. Filtrar agregações com WHERE. Não funciona. WHERE é executado antes do agrupamento e não sabe nada de COUNT, SUM, etc. Para condições sobre agregações existe o HAVING.

-- Errado
SELECT country, COUNT(*) FROM users
GROUP BY country
WHERE COUNT(*) > 100;

-- Certo
SELECT country, COUNT(*) FROM users
GROUP BY country
HAVING COUNT(*) > 100;

5. Sensibilidade a maiúsculas e minúsculas. WHERE name = 'Alice' e WHERE name = 'alice' são condições diferentes na maioria dos bancos de dados. Se as maiúsculas não devem importar, normalize os dois lados:

WHERE LOWER(name) = 'alice'

6. Esquecer o AND entre condições. Várias condições precisam de um AND ou OR explícito — aqui não há vírgula implícita.

-- Errado (sem AND)
WHERE country = 'Russia' age > 21

-- Certo
WHERE country = 'Russia' AND age > 21

Resumo rápido

  • WHERE filtra linhas em SELECT, UPDATE e DELETE.
  • As condições usam comparações, AND/OR/NOT, IN, BETWEEN, LIKE.
  • Para NULL, use IS NULL / IS NOT NULL — as comparações normais falham silenciosamente.
  • Quanto mais apertado for o seu WHERE, menos dados o banco de dados retorna — e mais rápido tudo fica.
  • Use sempre parênteses nas condições compostas AND/OR. Não adivinhe a precedência, escreva-a.

Experimente você mesmo

Três exercícios de dificuldade crescente sobre a mesma tabela orders:

  1. Encontre todos os pedidos pagos acima de 500.
  2. Encontre os pedidos de junho de 2024 de usuários fora da Russia.
  3. Encontre os pedidos em que delivered_at ainda não está definido (ou seja, NULL).

Escreva primeiro as consultas por conta própria e depois confira. Se não fizerem sentido de imediato — é totalmente normal. SQL se lê da esquerda para a direita como o inglês, e vira automático com a repetição.

Pratique com exercícios reais

Resolva exercícios no treinador de SQL com correção instantânea e dicas.

Abrir o treinador