

Olá galera, dando continuidade à série de validação de dados. Agora vou falar como criar a validação de CPF usando um gatilho(trigger) e uma função(function) em MySQL. Para esse post eu usei o script de validação de CPF deste artigo aqui escrito pelo Cristiano Martins Alves, no artigo do Cristiano ele mostra uma função para validação em SQL Server, eu apenas adaptei o código dele para que rode em MySQL, as mudanças foram poucas, quase todas foram em função da diferença de sintaxe(ponto e virgula e loops), da função CONVERT para CAST e da função LEN para LENGTH. Depois das alterações o código ficou da seguinte maneira.
-- -------------------------------------------------------------------------------- -- Routine DDL -- -------------------------------------------------------------------------------- DELIMITER $$ CREATE DEFINER=`root`@`localhost` FUNCTION `validarCpf`(CPF CHAR(11)) RETURNS double BEGIN DECLARE INDICE INT; DECLARE SOMA INT; DECLARE DIG1 INT; DECLARE DIG2 INT; DECLARE CPF_TEMP VARCHAR(11); DECLARE DIGITOS_IGUAIS CHAR(1); DECLARE RESULTADO CHAR(1); SET RESULTADO = FALSE; /* Verificando se os dígitos são iguais A Principio CPF com todos o números iguais são Inválidos apesar de validar o Calculo do digito verificado EX: O CPF 00000000000 é inválido, mas pelo calculo Validaria */ SET CPF_TEMP = SUBSTRING(CPF,1,1); SET INDICE = 1; SET DIGITOS_IGUAIS = 'S'; WHILE (INDICE <= 11) DO IF (SUBSTRING(CPF,INDICE,1) <> CPF_TEMP) Then SET DIGITOS_IGUAIS = 'N'; END IF; SET INDICE = INDICE + 1; END WHILE; /*Caso os dígitos não sejam todos iguais Começo o calculo do dígitos*/ IF (DIGITOS_IGUAIS = 'N') THEN /*Cálculo do 1º dígito*/ SET SOMA = 0; SET INDICE = 1; WHILE (INDICE <= 9) DO SET Soma = Soma + CAST(SUBSTRING(CPF,INDICE,1) AS UNSIGNED) * (11 - INDICE); SET INDICE = INDICE + 1; END WHILE; SET DIG1 = 11 - (SOMA % 11); IF (DIG1 > 9) THEN SET DIG1 = 0; END IF; -- Cálculo do 2º dígito } SET SOMA = 0; SET INDICE = 1; WHILE (INDICE <= 10) DO SET Soma = Soma + CAST(SUBSTRING(CPF,INDICE,1) AS UNSIGNED) * (12 - INDICE); SET INDICE = INDICE + 1; END WHILE; SET DIG2 = 11 - (SOMA % 11); IF DIG2 > 9 THEN SET DIG2 = 0; END IF; -- Validando IF (DIG1 = SUBSTRING(CPF,LENGTH(CPF)-1,1)) AND (DIG2 = SUBSTRING(CPF,LENGTH(CPF),1)) THEN SET RESULTADO = TRUE; ELSE SET RESULTADO = FALSE; END IF; END IF; RETURN RESULTADO; END
Executando esse código naquela nossa base de testes (download e leitura da parte 01) a função validaCpf() vai ser criada no seu banco de dados, para executar a função basta executar um SELECT normal chamando a função validaCpf(), como no exemplo abaixo.
SELECT validarCpf('02452345798') FROM dual
Nesse caso irá retornar 0(zero) que corresponde a false/falso, caso você coloque um cpf válido no teste ele irá retornar 1(um) que corresponde a true/verdadeiro. Sendo assim agora basta colocarmos na nossa trigger essa chamada para a validação.
-- Trigger DDL Statements
DELIMITER $$
USE `testes_roberson`$$CREATE DEFINER=`root`@`localhost` TRIGGER trgValidacaoEmail BEFORE INSERT ON clientes
FOR EACH ROW BEGIN
-- Declaro variável para identificar se está válido ou não
DECLARE email DOUBLE DEFAULT FALSE;
DECLARE cpf DOUBLE DEFAULT FALSE;
-- Verificar se e-mail é válido
IF (NOT EXISTS (SELECT NULL FROM Clientes WHERE NEW.Email REGEXP '^[a-zA-Z0-9]{1}([\._a-zA-Z0-9-]+)(\.[_a-zA-Z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+){1,3}$')) THEN
-- Caso seja inválido atribuo true para a variável email
SET email = TRUE;
END IF;
IF ((SELECT validarCpf(NEW.Cpf) FROM dual) = 0 ) THEN
-- Caso seja inválido atribuo true para a variável cpf
SET cpf = TRUE;
END IF;
-- Verifico se as duas variaveis (email e cpf) estão como true, e mostro o erro
IF (email && cpf) THEN
SELECT 0 FROM `Não foi possível inserir os dados! E-mail e CPF inválidos`INTO @error;
END IF;
-- Verifico se a variável email está como true, e mostro o erro
IF (email) THEN
SELECT 0 FROM `Não foi possível inserir os dados! E-mail inválido`INTO @error;
END IF;
-- Verifico se a variável cpf está como true, e mostro o erro
IF (cpf) THEN
SELECT 0 FROM `Não foi possível inserir os dados! CPF inválido`INTO @error;
END IF;
END$$
Criando essa trigger ou alterando a existente do exemplo anterior, a trigger será disparada todas as vezes que algum dado for ser inserido no banco e verificará tanto e-mail quanto CPF. Eu gostaria de ter feito esse exemplo de uma maneira um pouco diferente, queria armazenar em uma variável a string com o erro a cada verificação, e ao final concatenar elas e exibir o erro, porem não consegui que o CONCAT funciona-se dentro da clausula FROM. Caso alguem consiga algo do tipo, por favor me envie que eu atualizo aqui no script, e eu também vou continuar tentando fazer essa alteração.
O exemplo php da parte 01 continua funcionando da mesma maneira, para testarmos basta mudar no insert para um cpf inválido. Quando o E-mail e/ou CPF forem inválidos o erro será mostrado.
Espero ter contribuido com algo, sugestões, criticas ou elogios são muito bem aceitos. Espero que aproveitem e sucesso a todos.
Veja também:
Validando dados inseridos no banco MySql – Parte 01
Posts relacionados:






