SQL WHERE

Até aqui, todo SELECT trouxe todas as linhas da tabela: os 30 clientes, os 45 produtos. Mas as perguntas do dia a dia da Loja Aurora quase nunca são sobre todos. "Quais clientes são do Piauí?" "Quais produtos acabaram no estoque?" "Quem são as vendedoras?" Para pedir só as linhas que interessam, você acrescenta ao SELECT a cláusula WHERE (em inglês, "onde"): mostre só as linhas onde tal coisa for verdade.

Você vai aprender
  • A filtrar as linhas com WHERE coluna = valor, e onde o WHERE entra na consulta.
  • Como o banco decide, linha por linha, o que entra no resultado.
  • A regra de ouro: números sem aspas, textos entre aspas simples.
  • Por que 'PI' e 'pi' não são a mesma coisa, e por que "nenhuma linha" não é erro.
  • Como escrever um texto que tem apóstrofo, como Loja D'Água.
  • Os erros reais do SQLite: aspas duplas, texto sem aspas, WHERE no lugar errado.

A ideia: separar as fichas que servem

A Ana tem na mão as 30 fichas de clientes e precisa mandar um catálogo para quem mora no Piauí. Ela passa as fichas uma por uma e, em cada uma, olha o campo "estado": se for PI, a ficha vai para a pilha do catálogo; se não for, fica de fora. No fim, a pilha tem só os clientes do Piauí.

O WHERE é essa pergunta feita para cada ficha. Você escreve uma condição (estado = 'PI'), e o banco testa a condição em cada linha da tabela. As linhas em que ela é verdadeira entram no resultado; as outras ficam de fora.

PartePergunta que respondeExemplo
SELECTQuais colunas mostrar?SELECT nome, cidade
FROMDe qual tabela?FROM clientes
WHEREQuais linhas?WHERE estado = 'PI'

1. O primeiro WHERE

SELECT nome, cidade
FROM clientes
WHERE estado = 'PI';
SELECT nome, cidade
As colunas que vão aparecer, como na aula Escolhendo Colunas.
FROM clientes
A tabela.
WHERE
"Onde": a partir daqui vem a condição que cada linha precisa cumprir.
estado
A coluna que vai ser testada em cada linha.
=
"É igual a". A comparação mais simples; as outras (maior, menor, diferente) estão na aula Comparações.
'PI'
O valor procurado. É um texto, por isso vai entre aspas simples.
;
Fim do comando.

Vieram 14 clientes, de cinco cidades do Piauí. Repare em duas coisas:

  • A coluna estado nem aparece no resultado. A coluna testada no WHERE não precisa estar na lista do SELECT: uma coisa é o que você mostra, outra é o que você testa.
  • A consulta foi escrita em três linhas, uma parte em cada. É o costume quando aparece o WHERE: fica fácil ler de cima para baixo.

A ordem das partes é fixa

O WHERE vem depois do FROM. Sempre: primeiro o que mostrar, depois de onde, depois quais linhas. Mais adiante você vai conhecer outras partes (ORDER BY, LIMIT), e cada uma tem o seu lugar; a seção Quando dá errado mostra o que acontece se você trocar.


2. Como o banco pensa, linha por linha

Para cada um dos 30 clientes, o banco faz o mesmo teste:

  1. Pega a linha do cliente 1, José Ribamar Silva. O estado dele é 'PI'. 'PI' = 'PI'? Sim: a linha entra no resultado.
  2. Pega a linha do cliente 2, Maria Clara Mendes: 'PI'. Sim: entra.
  3. Pega a linha do cliente 3, Ana Beatriz Sousa: 'SP'. 'SP' = 'PI'? Não: fica de fora.
  4. …e assim até o cliente 30.

Só depois de escolher as linhas o banco monta as colunas do SELECT. Por isso dá para testar o estado sem mostrá-lo: o teste acontece antes.


3. Números: sem aspas

Quando a coluna guarda um número, escreva o número sem aspas, do jeito que você escreveria numa conta. Os clientes VIP têm o número 1 na coluna vip:

SELECT nome, email
FROM clientes
WHERE vip = 1;

São 5 clientes VIP. Outro caso muito comum é procurar uma linha pelo seu número, o id. Como cada id é único, vem uma linha só:

SELECT *
FROM produtos
WHERE id = 7;

E os produtos que acabaram no estoque? Estoque igual a zero:

SELECT nome, estoque
FROM produtos
WHERE estoque = 0;

Dois produtos: o pen drive e o carrinho de fricção. (São os dois produtos que a loja deixou de vender; a coluna descontinuado deles vale 1.)

Número com casas decimais

