[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/