Instrução SQL CASE WHEN: Sintaxe, exemplos reais e erros comuns
CASE WHEN é como você escreve a lógica if-then em SQL. Aprenda os dois formulários e use-os para rótulos, relatórios de estilo dinâmico, classificação personalizada e atualizações seguras, evitando as armadilhas NULL e de ordem.
CASEretorna um valor baseado na primeira condição que é verdadeira.- Coloque as condições mais específicas em primeiro lugar, ou as posteriores poderão nunca ser alcançadas.
- Sem
ELSE, as linhas sem correspondência retornamNULL. - Dentro de
SUMouCOUNT, CASE transforma uma consulta em um relatório compacto em estilo pivô.
A maioria dos relatórios precisa de alguma lógica: rotular os pedidos como grandes ou pequenos, contar os pedidos pagos e pendentes lado a lado ou mostrar os itens urgentes primeiro. SQL CASE WHEN lida com tudo isso diretamente dentro de uma consulta e funciona em todos os principais bancos de dados.
Executamos todas as consultas aqui no SQLite 3.50 e os resultados mostrados vêm dessa execução. CASE faz parte do SQL padrão, portanto se comporta da mesma maneira no PostgreSQL, MySQL, SQL Server e Oracle para estes exemplos.
O que é CASO QUANDO?
CASE é uma expressão, não um comando separado. Ele avalia as condições em ordem e retorna um valor, para que possa ir a qualquer lugar onde um valor seja permitido: em SELECT, WHERE, GROUP BY, ORDER BY ou dentro de funções. Sempre termina com END.
CASE
WHEN condition1 THEN result1
WHEN condition2 THEN result2
ELSE fallback
END
A tabela de amostra
CREATE TABLE orders (id INT, customer TEXT, total INT, status TEXT);
INSERT INTO orders VALUES
(1,'Asha',1200,'paid'), (2,'Ben',300,'pending'),
(3,'Asha',800,'paid'), (4,'Chitra',2500,'shipped'),
(5,'Dev',150,'cancelled'), (6,'Ben',NULL,'pending');
Observe que o pedido 6 não tem total. Essa linha importa mais tarde.
CASO pesquisado
Esta é a forma mais flexível, já que cada WHEN tem uma condição completa própria:
SELECT id, total,
CASE
WHEN total >= 1000 THEN 'large'
WHEN total >= 500 THEN 'medium'
ELSE 'small'
END AS size
FROM orders;
-- 1 | 1200 | large
-- 2 | 300 | small
-- 3 | 800 | medium
-- 4 | 2500 | large
-- 5 | 150 | small
-- 6 | NULL | small
Olhe para a última linha. O pedido 6 não tem total, mas é rotulado como “pequeno”. Ambas as comparações com NULL não eram verdadeiras, então caiu para ELSE. Mostramos como corrigir isso na seção NULL. Sempre dê um nome ao resultado usando AS, ou você pode obter um nome de coluna estranho.
CASO Simples
Ao comparar uma coluna com valores fixos, a forma mais curta é melhor:
SELECT id,
CASE status
WHEN 'paid' THEN 'Complete'
WHEN 'shipped' THEN 'Complete'
WHEN 'pending' THEN 'Waiting'
END AS label
FROM orders;
-- 1 | Complete
-- 2 | Waiting
-- 3 | Complete
-- 4 | Complete
-- 5 | NULL
-- 6 | Waiting
| Formulário | Compara | Pode usar intervalos? | Melhor para |
|---|---|---|---|
| Simples | Uma expressão para igualdade | Não | Mapeando códigos para rótulos |
| Pesquisado | Qualquer condição por filial | Sim | Intervalos, múltiplas colunas, verificações NULL |
O pedido é importante
CASE para na primeira condição verdadeira e este é o bug lógico mais comum. Troque as duas condições da nossa consulta anterior:
SELECT id, total,
CASE
WHEN total >= 500 THEN 'medium'
WHEN total >= 1000 THEN 'large'
ELSE 'small'
END AS size
FROM orders WHERE id IN (1, 4);
-- 1 | 1200 | medium
-- 4 | 2500 | medium
Agora nada pode ser “grande”. Um total de 2.500 também é pelo menos 500, então o primeiro ramo vence e o segundo nunca é alcançado. Nenhum erro aparece, apenas rótulos errados. Para intervalos, coloque primeiro a condição mais restritiva ou escreva intervalos completos, como total >= 500 AND total < 1000.
O que acontece sem MAIS?
Em nosso exemplo CASE simples acima, o pedido 5 foi cancelado e nenhuma filial tratou disso, então o resultado foi NULL. Às vezes é exatamente isso que você deseja, como mostra a próxima seção. Mas ao criar rótulos, um ELSE 'other' claro geralmente é melhor, pois torna visíveis valores inesperados em vez de deixar espaços em branco em um relatório.
Dica: Todas as ramificações devem retornar o mesmo tipo. Misturar texto e números funciona vagamente no SQLite, mas bancos de dados mais rígidos, como o PostgreSQL, gerarão um erro ou tentarão converter valores de maneiras que você não pretendia.
Relatórios de estilo dinâmico com SUM
Este é um dos padrões mais úteis no SQL diário. Agrupar CASE em um agregado transforma linhas em colunas, com uma linha por cliente:
SELECT customer,
SUM(CASE WHEN status = 'paid' THEN total ELSE 0 END) AS paid,
SUM(CASE WHEN status = 'pending' THEN 1 ELSE 0 END) AS pending_orders
FROM orders
GROUP BY customer
ORDER BY customer;
-- Asha | 2000 | 0
-- Ben | 0 | 2
-- Chitra | 0 | 0
-- Dev | 0 | 0
Uma consulta agora fornece a receita paga e o número de pedidos pendentes, sem necessidade de consultas ou junções separadas. O padrão funciona em quase todos os bancos de dados, ao contrário da sintaxe dedicada PIVOT que apenas alguns oferecem. Se GROUP BY for novo para você, leia SQL GROUP BY e HAVING.
Contagens condicionais
COUNT ignora NULLs, então um CASE sem ELSE conta apenas as linhas que correspondem:
SELECT COUNT(*) AS all_orders,
COUNT(CASE WHEN status = 'paid' THEN 1 END) AS paid_orders,
COUNT(CASE WHEN total >= 1000 THEN 1 END) AS large_orders
FROM orders;
-- 6 | 2 | 2
Tenha cuidado: se você adicionar ELSE 0 dentro de COUNT, todas as linhas serão contadas, porque 0 não é NULL. Use ELSE 0 com SUM e deixe de fora com COUNT. PostgreSQL e SQLite também suportam COUNT(*) FILTER (WHERE ...), que é bem lido, mas não está disponível em todos os lugares.
Agrupando por um CASE
Você pode criar seus próprios intervalos e resumi-los:
SELECT CASE WHEN total >= 1000 THEN 'large' ELSE 'other' END AS bucket,
COUNT(*)
FROM orders
GROUP BY bucket
ORDER BY bucket;
-- large | 2
-- other | 4
O agrupamento pelo alias funciona em SQLite, PostgreSQL e MySQL. O SQL Server não permite isso, então você teria que repetir a expressão inteira ou colocar a consulta em uma CTE ou subconsulta primeiro.
Classificação personalizada com ORDER BY
A ordem alfabética raramente é o que uma empresa deseja. CASE permite definir seu próprio pedido:
SELECT id, status FROM orders
ORDER BY CASE status
WHEN 'pending' THEN 1
WHEN 'paid' THEN 2
ELSE 3
END, id;
-- 2 | pending
-- 6 | pending
-- 1 | paid
-- 3 | paid
-- 4 | shipped
-- 5 | cancelled
Os pedidos pendentes vêm primeiro, o que é útil para uma fila de trabalho. A segunda coluna de classificação, id, mantém as linhas em uma ordem previsível dentro de cada grupo.
CASO em ATUALIZAÇÃO
CASE permite que uma instrução aplique alterações diferentes em linhas diferentes. Aqui, pequenos pedidos pendentes são sinalizados para revisão:
UPDATE orders
SET status = CASE
WHEN status = 'pending' AND total < 500 THEN 'review'
ELSE status
END;
SELECT id, status FROM orders WHERE customer = 'Ben';
-- 2 | review
-- 6 | pending
O ELSE status mantém as outras linhas inalteradas. Deixá-lo de fora é perigoso, porque linhas sem correspondência seriam definidas como NULL. Sem uma cláusula WHERE, esta instrução também afeta todas as linhas, portanto, em tabelas grandes, adicione um filtro e considere agrupar a alteração em uma transação para que você possa verificar o resultado antes de confirmar. Observe também que a ordem 6 não mudou, porque seu total NULL não satisfez total < 500.
Armadilhas NULAS
NULL causa dois problemas distintos com CASE. Primeiro, a forma simples compara usando igualdade, e nada é igual a NULL, nem mesmo o próprio NULL:
SELECT CASE NULL WHEN NULL THEN 'matched' ELSE 'not matched' END;
-- not matched
Então CASE col WHEN NULL nunca corresponde. Use o formulário pesquisado com IS NULL. Em segundo lugar, como vimos na ordem 6, um valor NULL escapa das comparações e chega a ELSE. A solução é verificar primeiro:
SELECT id,
CASE
WHEN total IS NULL THEN 'unknown'
WHEN total >= 1000 THEN 'large'
ELSE 'other'
END AS size
FROM orders WHERE id IN (1, 2, 6);
-- 1 | large
-- 2 | other
-- 6 | unknown
O pedido 6 agora recebe um rótulo honesto. Nosso guia sobre valores SQL NULL aborda esse comportamento na íntegra.
CASE versus outras opções
| Opção | Funciona em | Use-o quando |
|---|---|---|
CASO |
Todos os principais bancos de dados | Você quer lógica portátil |
COALESCER |
Todos os principais bancos de dados | Você só precisa de um substituto para NULL |
IF() |
MySQL | Uma escolha simples e bidirecional |
IIF() |
SQL Server, SQLite | Uma escolha simples e bidirecional |
DECODE() |
Oráculo | Código Oracle mais antigo |
| Tabela de pesquisa | Todos | O mapeamento é longo ou muda frequentemente |
Essa última opção merece uma reflexão. Se um CASE crescer para trinta ramificações e aparecer em cinco consultas, mova o mapeamento para uma tabela e junte-se a ela. Então, uma alteração é uma atualização de linha única, em vez de uma alteração de código em cinco locais.
Erros comuns
- Ordem de condição errada. Uma condição ampla primeiro oculta as mais restritas.
- Esquecimento
END. Este é o erro de sintaxe mais frequente. - Usando
WHEN NULL. Nunca corresponde, então useWHEN col IS NULL. - Adicionando
ELSE 0dentro deCOUNT. Conta todas as linhas. - Omitindo
ELSEem um UPDATE. Ele pode limpar valores com NULL. - Filtragem por CASE em
WHERE. Pode impedir que um índice seja usado. Consulte nosso guia sobre otimização de consultas SQL.
Considerações finais
CASE WHEN é um pequeno recurso que faz muito trabalho. Lembre-se de três regras: a primeira ramificação verdadeira vence, as linhas sem correspondência tornam-se NULL sem ELSE e NULL precisa de sua própria verificação. Para praticar, pegue um relatório que você está construindo atualmente com diversas consultas e tente produzi-lo como uma consulta usando SUM(CASE ...).
Perguntas frequentes
O que CASE WHEN faz no SQL?
Ele adiciona lógica if-then a uma consulta. O SQL verifica cada condição em ordem e retorna o valor da primeira que for verdadeira ou o valor ELSE se nenhum for.
O que acontece se não houver ELSE em uma instrução CASE?
As linhas que não correspondem a nenhuma condição retornam NULL. Isso é útil dentro de COUNT, mas em rótulos e atualizações pode causar espaços em branco ou perda de dados.
Posso usar CASE em uma cláusula WHERE?
Sim, porque é uma expressão. No entanto, as condições simples AND e OR são geralmente mais claras e são mais propensas a fazer uso de um índice.
Qual é a diferença entre CASE simples e pesquisado?
CASE simples compara uma expressão com valores fixos para igualdade. O CASE pesquisado possui uma condição completa em cada WHEN, portanto pode lidar com intervalos e verificações de NULL.
As instruções CASE podem ser aninhadas?
Sim, um CASE pode aparecer dentro de outro. Porém, o aninhamento profundo fica difícil de ler, então considere combinar condições com AND ou usar uma tabela de pesquisa.
Continue aprendendo
Precisa de ajuda com testes, WordPress ou SEO?
Ajudamos as equipes a fornecer software melhor e a expandir seus sites. Conte-nos no que você está trabalhando e sugeriremos um próximo passo claro.
Mais guias sobre testes, IA e desenvolvimento moderno
Gostou deste artigo? Escolha um tópico e vá direto para nossos tutoriais mais recentes.
Explicação das alucinações de IA: por que os modelos de linguagem inventam as coisas e como reduzi-las
Explicação das alucinações de IA: o que são, por que os modelos de linguagem as produzem, tipos comuns, como reduzi-las com aterramento e instruções…
Leia o artigo →DevOpsVariáveis de ambiente explicadas: arquivos .env, segredos e configuração bem feitos
Variáveis de ambiente explicadas com exemplos de Python que executamos: leitura e configuração, por que cada valor é uma string, arquivos .env, hera…
Leia o artigo →Desenvolvimento de softwareExplicação da limitação de taxa de API: algoritmos, cabeçalhos e tratamento de erros 429
Limitação de taxa de API explicada com uma simulação que executamos: token bucket, janela fixa, janela deslizante, 429 respostas, cabeçalhos de limi…
Leia o artigo →Automação de testesZombando em Python: unittest.mock, patch e os erros que fazem os testes mentirem
Zombaria em Python com unittest.mock, testado: Mock e return_value, side_effect, patch onde um nome é usado, especificação e autospec, zombaria de d…
Leia o artigo →Teste de softwareCobertura de código explicada: cobertura de linha versus filial e o que 100% realmente significa
Cobertura de código explicada com uma execução cobertura.py real: cobertura de linha, ramal e condição, leitura de um relatório, por que 100% de cob…
Leia o artigo →Bancos de dados e SQLDELETE vs TRUNCATE vs DROP em SQL: diferenças, reversão e quando usar cada um
DELETE vs TRUNCATE vs DROP explicado com SQL testado: o que cada um remove, rollback, aciona, redefinição de identidade, velocidade e como PostgreSQ…
Leia o artigo →Bancos de dados e SQLExibições SQL explicadas: crie, use e evite as armadilhas, com exemplos
Visualizações SQL explicadas com consultas que executamos: criação de uma visualização, resultados ao vivo, ocultação de colunas, desempenho, visual…
Leia o artigo →Desenvolvimento de softwareInterface TypeScript vs tipo: diferenças reais, testadas com o compilador
Interface TypeScript versus tipo, verificada com o compilador real: o que ambos podem fazer, o que apenas um pode fazer, mesclagem de declarações, e…
Leia o artigo →Desenvolvimento de softwarePython *args e **kwargs explicados: funções flexíveis com exemplos claros
Python *args e **kwargs explicados com o código que executamos: empacotamento e descompactação, ordem dos parâmetros, argumentos somente de palavras…
Leia o artigo →Desenvolvimento de softwareFunções Python Lambda: sintaxe, usos reais e quando não usá-los
Funções lambda do Python explicadas com o código que executamos: sintaxe, classificação com chave, mapa e filtro, fechamentos, armadilha de ligação …
Leia o artigo →Inteligência artificialO que são agentes de IA? Como eles funcionam, com um loop de agente simples que você pode executar
O que são agentes de IA? Um guia simples para o loop do agente, ferramentas, memória e proteções, com um pequeno loop Python que executamos, riscos …
Leia o artigo →DevOpsMonitoramento versus observabilidade: a verdadeira diferença, com logs, métricas e rastreamentos
Explicação do monitoramento versus observabilidade: falhas conhecidas e desconhecidas, logs, métricas e rastreamentos, um passo a passo do incidente…
Leia o artigo →DevOpsDocker Volumes vs Bind Mounts: persista os dados do contêiner da maneira certa
Volumes Docker versus montagens de ligação explicadas: por que os dados do contêiner desaparecem, volumes nomeados, montagens de ligação, tmpfs, exe…
Leia o artigo →Automação de testesTDD vs BDD: principais diferenças, um recurso criado de ambas as maneiras e quando usar cada um
TDD vs BDD explicado com um recurso de desconto construído em ambos os sentidos: refatoração vermelho-verde com o código que executamos, cenários da…
Leia o artigo →Teste de softwareTeste de aceitação do usuário (UAT): processo, lista de verificação e exemplos reais
Explicação do teste de aceitação do usuário: quem o executa, como ele difere do controle de qualidade, um processo de sete etapas, um modelo de caso…
Leia o artigo →Bancos de dados e SQLValores SQL NULL explicados: IS NULL, COALESCE, NULLIF e as armadilhas a serem evitadas
Valores SQL NULL explicados com consultas que executamos: lógica de três valores, IS NULL, COALESCE, NULLIF, como agregações, junções e classificaçã…
Leia o artigo →Bancos de dados e SQLInstrução SQL CASE WHEN: sintaxe, exemplos reais e erros comuns
SQL CASE WHEN explicado com consultas que executamos: formulários simples e pesquisados, ordem de condição, pivôs com SUM, truques COUNT, classifica…
Leia o artigo →Desenvolvimento de softwareO que é JWT? JSON Web Tokens explicados com um exemplo prático
O que é JWT? JSON Web Tokens explicados: as três partes, um token construído e adulterado no código que executamos, JWT vs sessões, armazenamento, t…
Leia o artigo →Desenvolvimento de softwareLoop de eventos JavaScript explicado: pilha de chamadas, microtarefas e temporizadores com exemplos
O loop de eventos JavaScript explicado com o código que executamos: pilha de chamadas, filas de tarefas e microtarefas, por que setTimeout 0 não é i…
Leia o artigo →Desenvolvimento de softwareGeradores Python e rendimento explicado: economize memória com exemplos reais
Geradores Python e rendimento explicados com o código que executamos: como eles pausam e reiniciam, medem economia de memória, pipelines, sequências…
Leia o artigo →Inteligência artificialO que são incorporações? Similaridade de vetores e cossenos explicada de forma simples
O que são incorporações? Um guia em linguagem simples para vetores, similaridade de cossenos e pesquisa semântica, com um pequeno exemplo que execut…
Leia o artigo →DevOpsImplantação azul-verde vs canário: diferenças, compensações e como escolher
Explicação da implantação azul-verde versus canário: como cada um funciona, custo, risco e reversão, agrupamento estável de usuários que testamos, m…
Leia o artigo →Automação de testesTestes instáveis: o que os causa e como corrigi-los para sempre
Testes instáveis explicados com demonstrações que executamos: as principais causas, como confirmar e diagnosticar uma, soluções adequadas para tempo…
Leia o artigo →Teste de softwareTeste de carga versus teste de estresse: diferenças, métricas e exemplos k6
Teste de carga versus teste de estresse explicado: o que cada um prova, testes de pico e absorção, as métricas que importam, por que as médias engan…
Leia o artigo →Teste de softwareCaso de teste versus cenário de teste: principais diferenças, exemplos e quando usar cada um
Caso de teste vs cenário de teste explicado: definições claras, uma tabela lado a lado, um recurso de redefinição de senha retirado de cenários para…
Leia o artigo →Bancos de dados e SQLOtimização de consultas SQL: leia planos de execução e corrija consultas lentas, com intervalos
Otimização de consulta SQL testada em um milhão de linhas: leia planos de execução, adicione os índices corretos, corrija filtros não sargáveis, use…
Leia o artigo →Bancos de dados e SQLSQL UNION vs UNION ALL: diferenças, exemplos e desempenho testado
SQL UNION vs UNION ALL explicado com consultas que executamos: duplicatas, as regras que ambos seguem, um bug de dados real, desempenho medido, INTE…
Leia o artigo →Desenvolvimento de softwareTutorial da API JavaScript Fetch: GET, POST, tratamento de erros e tempos limite
Um tutorial da API JavaScript Fetch testado em um servidor local: GET e POST, por que 404 não lança, um auxiliar reutilizável, strings de consulta, …
Leia o artigo →Desenvolvimento de softwareManipulação de arquivos Python: leitura, gravação, CSV, JSON e pathlib com exemplos
Manipulação de arquivos Python explicada com código que executamos: modos abertos, com, leitura de arquivos grandes, CSV, JSON, pathlib, arquivos bi…
Leia o artigo →Desenvolvimento de softwareClasses e objetos Python: tutorial OOP com exemplos reais
Classes e objetos Python explicados com código que executamos: __init__, métodos, atributos de classe vs instância, herança, propriedades, métodos d…
Leia o artigo →Inteligência artificialO que é um modelo de linguagem grande? Como funcionam os LLMs, explicado sem exageros
O que é um modelo de linguagem grande? LLMs explicados em linguagem simples: tokens, incorporações, atenção, treinamento, temperatura e janelas de c…
Leia o artigo →DevOpsComandos Linux para iniciantes: o guia essencial do terminal com exemplos
Comandos Linux para iniciantes, agrupados por tarefa: navegação, arquivos, visualização de logs, grep, pipes, permissões, processos e arquivos, com …
Leia o artigo →Automação de testesSelenium vs Playwright: principais diferenças, código comparado e qual escolher
Selenium vs Playwright comparado: arquitetura, espera, suporte a navegador e linguagem, depuração, o mesmo teste em ambas as ferramentas, conselhos …
Leia o artigo →Teste de softwareParticionamento de equivalência: técnica de design de teste explicada com exemplos resolvidos
Explicação do particionamento de equivalência: como encontrar partições válidas e inválidas, exemplos resolvidos para idades, senhas e cupons, teste…
Leia o artigo →Teste de softwareGravidade vs Prioridade em Testes de Software: Diferenças, Matriz e Exemplos Reais
Explicação da gravidade versus prioridade em testes de software: definições claras, uma matriz de quatro vias com exemplos, escalas de nível, quem d…
Leia o artigo →Bancos de dados e SQLTutorial de subconsultas SQL: tipos, subconsultas correlacionadas e EXISTS com exemplos
Um tutorial de subconsultas SQL com consultas que executamos: subconsultas escalares, IN, FROM e SELECT, subconsultas correlacionadas, EXISTS, a arm…
Leia o artigo →Bancos de dados e SQLTransações SQL e ACID explicados: COMMIT, ROLLBACK e níveis de isolamento
Transações SQL e ACID explicadas com uma transferência bancária que executamos: COMMIT, ROLLBACK, savepoints, locks, níveis de isolamento, leituras …
Leia o artigo →Desenvolvimento de softwareGit merge vs rebase: diferenças, exemplos e quando usar cada um
Git merge vs rebase explicado com saída real do log, uma tabela comparativa, a regra de ouro do rebase e um fluxo de trabalho seguro para equipes.
Leia o artigo →Desenvolvimento de softwareList comprehension em Python: sintaxe, exemplos e quando evitar
List comprehension em Python explicada: sintaxe, filtros, if-else, laços aninhados, tempos medidos e quando um laço for comum é a melhor escolha.
Leia o artigo →Bancos de dados e SQLSQL JOIN explicado com exemplos (Inner, Left, Right, Full)
Entenda os joins SQL passo a passo com tabelas e consultas de exemplo: INNER, LEFT, RIGHT, FULL, CROSS e SELF, além de erros comuns e dicas de desem…
Leia o artigo →