Nos números, a casa decimal é separada por ponto, nunca por vírgula: 59.95, e não 59,95. A vírgula, no SQL, separa as colunas. A aula Comparações mostra o que acontece quando se usa a vírgula.


4. Textos: entre aspas simples

Quando o valor é um texto (um nome, uma cidade, uma sigla), ele vai entre aspas simples: 'São Paulo'. As aspas mostram ao banco onde o texto começa e onde termina, e que aquilo é um valor, e não o nome de uma coluna.

SELECT nome, cidade
FROM clientes
WHERE cidade = 'São Paulo';

O espaço no meio de 'São Paulo' não atrapalha: tudo o que está entre as aspas faz parte do texto. Mais um exemplo, com os cargos:

SELECT nome, cargo
FROM funcionarios
WHERE cargo = 'Vendedora';
Tipo do valorComo escreverExemplo
Número inteiroSem aspasWHERE vip = 1
Número com decimaisSem aspas, com pontoWHERE preco = 59.95
TextoEntre aspas simplesWHERE estado = 'PI'
DataEntre aspas simples, no formato ano-mês-diaWHERE nascimento = '1985-03-12'

As datas da Loja Aurora são guardadas como texto, no formato AAAA-MM-DD (ano, mês, dia). Por isso também levam aspas. Datas têm aula própria: Datas e Horas.

Missão: a loja vai abrir uma filial no Ceará e quer conhecer os clientes de Fortaleza. Acrescente um WHERE para mostrar só eles.

SELECT nome, cidade
FROM clientes;
SELECT nome, cidade
FROM clientes
WHERE cidade = 'Fortaleza';

5. O texto tem de ser exato

Para o SQLite, dois textos só são iguais se forem iguais letra por letra: mesmas maiúsculas, mesmos acentos, mesmos espaços. Olhe o que acontece com a sigla em minúsculas:

SELECT nome, cidade
FROM clientes
WHERE estado = 'pi';

Nenhuma linha. E nenhuma mensagem de erro, também: a consulta está certa, só que nenhum cliente tem o estado 'pi' (todos estão gravados como 'PI', em maiúsculas). Sem o acento acontece o mesmo:

SELECT nome, cidade
FROM clientes
WHERE cidade = 'Sao Paulo';

De novo, nada. Na tabela está 'São Paulo', com til. Um espaço sobrando no fim ('Ana Beatriz Sousa ') também faz a busca não achar nada.

"Nenhuma linha" não é erro

Quando o WHERE não encontra nada, o banco responde com uma tabela vazia, sem reclamar. Ele não tem como saber se você esperava encontrar alguém. Se o resultado veio vazio e você tinha certeza de que havia dados, desconfie do valor procurado: maiúsculas, acentos e espaços. Um SELECT DISTINCT estado FROM clientes; mostra como os valores estão gravados de verdade.

Existem jeitos de buscar ignorando as maiúsculas: o LIKE (aula LIKE) e as funções que convertem o texto, como lower() (aula Funções de Texto). Por enquanto, a regra é escrever o valor exatamente como ele está na tabela.


6. Texto com apóstrofo

Um dos fornecedores da loja se chama Loja D'Água. O nome tem um apóstrofo, que é o mesmo caractere da aspa simples. Como escrever esse texto, se a aspa simples marca o fim dele? O SQL padrão tem uma resposta: escreva a aspa duas vezes.

