Esta store function, foi desenvolvida pensando no armazenamento do CNPJ em BIGINT, mas pode ser usada facilmente sem adaptações com CNPJ tipo VARCHAR(14) sem mascaras ou formatações.
Recomendável persistência do CNPJ em BIGINT por motivo principal de desempenho.
Segue function....
IF EXISTS (
SELECT *
FROM sys.objects
WHERE object_id = OBJECT_ID(N'[dbo].[usf_valida_cnpj]')
AND type IN (N'FN')
)
DROP FUNCTION dbo.usf_valida_cnpj;
GO
CREATE FUNCTION dbo.usf_valida_cnpj(@cnpjx varchar(14)) RETURNS bit
AS
-- Nome Artefato/Programa..: usf_valida_cnpj.sql
-- Autor(es)...............: Emerson Hermann (emersonhermann [at] gmail.com) O Peregrino (http://www.emersonhermann.blogspot.com) baseado em Script feito por:
-- ........................: Baseado em código de Fernando Jacinto da Silva em http://www.devmedia.com.br
-- Data Inicio ............: 18/09/2011
-- Data Atualizacao........: 19/09/2012
-- Versao..................: 0.02
-- Compilador/Interpretador: T-SQL (Transact SQL)
-- Sistemas Operacionais...: Windows
-- SGBD....................: MS SQL Server 2005/2008
-- Kernel..................: Nao informado!
-- Finalidade..............: Store Procedure (Function) para validar o numero do CNPJ
-- OBS.....................: A entrada é um varchar e o retorno é um bit, 1 para válido, 0 para inválido e null para nulos
-- ........................:
--
BEGIN
DECLARE
@cnpj varchar(14)
, @indice int
, @soma int
, @dig1 int
, @dig2 int
, @var1 int
, @var2 int
, @resultado bit
SET @cnpj = @cnpjx
SET @soma = 0
SET @indice = 1
SET @resultado = 0
-- pre-validacao 1, se e nulo, entao retorna nulo
IF @cnpj IS NULL BEGIN
SET @resultado = NULL
RETURN (@resultado)
END --fim_se
-- pre-validacao 2, se e maior que 11 digitos , entao retorna 0
IF LEN(@cnpj) > 14 BEGIN
SET @resultado = 0
RETURN (@resultado)
END --fim_se
-- pre-validacao 3, se e tem alguma letra no cpf, entao retorna 0
IF (SELECT CASE WHEN patindex('%[^0-9]%', @cnpj) > 0 THEN 1 ELSE 0 END) = 1 BEGIN
SET @resultado = 0
RETURN (@resultado)
END --fim_se
-- pre-validacao 4, se e menor que 11 digitos , pode ser oriundo de bigint, então fazer tratamento de zeros
IF LEN(@cnpj) < 14 BEGIN
SET @cnpj = REPLICATE('0',14-LEN(@cnpj))+@cnpj
END --fim se
/* algorítimo para o primeiro dígito 543298765432 */
/* cálculo do 1º dígito */
/* cálculo da 1ª parte do algorítiom 5432 */
SET @var1 = 5 /* 1a parte do algorítimo começando de "5" */
WHILE (@indice <= 4) BEGIN
SET @soma = @soma + CONVERT(int,SUBSTRING(@cnpj,@indice,1)) * @var1
SET @indice = @indice + 1 /* navegando um-a-um até < = 4, as quatro primeira posições */
SET @var1 = @var1 - 1 /* subtraindo o algorítimo de 5 até 2 */
END
/* cálculo da 2ª parte do algorítiom 98765432 */
SET @var2 = 9
WHILE (@indice <= 12) BEGIN
SET @soma = @soma + CONVERT(int,SUBSTRING(@cnpj,@indice,1)) * @var2
SET @indice = @indice + 1
SET @var2 = @var2 - 1
END
SET @dig1 = (@soma % 11)
/* se o resto da divisão for < 2, o digito = 0 */
IF @dig1 < 2 BEGIN
SET @dig1 = 0
END ELSE BEGIN /* se o resto da divisão não for < 2*/
SET @dig1 = 11 - (@soma % 11)
END
/* cálculo do 2º dígito */
/* zerando o indice e a soma para começar a calcular o 2º dígito*/
SET @indice = 1
SET @soma = 0
/* cálculo da 1ª parte do algorítiom 65432 */
SET @var1 = 6 /* 2a parte do algorítimo começando de "6" */
SET @resultado = 0
WHILE (@indice <= 5) BEGIN
SET @soma = @soma + CONVERT(int,SUBSTRING(@cnpj,@indice,1)) * @var1
SET @indice = @indice + 1 /* navegando um-a-um até < = 5, as quatro primeira posições */
SET @var1 = @var1 - 1 /* subtraindo o algorítimo de 6 até 2 */
END
/* cálculo da 2ª parte do algorítiom 98765432 */
SET @var2 = 9
WHILE (@indice <= 13) BEGIN
SET @soma = @soma + CONVERT(int,SUBSTRING(@cnpj,@indice,1)) * @var2
SET @indice = @indice + 1
SET @var2 = @var2 - 1
END
SET @dig2 = (@soma % 11)
/* se o resto da divisão for < 2, o digito = 0 */
IF @dig2 < 2 BEGIN
SET @dig2 = 0
END ELSE BEGIN /* se o resto da divisão não for < 2*/
SET @dig2 = 11 - (@soma % 11)
END
-- validando
IF (@dig1 = SUBSTRING(@cnpj,LEN(@cnpj)-1,1)) AND (@dig2 = SUBSTRING(@cnpj,LEN(@cnpj),1)) BEGIN
SET @resultado = 1
END ELSE BEGIN
SET @resultado = 0
END
RETURN (@resultado)
END;
GO
-- chamada da function
-- test 1
SELECT dbo.usf_valida_cnpj('00000000000191'); -- Banco do Brasil Sede - 1 (válido)
-- test 2
SELECT dbo.usf_valida_cnpj('191'); -- Banco do Brasil Sede - 1 (válido)
-- test 3
SELECT dbo.usf_valida_cnpj('00000000000192'); -- Banco do Brasil Sede - 0 (inválido)
Este comentário foi removido pelo autor.
ResponderExcluirGosto muito da solução do Euler Taveira, que resolve com SQL puro. Vide: http://wiki.postgresql.org/wiki/CNPJ
ResponderExcluirOlá Fábio, também gosto, porém a solução dada por Euler é para Postgres, talvez adaptar para Oracle seja mais fácil, porém para SQL SERVER não é, pois que não encontrei uma função equivalente ao generate_series do Postgres no SQL SERVER
ExcluirEntretanto aceito sugestões. :)
Excluir