sexta-feira, 25 de julho de 2008

Validação de CPF - Algoritmo Sem Loops

O algoritmo para validação de CPF pode ser implementado sem loops. A solução alternativa que aparece convertida para Pl/ PgSQL foi retirada do site do Clube do Hardware, com alguns ajustes. O código ficou bem pequeno e os loops foram trocados por operações com vetores. Observe que no PostgreSQL os vetores começam a partir da posição zero.

O código aparece abaixo:

-- Formatar CPF com vetor
CREATE OR REPLACE FUNCTION CPF_Validar_Sem_Loop(par_cpf varchar(11)) RETURNS integer AS $$
-- ROTINA DE VALIDAÇÃO DE CPF SEM LOOP
-- Conversão para o PL/ PGSQL: Cláudio Bezera Leopoldino - http://postgresqlbr.blogspot.com/
-- Algoritmo original: http://forum.clubedohardware.com.br/validacao-cpf/51717
-- Retorna 1 para CPF correto.
DECLARE
vet_cpf integer [11]; --Recebe o CPF DIGITADO
dv integer; -- Primeiro número do DV (Dígito Verificador)
dv1 integer; -- Segundo número do DV (Dígito Verificador)
soma integer; -- Soma utilizada para o cálculo do DV
rest integer; -- Resto da divisão
BEGIN
IF char_length(par_cpf) = 11 THEN
ELSE
RAISE NOTICE 'Formato inválido: %',$1;
RETURN 0;
END IF;
-- Atribuição dos valores do Vetor
vet_cpf[0] := cast(substring (par_cpf FROM 1 FOR 1) as integer);
vet_cpf[1] := cast(substring (par_cpf FROM 2 FOR 1) as integer);
vet_cpf[2] := cast(substring (par_cpf FROM 3 FOR 1) as integer);
vet_cpf[3] := cast(substring (par_cpf FROM 4 FOR 1) as integer);
vet_cpf[4] := cast(substring (par_cpf FROM 5 FOR 1) as integer);
vet_cpf[5] := cast(substring (par_cpf FROM 6 FOR 1) as integer);
vet_cpf[6] := cast(substring (par_cpf FROM 7 FOR 1) as integer);
vet_cpf[7] := cast(substring (par_cpf FROM 8 FOR 1) as integer);
vet_cpf[8] := cast(substring (par_cpf FROM 9 FOR 1) as integer);
vet_cpf[9] := cast(substring (par_cpf FROM 10 FOR 1) as integer);
vet_cpf[10] := cast(substring (par_cpf FROM 11 FOR 1) as integer);
-- CÁLCULO DO PRIMEIRO NÚMERO DO DV
-- Soma dos nove primeiros multiplicados por 10, 9, 8 e assim por diante...
soma:=(vet_cpf[0]*10)+(vet_cpf[1]*9)+(vet_cpf[2]*8)+(vet_cpf[3]*7)+(vet_cpf[4]*6)+(vet_cpf[5]*5)+(vet_cpf[6]*4)+(vet_cpf[7]*3)+(vet_cpf[8]*2);
rest:=soma % 11;
if (rest = 0) or (rest = 1) THEN
dv:=0;
ELSE dv:=(11-rest); END IF;
-- CÁLCULO DO SEGUNDO NÚMERO DO DV
-- Soma dos nove primeiros multiplicados por 11, 10, 9 e assim por diante...
soma:=(vet_cpf[0]*11)+(vet_cpf[1]*10)+(vet_cpf[2]*9)+(vet_cpf[3]*8)+(vet_cpf[4]*7)+(vet_cpf[5]*6)+(vet_cpf[6]*5)+(vet_cpf[7]*4)+(vet_cpf[8]*3)+(dv*2);
rest:=soma % 11;
if (rest = 0) or (rest = 1) THEN
dv1:=0;
ELSE dv1:=(11-rest); END IF;
IF (dv = vet_cpf[9]) and (dv1 = vet_cpf[10]) THEN
RETURN 1;
ELSE
RAISE NOTICE 'DV do CPF Inválido: %',$1;
RETURN 0;
END IF;
END;
$$ LANGUAGE PLPGSQL;

Sintaxe para a chamada da função criada:

SELECT CPF_Validar_Sem_Loop ('número do cpf');

Caso queira relembrar o algoritmo com loops ou ver ais comentários sobre o cálculo de CPF, clique aqui.

4 comentários:

Roger Demetrescu disse...

Valeu pelo artigo.. :)

Uma pergunta, porém: há alguma razão específica de você ter codificado:

IF char_length(par_cpf) = 11 THEN
-- (esse bloco esta vazio)
ELSE
RAISE NOTICE 'Formato inválido: %',$1;
RETURN 0;
END IF;


.. quando poderia ter usado uma lógica mais simples e enxuta como:

IF char_length(par_cpf) <> 11 THEN
RAISE NOTICE 'Formato inválido: %',$1;
RETURN 0;
END IF;


Abraços

Roger

Cláudio Leopoldino disse...

Demetresku, tens toda a razão! Foi erro de copiar e colar de outro programa.

Cláudio Leopoldino disse...
Este comentário foi removido pelo autor.
Renan Denadai disse...

Legal cara, já viu esse site?

http://www.gerardocumentos.com.br/

Muito bom