CASE é o If/Else do SQL
O CASE é como você coloca lógica condicional dentro de uma query no SQLite. Ele percorre os ramos WHEN na ordem, escolhe o primeiro que casar e devolve o valor que vem depois do THEN. Se nada casar, retorna o valor do ELSE — ou NULL, caso você não tenha escrito um.
A palavra-chave aqui é expressão. O CASE produz um valor, então ele cabe em qualquer lugar onde um valor é aceito: uma coluna do SELECT, uma chave do ORDER BY, o lado direito de uma comparação ou até como argumento de uma função.
Esse é o esqueleto: CASE, um ou mais WHEN ... THEN ..., um ELSE opcional e fecha com END. O END é obrigatório — esquecer dele é o erro de digitação mais comum aqui.
Um exemplo prático de CASE WHEN no SQLite
Imagine que você tem uma tabela de pedidos e quer classificar cada linha pelo tamanho. Vamos montar uma rapidinho ali na hora pra você poder rodar a query:
Os ramos são avaliados de cima para baixo. O primeiro que casar vence, então ordene do mais específico para o mais genérico. O ELSE funciona como uma rede de segurança, capturando tudo o que não bateu — sem ele, 1200.00 voltaria como NULL em vez de 'grande'.
Diferença entre CASE simples e pesquisado no SQLite
O exemplo acima usa a forma pesquisada (searched): cada WHEN carrega sua própria condição booleana. Quando você só precisa comparar uma mesma expressão com vários valores fixos, dá para encurtar usando a forma simples:
A expressão depois do CASE é avaliada uma vez e comparada com = contra cada valor de WHEN. Fica mais limpo quando você está fazendo comparações de igualdade em uma única coluna.
Tem um detalhe importante: o CASE simples usa =, e NULL = NULL não é verdadeiro em SQL. Se status puder ser NULL, os ramos 'A'/'B'/'C' não vão casar com ele — vai cair no ELSE. Para tratar NULL de forma explícita, mude para a forma pesquisada e use WHEN status IS NULL THEN ....
CASE dentro de ORDER BY no SQLite
O ORDER BY aceita qualquer expressão, então o CASE funciona tranquilamente ali. É útil quando você quer uma ordenação personalizada que não segue ordem alfabética nem numérica:
'high' < 'low' < 'medium' na ordem alfabética, o que não serve pra nada quando você precisa priorizar tarefas. Mapeando cada prioridade para um número com CASE, você consegue a ordem que realmente faz sentido. O , id no final serve como critério de desempate estável.
CASE dentro do WHERE no SQLite
Dá pra usar CASE dentro do WHERE, mas, na maioria das vezes, não compensa — encadear AND/OR fica bem mais legível. Onde ele realmente brilha é quando a própria condição depende de outro valor:
Itens em promoção entram com preço abaixo de 20; os demais, abaixo de 30. Ou seja, o próprio limite muda conforme a condição. Sem o CASE, você teria que escrever algo como (on_sale = 1 AND price < 20) OR (on_sale = 0 AND price < 30) — dá no mesmo, mas polui a consulta.
CASE dentro de funções de agregação
É aqui que o CASE realmente brilha. Combinando com SUM ou COUNT, dá pra calcular totais de um subconjunto de linhas numa única varredura — é o jeito SQL de dizer "conta quantas atendem a essa condição":
O CASE devolve 1 para as linhas que batem com a condição e 0 para o resto, então o SUM acaba virando uma contagem condicional. Esse mesmo truque funciona para faturamento — basta retornar total nas linhas que se encaixam e 0 nas demais. Uma única varredura na tabela e você já consegue várias agregações condicionais.
IIF: o atalho de duas saídas
Quando você tem uma única condição com apenas dois resultados possíveis, o SQLite oferece o IIF(cond, when_true, when_false). É só um açúcar sintático para CASE WHEN cond THEN when_true ELSE when_false END:
Use IIF quando a lógica for binária e fizer mais sentido em uma única linha. Já o CASE entra em cena quando você tem três ou mais ramificações, precisa tratar NULL separadamente ou quer aproveitar a ordem de avaliação das várias cláusulas WHEN.
Armadilhas que vale conhecer
Algumas coisas costumam pegar a galera de surpresa:
- Esquecer o
END. OCASEabre um bloco e oENDfecha. O SQLite só vai acusar o erro de parsing bem depois do ponto onde você realmente errou. - Sem
ELSE, o resultado éNULL. Se nenhuma das ramificaçõesWHENcasar e você não colocouELSE, sobraNULL. Às vezes é isso que você quer mesmo, mas na maioria das vezes não é. - A ordem das ramificações importa. Na forma pesquisada, o primeiro
WHENque bater vence. ColocarWHEN total < 500antes deWHEN total < 100faz a segunda condição nunca ser alcançada. - Mistura de tipos. Cada ramificação pode devolver um tipo diferente e o SQLite não vai reclamar — mas o código que consome o resultado pode reclamar. Procure manter tipos compatíveis em todos os ramos (tudo texto, tudo numérico).
CASEsimples eNULL. Como já comentamos: a forma simples usa=, que nunca casa comNULL. Quando tiver nulos em jogo, vá de forma pesquisada.
A seguir: funções de string
O CASE permite ramificar a partir de valores; o próximo capítulo começa a parte de transformar valores. As funções de string — UPPER, LOWER, SUBSTR, REPLACE e os padrões com LIKE — cuidam do trabalho do dia a dia de limpar e reformatar colunas de texto. É o que vem na sequência.
Perguntas frequentes
O que é uma expressão CASE no SQLite?
O CASE é a versão SQL do if/else: ele avalia condições e devolve um valor. Repare que é uma expressão, não um comando — ou seja, dá pra usar em qualquer lugar onde um valor é aceito: no SELECT, no WHERE, no ORDER BY, num UPDATE e até dentro de funções de agregação. Cada ramo segue o formato WHEN condição THEN valor, com um ELSE opcional no final.
Qual a diferença entre CASE simples e CASE pesquisado no SQLite?
O CASE simples compara uma única expressão com vários valores: CASE status WHEN 'A' THEN ... WHEN 'B' THEN ... END. Já o CASE pesquisado avalia uma condição booleana independente em cada ramo: CASE WHEN price > 100 THEN ... WHEN qty = 0 THEN ... END. A forma pesquisada é mais flexível — você mistura colunas, operadores e checagens de NULL à vontade.
Quando devo usar IIF em vez de CASE no SQLite?
IIF(cond, a, b) nada mais é que um atalho para CASE WHEN cond THEN a ELSE b END. Use IIF quando a lógica tem só dois caminhos e fica mais legível assim. Parta para o CASE quando tiver três ou mais ramos, quiser aproveitar a ordem de avaliação dos WHEN ou precisar tratar NULL explicitamente com WHEN col IS NULL.