More Options ...
Categorias
Nuvem de Tags
Blog RSS
Comentários RSS

Void « Default
Life
Earth
Wind
Water
Fire
Light 
Pq exatamente fazer uma validação em Banco? Ainda mais usando uma trigger
Um dos porque é, digamos que você tenha um unico banco de dados para mais de um aplicativo(web, desktop, mobile, etc), sendo assim a validação não precisa ser feita em cada um dos aplicativos, uma unica validação é feita para todos os aplicativos, fazendo assim com que os dados sejam todos validados da mesma maneira, evitando inconsistencias. Pensando em grandes sistemas aonde existem vários programadores trabalhando em cima do mesmo banco/sistema, evitamos que algum dos programadores esqueça de fazer a validação na tela X ou Y. Pense que dessa forma não tem como o dado entrar incorreto no banco, até mesmo se alguem conseguir colocar uma query diretamente no banco, essa query vai ser validada.
Assim temos 100% de certeza que os dados só entram na tabela se forem válidos.
Talvez o exemplo de email e de CPF não seja o melhor exemplo pois são coisas “banais” que dificilmente são esquecidas, e geralmente são bem testadas, mas se você tiver uma validação peculiar a aquele campo, onde é preciso fazer um calculo complexo, algo não tão comum ou um calculo “secreto” de segurança que não pode ser divulgado nem dentro da propria empresa, nesse caso não precisa ensinar ou divulgar a forma como tal dado é validado, simplesmente o dado só irá entrar no banco se estiver correto. Estou escrevendo um outro post que mostra um exemplo mais peculiar onde a necessidade é mais clara.
Lembrando que triggers e procedures não são só para validações, existem muitas outras utilidades que pretendo exclarecer em próximos posts.
Obrigado pela participação, e espero ter sido claro.
Ótimo post Roberson parabéns!
Só uma observação:
No ultimo END da função de validar CPF faltou o “$$”
Tudo bem Roberson!
Ótimo post, parabéns, só pra endossar ai o que você falou sobre a utilidade de se ter a validação no banco, quando criei a função para SQL Server a estava desenvolvendo um integração com uma URA (Unidade de Resposta Audível) essa o sistemas da URA precisava por meio de funções no banco fazer uma série de consistências uma delas era o CPF que o cliente havia digitado no telefone.
Obrigado Cristiano por esse excelente exemplo de utilização, também tenho usado muito esse tipo de validação em integrações de webservice.
Onde se coloca esse código?
Para utilizar você deve customizar para as suas necessidades e executar no banco de dados da mesma maneira que você executa uma query. Ao Executar as procedures/functions/ trigger serão criadas no seu banco.
Qualquer dúvida manda ai.