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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
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!
ACHANDO O ERRO, COMO QUE FAZ PARA DELETAR^?