[2011-04-02] Código completo:
DECLARE @TEXTO VARCHAR(20) SET @TEXTO = '02.841.834/0001-55' DECLARE @CPF_CNPJ VARCHAR(20) SET @CPF_CNPJ = '' ;WITH SPLIT AS ( SELECT 1 AS ID, SUBSTRING(@TEXTO, 1, 1) AS LETRA UNION ALL SELECT ID + 1, SUBSTRING(@TEXTO, ID + 1, 1) FROM SPLIT WHERE ID < LEN(@TEXTO) ) SELECT @CPF_CNPJ += LETRA FROM SPLIT WHERE LETRA LIKE '[0-9]' OPTION(MAXRECURSION 0) IF LEN(@CPF_CNPJ) NOT IN (11, 14) BEGIN SELECT 'Inválido' RETURN END DECLARE @DIGITO1 INT, @DIGITO2 INT, @VALOR1 INT, @VALOR2 INT DECLARE @I INT, @J INT, @TOTAL_TMP INT, @COEFICIENTE_TMP INT, @DIGITO_TMP INT, @VALOR_TMP INT SET @DIGITO1 = SUBSTRING(@CPF_CNPJ, LEN(@CPF_CNPJ) - 1, 1) SET @DIGITO2 = SUBSTRING(@CPF_CNPJ, LEN(@CPF_CNPJ), 1) SET @J = 1 WHILE @J <= 2 BEGIN SELECT @TOTAL_TMP = 0, @COEFICIENTE_TMP = 2 SET @I = ((LEN(@CPF_CNPJ) - 3) + @J) WHILE @I >= 0 BEGIN SELECT @DIGITO_TMP = SUBSTRING(@CPF_CNPJ, @I, 1), @TOTAL_TMP = @TOTAL_TMP + (@DIGITO_TMP * @COEFICIENTE_TMP), @COEFICIENTE_TMP = @COEFICIENTE_TMP + 1 IF (@COEFICIENTE_TMP > 9) AND LEN(@CPF_CNPJ) = 14 SET @COEFICIENTE_TMP = 2 SET @I = @I - 1 END SET @VALOR_TMP = 11 - (@TOTAL_TMP % 11) IF (@VALOR_TMP >= 10) SET @VALOR_TMP = 0 IF @J = 1 SET @VALOR1 = @VALOR_TMP ELSE SET @VALOR2 = @VALOR_TMP SET @J = @J + 1 END SELECT CASE WHEN @VALOR1 = @DIGITO1 AND @VALOR2 = @DIGITO2 THEN 'Válido' ELSE 'Inválido' END
[Post-Original] Explicação:
Boa noite pessoas!
No blog do Rogério, encontrei um ótimo algoritmo de validação de CNPJ e CPF para ORACLE, para que ninguém tenha que ficar transitando de ‘PL\SQL’ para ‘T-SQL’, já realizei este trabalho e vou detalhar um pouco o funcionamento deste algoritmo.
Primeiro precisamos de um CNPJ ou CPF para validar, assim identifiquei um que estava “vagando” na internet.
DECLARE @CPF_CNPJ VARCHAR(20) SET @CPF_CNPJ = '02.841.834/0001-55'
Ok, tenho o CNPJ/CPF para validar, mas tenho que remover os caracteres não numéricos, desta forma utilizarei a função SOMENTE_NUMEROS que desenvolvi para o artigo anterior:
SET @CPF_CNPJ = dbo.SOMENTE_NUMEROS(@CPF_CNPJ)
A primeira valiação verifica se a quantidade de caracteres é de um CPF ou de um CNPJ
IF LEN(@CPF_CNPJ) NOT IN (11, 14) BEGIN SELECT 'Inválido' RETURN END
Em sequida, defino quatro variáveis que serão utilizadas para a validação dos digitos verificadores do CNPJ e CPF.
DECLARE @DIGITO1 INT, @DIGITO2 INT, @VALOR1 INT, @VALOR2 INT
Também há outras variáveis a serem utilizadas durante a operação.
DECLARE @I INT, @J INT, @TOTAL_TMP INT, @COEFICIENTE_TMP INT, @DIGITO_TMP INT, @VALOR_TMP INT
As variáveis DIGITO1 e DIGITO2 armazenarão os digitos verificadores do CNPJ/CPF.
SET @DIGITO1 = SUBSTRING(@CPF_CNPJ, LEN(@CPF_CNPJ) - 1, 1) SET @DIGITO2 = SUBSTRING(@CPF_CNPJ, LEN(@CPF_CNPJ), 1)
Feito isso, determino um laço de repetição para dois loops, um para cada digito.
SET @J = 1 WHILE @J <= 2 BEGIN
Determino os valores inicias das variáveis de validação.
SELECT @TOTAL_TMP = 0, @COEFICIENTE_TMP = 2
Agora, aplico o algoritmo para gerar cada um dos digitos verificadores.
SET @I = ((LEN(@CPF_CNPJ) - 3) + @J) WHILE @I >= 0 BEGIN SELECT @DIGITO_TMP = SUBSTRING(@CPF_CNPJ, @I, 1), @TOTAL_TMP = @TOTAL_TMP + (@DIGITO_TMP * @COEFICIENTE_TMP), @COEFICIENTE_TMP = @COEFICIENTE_TMP + 1 IF (@COEFICIENTE_TMP > 9) AND LEN(@CPF_CNPJ) = 14 SET @COEFICIENTE_TMP = 2 SET @I = @I - 1 END SET @VALOR_TMP = 11 - (@TOTAL_TMP % 11) IF (@VALOR_TMP >= 10) SET @VALOR_TMP = 0
Identifico qual dos digitos verificadores foi gerado e prossigo para o próximo digito no laço de repetição.
IF @J = 1 SET @VALOR1 = @VALOR_TMP ELSE SET @VALOR2 = @VALOR_TMP SET @J = @J + 1 END
Por fim, verifico se os digitos gerados têm o mesmo valor dos presente no CNPJ/CPF.
IF @VALOR1 = @DIGITO1 AND @VALOR2 = @DIGITO2 SELECT 'Válido' ELSE SELECT 'Inválido'
Para o próximo artigo, ainda estou estudando uma forma interessante de trabalhar com máscaras e CTE.
Artigos relacionados:
Blog do Rogério – Validação CNPJ/CPF com PL/SQL
http://blogdozunga.blogspot.com/2009/02/precisava-de-uma-rotina-para-validar.html
FUNÇÕES: Somente Números (com CTE)
https://sqlfromhell.wordpress.com/2009/11/18/somente-numeros-com-cte/
FUNÇÕES: Somente Números (com WHILE)
https://sqlfromhell.wordpress.com/2009/11/17/somente-numeros-com-while/
Pingback: Formatando valores numéricos, CPF e CNPJ « Sql From Hell.com
Pingback: FUNÇÕES: Somente Números (com CTE) v2 « Sql From Hell.com
Pingback: (DRAFT) Trabalhando com CLR: Validação de CNPJ e CPF « SQL From Hell.com
Pingback: Aniversário de 3 anos do SQL From Hell!! « SQL From Hell.com
Só seria necessário colocar mais uma validação para CPF/CNPJ com todos os dígitos iguais, pois não são válidos, todavia passam pelo validador.
Além disso, um CPF (11 dígitos), com 14 dígitos (com zeros à esquerda) não é validado corretamente.
Pingback: Como validar CPF e CNPJ no SQL Server | SQL From Hell.com