SELECT nome, cidade
FROM fornecedores
WHERE nome = 'Loja D''Água';
'
Abre o texto.
Loja D
O começo do texto.
''
Duas aspas simples seguidas, sem espaço: dentro de um texto, elas querem dizer "um apóstrofo". Não são aspas duplas ("); são duas aspas simples (' e ').
Água
O resto do texto.
'
Fecha o texto.

O resultado mostra o nome com um apóstrofo só, Loja D'Água, porque é assim que ele está gravado. As duas aspas são só o jeito de escrever o apóstrofo dentro da consulta. Com uma aspa só, o banco acha que o texto acabou em 'Loja D' e se perde; você vai ver a mensagem em Quando dá errado.


7. WHERE com o que você já sabe

O WHERE se junta a tudo o que você aprendeu nas aulas anteriores. Em quais cidades do Piauí a loja tem clientes? DISTINCT para não repetir, WHERE para ficar só com o Piauí:

SELECT DISTINCT cidade
FROM clientes
WHERE estado = 'PI';

São 5 cidades. Primeiro o WHERE escolheu os 14 clientes do Piauí; depois, o DISTINCT tirou as repetições de Teresina.

Missão: quais produtos a loja deixou de vender? Eles têm o número 1 na coluna descontinuado. Mostre o nome, o preço e o estoque deles.

SELECT nome, preco, estoque
FROM produtos;
SELECT nome, preco, estoque
FROM produtos
WHERE descontinuado = 1;

Formas diferentes de escrever a mesma condição

As três consultas abaixo trazem os mesmos 14 clientes do Piauí:

SELECT nome FROM clientes WHERE estado = 'PI';
SELECT nome FROM clientes WHERE 'PI' = estado;
SELECT nome FROM clientes WHERE estado == 'PI';

A segunda inverte os lados: 'PI' = estado é o mesmo que estado = 'PI', como 2 = x é o mesmo que x = 2. A terceira usa ==, um "igual" duplo que o SQLite aceita, mas que não é SQL padrão.

FormaQuando usar
WHERE estado = 'PI'Sempre. É o padrão, funciona em todos os bancos e é o que todo mundo espera ler
WHERE 'PI' = estadoFunciona, mas é estranho de ler. Evite
WHERE estado == 'PI'Evite: o == é uma extensão do SQLite, não faz parte do SQL padrão

Quando dá errado

Aspas duplas no lugar de aspas simples: o editor recusa, o terminal aceita calado

Quem vem de outras linguagens de programação costuma escrever texto entre aspas duplas. No editor do guia, isso dá erro:

SELECT nome, preco
FROM produtos
WHERE nome = "Mouse Sem Fio";

A mensagem diz: "não existe a coluna "Mouse Sem Fio"; isso deveria ser um texto entre aspas simples?". O próprio SQLite dá a dica. No SQL padrão, aspas duplas servem para nomes (de colunas, de tabelas), e não para textos. Então o banco procurou uma coluna chamada Mouse Sem Fio e, claro, não achou. O editor segue o padrão à risca.

Agora a mesma consulta no terminal, no sqlite3 que vem no Debian da Ana (e em muitas outras distribuições Linux):

$ sqlite3 loja.db
SQLite version 3.50.4 2025-07-30 19:33:53
Enter ".help" for usage hints.
sqlite> SELECT nome, preco FROM produtos WHERE nome = "Mouse Sem Fio";
Mouse Sem Fio|59.95
sqlite> .quit

Funcionou, sem aviso nenhum. Esse sqlite3 é "tolerante": quando não acha uma coluna com aquele nome, ele desiste de procurar e trata "Mouse Sem Fio" como texto. Parece uma gentileza, mas é uma armadilha. As aspas duplas continuam querendo dizer "nome de coluna"; o texto só vale enquanto não existir uma coluna com aquele nome. Veja o que acontece no dia em que alguém cria uma coluna chamada PI na tabela de clientes:

$ sqlite3 loja.db
SQLite version 3.50.4 2025-07-30 19:33:53
Enter ".help" for usage hints.
sqlite> SELECT count(*) FROM clientes WHERE estado = "PI";
14
sqlite> ALTER TABLE clientes ADD COLUMN PI INTEGER;          « alguém criou uma coluna chamada PI
sqlite> SELECT count(*) FROM clientes WHERE estado = "PI";
0                                                            « agora "PI" é a coluna nova, vazia
sqlite> SELECT count(*) FROM clientes WHERE estado = 'PI';
14                                                           « com aspas simples, nada muda
sqlite> .quit

A mesma consulta, sem mudar uma letra, passou de 14 clientes para 0, e de novo sem erro nenhum. Com "PI", o banco agora compara o estado com a coluna PI (que está vazia). Com 'PI', ele compara com o texto PI, hoje e sempre. (O ALTER TABLE, que acrescenta uma coluna, tem aula própria: ALTER TABLE.)

Como consertar: textos sempre entre aspas simples: WHERE nome = 'Mouse Sem Fio'. Assim a consulta funciona igual no editor, no terminal e em qualquer banco.

Nos outros bancos

Por que tanta gente escreve aspas duplas? Porque alguns bancos aceitam. No MySQL, um texto pode ficar entre aspas simples ou duplas (a não ser que o modo ANSI_QUOTES esteja ligado; aí as duplas viram nomes, como no padrão). No PostgreSQL, aspas duplas são sempre nomes, e textos só vão entre aspas simples, como no editor do guia. Com aspas simples, a consulta funciona em todos eles; é por isso que o guia usa só elas.

Texto sem aspas
SELECT nome, cidade
FROM clientes
WHERE estado = PI;

no such column: PI. Sem aspas, PI parece o nome de uma coluna, e a tabela clientes não tem coluna nenhuma chamada PI. É o mesmo erro de um nome de coluna digitado errado. Como consertar: WHERE estado = 'PI'.

O apóstrofo sem dobrar
SELECT nome, cidade
FROM fornecedores
WHERE nome = 'Loja D'Água';

near "Água": syntax error. O banco leu o texto 'Loja D' (a segunda aspa fechou o texto) e, logo depois, encontrou a palavra Água, que não faz sentido ali. Como consertar: dobre o apóstrofo: 'Loja D''Água'.

WHERE antes do FROM
SELECT nome, cidade
WHERE estado = 'PI'
FROM clientes;

near "FROM": syntax error. A ordem das partes é fixa: SELECT, FROM, WHERE. O banco aceitou o WHERE ali (ele acha que é uma consulta sem tabela, como o SELECT 2 + 2), mas não esperava um FROM depois dele. Como consertar: mova o WHERE para depois do FROM.

Procurar quem não tem valor com = NULL

A Ana quer os clientes sem email. Ela sabe que são 3, mas:

SELECT nome, email
FROM clientes
WHERE email = NULL;

Nenhuma linha, e nenhum erro. O NULL quer dizer "sem valor", e nada é "igual" a um valor que não existe, nem outro NULL. Para procurar os campos vazios existe um teste próprio, o IS NULL, que você vai aprender na aula IS NULL e IS NOT NULL. Por enquanto, lembre: = NULL nunca encontra nada.

Missão: a Ana quer os clientes de Recife, mas a consulta dá erro. Conserte.

SELECT nome, cidade
FROM clientes
WHERE cidade = "Recife";
SELECT nome, cidade
FROM clientes
WHERE cidade = 'Recife';

Referência rápida

EscritaO que faz
SELECT … FROM … WHERE condição;Mostra só as linhas em que a condição é verdadeira
WHERE vip = 1Número: sem aspas
WHERE preco = 59.95Número com decimais: ponto, sem aspas
WHERE estado = 'PI'Texto: entre aspas simples, exatamente como está gravado
WHERE nome = 'Loja D''Água'Apóstrofo dentro do texto: duas aspas simples
SELECT DISTINCT cidade … WHERE …Filtra as linhas e depois tira as repetições
SintomaCausa provável
no such column: "Mouse Sem Fio" - should this be a string literal in single-quotes? (no editor)Texto entre aspas duplas: troque por aspas simples
No terminal, "PI" funciona, mas um dia para de funcionar, sem erroAspas duplas viram texto só enquanto não existe coluna com aquele nome: use aspas simples
no such column: PITexto sem aspas
near "Água": syntax errorApóstrofo dentro do texto sem dobrar
near "FROM": syntax errorWHERE antes do FROM
Nenhuma linha, sem erroNenhuma linha cumpre a condição: confira maiúsculas, acentos e espaços (ou é um = NULL)

Exercícios

1. Os clientes de Teresina

Complete a palavra-chave e as aspas:

SELECT nome FROM clientes cidade = ;

2. Os livros

Os livros são a categoria de número 4. Complete o valor:

SELECT nome, preco FROM produtos WHERE categoria_id = ;

3. Qual destas condições está escrita do jeito certo (e funciona igual no editor e no terminal)?

4. SELECT nome FROM clientes WHERE cidade = 'fortaleza'; trouxe nenhuma linha, sem erro. Por quê?

5. Como se escreve, dentro de uma consulta, o nome do fornecedor Loja D'Água?

6. Em que ordem as partes da consulta são escritas?

Missão final: a equipe da Luana

Missão: a supervisora Luana Castelo é a funcionária de número 5. Na tabela funcionarios, a coluna chefe_id guarda o número do chefe de cada um. Mostre o nome e o cargo de quem trabalha diretamente com a Luana.

SELECT nome, cargo
FROM funcionarios;
SELECT nome, cargo
FROM funcionarios
WHERE chefe_id = 5;

São três: Igor, Sofia e Davi. Experimente trocar o 5 por 1 para ver a equipe da gerente, Marta.


Resumo

  • WHERE ("onde") filtra as linhas: o banco testa a condição em cada linha e só mostra aquelas em que ela é verdadeira.
  • A ordem é fixa: SELECT → FROM → WHERE. A coluna testada não precisa aparecer no SELECT.
  • Números sem aspas (com ponto nos decimais); textos e datas entre aspas simples.
  • Aspas duplas são para nomes, não para textos. No editor, "Mouse Sem Fio" dá no such column; no sqlite3 do terminal, passa calado e quebra no dia em que existir uma coluna com aquele nome.
  • Comparar texto é exato: maiúsculas, acentos e espaços contam. "Nenhuma linha" não é erro; confira o valor.
  • Apóstrofo dentro do texto se escreve com duas aspas simples: 'Loja D''Água'.
  • = NULL nunca encontra nada; para os campos vazios existe o IS NULL.