Oi! Seja bem-vindo!
Hoje vamos validar CPFs e CNPJs no SQL Server. Do cálculo matemático a exemplos de código, te mostrarei na prática como conferir se um documento está correto.
CPF e CNPJ, o que são?
Se você é estrangeiro ou não conhece a fundo, CPF e CNPJ são abreviações para:
== CPF: Cadastro Nacional de Pessoa Física
== CNPJ:Cadastro Nacional de Pessoa Jurídica (empresa)
Atualmente, essas são as formas de identificação principais de uma pessoa (CPF) ou empresa (CNPJ) junto a empresas, bancos e órgãos governamentais.
Dada a importância desses documentos, é importante assegurar que nosso banco de dados não permita a inclusão de números inválidos. Então hoje, vou te mostrar como validar um CPF ou CNPJ no seu SQL Server. Porém, o tutorial vai além: Te mostro como é feito o cálculo, assim se você estiver em outro banco como Oracle, MySQL, Postgree ou outro, você pode implementar a mesma lógica.
Como validar CPFs e CNPJs no SQL Server
Aqui vai o script SQL que utilizei no vídeo:
-------------------------------------------------------
-- Como validar CPFs e CNPJs no SQL Server
-------------------------------------------------------
use master
if db_id('curso') is not null
drop database curso
go
create database curso
go
use curso
go
create function valida_cpf_cnpj (@documento varchar(18))
returns bit as
begin
-- Remove caracteres
declare @doc varchar(14) = ''
;with split as (
select 1 as id, substring(@documento, 1, 1) as algarismo
union all
select id + 1, substring(@documento, id + 1, 1)
from split
where id < len(@documento)
)
select @doc += algarismo from split where algarismo like '[0-9]'
-- variáveis
declare
@doc_len int = len(@doc),
@doc_digito1 int = substring(@doc, len(@doc) - 1, 1),
@doc_digito2 int = substring(@doc, len(@doc), 1),
@loop_digitos_verificadores int = 1,
@posicao_proximo_algarismo int,
@somatoria_algarismos_x_coeficientes int,
@coeficiente_multiplicador int,
@algarismo int,
@resto_divisao_inteira int,
@digito_calculado1 int,
@digito_calculado2 int
-- loop: executa uma validação para cada um dos digitos (começa em 1 termina em 2)
while @loop_digitos_verificadores <= 2 begin select @somatoria_algarismos_x_coeficientes = 0, @coeficiente_multiplicador = 2, @posicao_proximo_algarismo = @doc_len + @loop_digitos_verificadores - 3 -- loop: Uma repetição para cada algarismo da raiz do cnpj ou cpf while @posicao_proximo_algarismo >= 0
begin
select
@algarismo = substring(@doc, @posicao_proximo_algarismo, 1),
@somatoria_algarismos_x_coeficientes += @algarismo * @coeficiente_multiplicador,
@coeficiente_multiplicador = @coeficiente_multiplicador + 1,
@posicao_proximo_algarismo -= 1
--print '@algarismo: ' + convert(varchar, @algarismo)
--print '@coeficiente_multiplicador: ' + convert(varchar, @coeficiente_multiplicador - 1)
--print 'produto: ' + convert(varchar, @algarismo * (@coeficiente_multiplicador - 1))
--print '@somatoria_algarismos_x_coeficientes (somatória atual): ' + convert(varchar, @somatoria_algarismos_x_coeficientes)
-- Se for um cnpj reinicia a contagem de coeficientes (para cpf continua)
if @doc_len > 11 and @coeficiente_multiplicador > 9
set @coeficiente_multiplicador = 2
end
--print '@somatoria_algarismos_x_coeficientes (somatória final): ' + convert(varchar, @somatoria_algarismos_x_coeficientes)
set @resto_divisao_inteira = 11 - (@somatoria_algarismos_x_coeficientes % 11)
--print '@resto_divisao_inteira: ' + convert(varchar, @resto_divisao_inteira)
if (@resto_divisao_inteira = 10)
set @resto_divisao_inteira = 0
if @loop_digitos_verificadores = 1
set @digito_calculado1 = @resto_divisao_inteira
else
set @digito_calculado2 = @resto_divisao_inteira
set @loop_digitos_verificadores += 1
end
return
-- select
case
when @digito_calculado1 = @doc_digito1 and @digito_calculado2 = @doc_digito2 then 1
else 0
end
end
/*
-- Teste: Matriz de cálculo:
declare @doc varchar(14) = 12345678000195
;with a as (
select
-- validação primeiro dígito
id = 1,
posicao_d1 = len(@doc) - 2,
coeficiente_d1 = 2,
elemento_d1 = substring(@doc, len(@doc) - 2, 1),
produto_d1 = substring(@doc, len(@doc) - 2, 1) * 2,
-- validação segundo dígito
posicao_d2 = len(@doc) - 1,
coeficiente_d2 = 2,
elemento_d2 = substring(@doc, len(@doc) - 1, 1),
produto_d2 = substring(@doc, len(@doc) - 1, 1) * 2
union all
select
-- digito 1
id + 1,
posicao_d1 - 1,
case when coeficiente_d1 > 8 and len(@doc) = 14 then 2 else coeficiente_d1 + 1 end,
substring(@doc, posicao_d1 - 1, 1),
substring(@doc, posicao_d1 - 1, 1) * case when coeficiente_d1 > 8 and len(@doc) = 14 then 2 else coeficiente_d1 + 1 end,
-- digito 2
posicao_d2 - 1,
case when coeficiente_d2 > 8 and len(@doc) = 14 then 2 else coeficiente_d2 + 1 end,
substring(@doc, posicao_d2 - 1, 1),
substring(@doc, posicao_d2 - 1, 1) * case when coeficiente_d2 > 8 and len(@doc) = 14 then 2 else coeficiente_d2 + 1 end
from a where posicao_d2 - 1 > 0)
select * from a
from (
select
sum(produto_d1) produto_d1,
sum(produto_d2) produto_d2
from a) somatoria
-- Exemplos válidos
select dbo.valida_cpf_cnpj ('12345678000195')
select dbo.valida_cpf_cnpj ('12345678909')
select dbo.valida_cpf_cnpj ('12.345.678/0001-95')
select dbo.valida_cpf_cnpj ('123.456.789-09')
-- Exemplos inválidos
select dbo.valida_cpf_cnpj ('12345678910')
select dbo.valida_cpf_cnpj ('12.345.678/0001-90')
*/
CONCLUSÃO
Admito que falar de cálculo, ou fazer cálculos as vezes é meio chato… 🙂 Mas como você viu não é nada complicado. Principalmente, a função que valida o CPF ou CNPJ já está na mão, prontinha para uso.
Sei o quanto é importante criar mecanismos de proteção para um banco de dados, disso eu sou fã… então montei esse artigo pensando em te inspirar um pouco a proteger seu banco também. Acredite: Tem horas que esse tipo de coisa salva a nossa pele… hohohohoho!
Abraço do seu amigo Josué 🙂