SQL Server
Localizando erros de conversão no SQL Server com TRY_CAST
Por que CAST no WHERE falha em tabela inteira antes do filtro — e como usar TRY_CAST para achar só as linhas que não convertem, entendendo a ordem lógica de processamento da query.
Quando lidamos com banco de dados é comum esbarrar na mensagem “Conversion failed when converting…”. Isso aparece em situações em que o valor de origem não pode ser convertido para o tipo de destino.
Conversões válidas (quando o literal bate com o tipo):
SELECT HorarioFormatado = CAST('13:30' AS time);
SELECT DataFormatada = CAST('2024-02-28' AS date);
Essas sentenças são válidas porque os valores respeitam o formato esperado. Já exemplos que quebram:
SELECT HorarioFormatado = CAST('32:00' AS time);
SELECT DataFormatada = CAST('33' AS date);
Elas retornam erro do tipo: “Conversion failed when converting date and/or time from character string.”
Fácil de identificar e de resolver na mão, certo? Nem sempre.
Imagine uma consulta em uma tabela com dez mil registros: você precisa tratar a coluna como time para comparar com um intervalo, por exemplo:
SELECT *
FROM Horarios
WHERE CAST(Horario AS time) BETWEEN CAST('13:40' AS time) AND CAST('15:30' AS time);
Aqui o CAST é necessário porque comparar varchar com BETWEEN em horário não é o mesmo que comparar tipos time de forma confiável — você quer o domínio time.
Só que, se em alguma linha o valor for inválido (ex.: '32:00'), a query inteira pode falhar com o mesmo erro de conversão — mesmo que o seu intervalo de busca seja só entre 13:40 e 15:30. Por quê?
SQL Server: ordem lógica de processamento
Entra em cena a ordem lógica de processamento da query: em linhas gerais, é a ordem em que o motor conceitualmente avalia as cláusulas (FROM, WHERE, GROUP BY, etc.).
No caso acima, o CAST está no WHERE. O ponto importante: a conversão é aplicada no contexto do predicado antes de você “enxergar” só as linhas que passariam no filtro final — ou seja, o motor precisa avaliar a expressão de conversão para as linhas candidatas, e ao encontrar um valor que não converte, a query aborta com erro antes de te entregar um resultado parcial.
Por isso o erro aparece mesmo quando “matematicamente” você só queria o intervalo das 13:40 às 15:30: ainda existe uma linha com lixo na coluna que explode na etapa de avaliação da expressão.
Vale a leitura da documentação oficial do SELECT (Transact-SQL) para aprofundar em logical processing order e no comportamento das cláusulas.
Como achar as linhas problemáticas com TRY_CAST
TRY_CAST tenta converter o valor; se não der, retorna NULL em vez de erro.
Para localizar o que não converte, use isso de propósito no WHERE:
SELECT *
FROM Horarios
WHERE TRY_CAST(Horario AS time) IS NULL
AND Horario IS NOT NULL; -- opcional: ignorar NULL “legítimo” da coluna
Assim você lista só os registros em que a conversão para time falharia se fosse um CAST “duro”.
Pense numa tabela Horarios com mistura de valores válidos e inválidos em Horario (varchar):
| Id | Horario |
|---|---|
| 1 | 13:30 |
| 2 | 32:00 |
| 3 | 08:15 |
A consulta com TRY_CAST(...) IS NULL deve trazer a linha do 32:00 (e qualquer outro valor estranho), para você corrigir dado na origem, ajustar ETL ou tratar com regra de negócio — sem derrubar a query que usa CAST no intervalo.
Depois de limpar (ou isolar) os problemáticos, a busca com CAST(Horario AS time) BETWEEN ... volta a ser segura do ponto de vista de conversão.
Considerações
TRY_CAST não serve só para esse diagnóstico: vale estudar os demais cenários na documentação do TRY_CAST.
O objetivo aqui foi ser didático: além de um filtro para achar “lixo”, entender por que o erro aparece mesmo com um WHERE que parece restritivo — e por que a ordem lógica de avaliação importa tanto no dia a dia com SQL Server.