Fala galera!

Nesse artigo, eu gostaria de compartilhar com vocês uma dúvida que enviaram há alguns minutos em um grupo de Whatsapp sobre um problema muito comum no dia a dia de quem trabalha com SQL Server, especialmente nas áreas de BI e/ou desenvolvimento, que são erros de conversão de tipos de dados, ou seja, a tentativa de converter um valor de um tipo para outro tipo, muito comum quando o dado de origem vem de fontes não-estruturadas como CSV, JSON e arquivos textos e eles são todos importados como texto (varchar/nvarchar) e convertidos para os tipos mais adequados posteriormente.

Quem nunca se deparou com uma mensagem de erro dessas ?

Msg 245, Level 16, State 1, Line 40
Conversion failed when converting the varchar value ‘1401D’ to data type int.

Msg 241, Level 16, State 1, Line 44
Conversion failed when converting date and/or time from character string.

Caso você esteja utilizando a versão 2005 ou 2008 do SQL Server, você pode utilizar as funções ISNUMERIC (números inteiros, reais, moedas, decimais, etc) e ISDATE (datas) para fazer a validação para identificar os valores que estão inconsistentes ao se deparar com um erro na tentativa de conversão.

Caso você esteja utilizando a versão 2012 ou superior, você pode utilizar, além das funções vistas anteriormente, as novas funções TRY_PARSE (tipos numéricos e data, apenas), TRY_CAST (qualquer tipo) ou TRY_CONVERT (qualquer tipo, com 3 parâmetro opcional para controlar máscara de entrada) para realizar a conversão de dados, da forma como você costuma utilizar normalmente. O diferencial dessas funções, é que em caso de inconsistência durante a conversão, a função não irá gerar um erro/exceção, pelo contrário, irá silenciosamente ignorar esse erro (retornando NULL para os casos que estão inconsistentes). Isso pode ser utilizado tanto durante a exibição dos resultados tanto no WHERE, para ajudar a identificar quais os registros retornaram NULL, ou seja, quais gerariam erro ao tentar uma conversão tradicional, utilizando CAST/CONVERT.

Desde o SQL Server 2005, também é possível validar essas informações utilizando Expressões Regulares (Regexp), conforme demonstrei com vários exemplos e explicações no artigo SQL Server – Como utilizar expressões regulares (RegExp) no seu banco de dados.

Script usado no vídeo:

IF ( OBJECT_ID ( 'tempdb..#Teste' ) IS NOT NULL ) DROP TABLE #Teste
SELECT
    CAST ( BusinessEntityID AS VARCHAR ( MAX ) ) AS BusinessEntityID ,
    Title ,
    FirstName ,
    LastName ,
    rowguid ,
    CONVERT ( VARCHAR ( MAX ) , ModifiedDate , 112 ) AS ModifiedDate
INTO
    #Teste
FROM
    AdventureWorks2019.Person.Person


-- Simulando alguns erros
UPDATE #Teste
SET
    ModifiedDate = LEFT ( ModifiedDate , 7 ) + '2'
WHERE
    BusinessEntityID BETWEEN 1 AND 20
    OR BusinessEntityID BETWEEN 5000 AND 6000


UPDATE #Teste
SET
    BusinessEntityID += 'D'
WHERE
    BusinessEntityID BETWEEN 1400 AND 1450


SELECT *
FROM #Teste


SELECT *
FROM #Teste
WHERE BusinessEntityID LIKE '%D'
OR BusinessEntityID BETWEEN 1 AND 50
OR BusinessEntityID BETWEEN 5000 AND 6000



SELECT CONVERT ( INT , BusinessEntityID )
FROM #Teste


SELECT CONVERT ( DATE , ModifiedDate , 112 )
FROM #Teste


SELECT BusinessEntityID
FROM #Teste
WHERE TRY_CAST ( BusinessEntityID AS INT ) IS NULL


SELECT ModifiedDate
FROM #Teste
WHERE TRY_CONVERT ( DATE , ModifiedDate , 112 ) IS NULL


SELECT ModifiedDate , TRY_CONVERT ( DATE , ModifiedDate , 112 )
FROM #Teste


SELECT * 
FROM #Teste
WHERE ISNUMERIC ( BusinessEntityID ) = 0


SELECT * FROM #Teste
WHERE ISDATE ( ModifiedDate ) = 0

Bom pessoal, espero que tenham gostado desse artigo simples, pequeno, mas bem objetivo e que ajuda muito quem está iniciando na jornada da área de dados.
Um forte abraço e até a próxima!