Dígito de controle

Forum sobre SQL.

Moderador: Moderadores

Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Dígito de controle

Mensagem por JoséQuintas »

Código: Selecionar todos

FUNCTION CalculaDigito( cNumero, cModulo )

   LOCAL nFator, nCont, nSoma, nResto, nModulo, cCalculo

   hb_Default( @cModulo, "11" )
   IF Empty( cNumero )
      RETURN ""
   ENDIF
   cCalculo := AllTrim( cNumero )
   nModulo  := Val( cModulo )
   nFator   := 2
   nSoma    := 0
   IF nModulo == 10
      FOR nCont = Len( cCalculo ) To 1 Step -1
         nSoma += Val( Substr( cCalculo, nCont, 1 ) ) * nFator
         nFator += 1
      NEXT
   ELSE
      FOR nCont = Len( cCalculo ) To 1 Step -1
         nSoma += Val( Substr( cCalculo, nCont, 1 ) ) * nFator
         IF nFator == 9
            nFator := 2
         ELSE
            nFator += 1
         ENDIF
      NEXT
   ENDIF
   nResto := 11 - Mod( nSoma, 11 )
   IF nResto > 9
      nResto := 0
   ENDIF
   cCalculo := Str( nResto, 1 )

   RETURN cCalculo

Código: Selecionar todos

CREATE FUNCTION `ze_CalculaDigito`(
	`cNumero` VARCHAR(30),
	`nModulo` INT(11)
)
RETURNS VARCHAR(1)
BEGIN
   DECLARE nFator INT(11);
   DECLARE nSoma INT(11);
   DECLARE nCont INT(11);
   DECLARE nResto INT(11);

   IF LENGTH( cNumero ) < 1 THEN
      RETURN '';
   END IF;

   SET nFator = 2;
   SET nSoma = 0;
   SET nCont = LENGTH( cNumero );

   IF nModulo = 10 THEN
      WHILE nCont > 0 DO
         SET nSoma = nSoma + ( CAST( SUBSTR( cNumero, nCont, 1 ) AS INTEGER ) * nFator ) ;
         SET nFator = nFator + 1;
         SET nCont = nCont - 1;
      END WHILE;
   ELSE
      WHILE nCont > 0 DO
         SET nSoma = nSoma + ( CAST( SUBSTR( cNumero, nCont, 1 ) AS INTEGER ) * nFator ) ;
         IF nFator = 9 THEN
            SET nFator = 2;
         ELSE
            SET nFator = nFator + 1;
         END IF;
         SET nCont = nCont - 1;
      END WHILE;
	END IF;

	SET nResto = 11 - MOD( nSoma, 11 );
	IF nResto > 9 THEN
	   SET nResto = 0;
   END IF;

   RETURN CAST( nResto AS VARCHAR(1) );
END
Em fase de testes ainda.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Dígito de controle

Mensagem por JoséQuintas »

Tá divertido isso.
Rotina de calcular dígito

Código: Selecionar todos

CREATE FUNCTION `ze_CalculaDigito`(
	`cNumero` VARCHAR(30),
	`nModulo` INT(11)
)
RETURNS varchar(1) CHARSET latin1
BEGIN
   DECLARE nFator INT(11);
   DECLARE nSoma INT(11);
   DECLARE nCont INT(11);
   DECLARE nResto INT(11);

   IF LENGTH( cNumero ) < 1 THEN
      RETURN '';
   END IF;

   SET nFator = 2;
   SET nSoma = 0;
   SET nCont = LENGTH( cNumero );

   IF nModulo = 10 THEN
      WHILE nCont > 0 DO
         SET nSoma = nSoma + ( CAST( SUBSTR( cNumero, nCont, 1 ) AS INTEGER ) * nFator ) ;
         SET nFator = nFator + 1;
         SET nCont = nCont - 1;
      END WHILE;
   ELSE
      WHILE nCont > 0 DO
         SET nSoma = nSoma + ( CAST( SUBSTR( cNumero, nCont, 1 ) AS INTEGER ) * nFator ) ;
         IF nFator = 9 THEN
            SET nFator = 2;
         ELSE
            SET nFator = nFator + 1;
         END IF;
         SET nCont = nCont - 1;
      END WHILE;
	END IF;

	SET nResto = 11 - MOD( nSoma, 11 );
	IF nResto > 9 THEN
	   SET nResto = 0;
   END IF;

   RETURN CAST( nResto AS VARCHAR(1) );
END
Rotina de retornar só numeros.

Código: Selecionar todos

CREATE FUNCTION `ze_SoNumeros`(
	`cValue` VARCHAR(20)
)
RETURNS varchar(20) CHARSET latin1
BEGIN
DECLARE cReturn VARCHAR(20) DEFAULT '';
DECLARE nCont INTEGER DEFAULT 1;
WHILE nCont <= LENGTH( cValue ) DO
   IF SUBSTR( cValue, nCont, 1 ) IN ( '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ) THEN
      set creturn = CONCAT( creturn, SUBSTR( cvalue, ncont, 1 ) );
   END if;
   SET ncont = ncont + 1;
END WHILE;
RETURN creturn;
END
Rotina de validar CNPJ

Código: Selecionar todos

CREATE FUNCTION `ze_ValidCNPJ`(
	`cCnpj` VARCHAR(20)
)
RETURNS int(11)
BEGIN

DECLARE cNumero VARCHAR(20);
DECLARE lOk INTEGER;
SET cNumero = ze_SoNumeros( cCnpj );
IF LENGTH( cNumero ) <> 14 THEN
   RETURN IF( LENGTH( cNumero ) = 0, 1, 0 );
END IF;
SET cNumero = LPAD( cNumero, 14, '0' );
SET cNumero = SUBSTR( cNumero, 1, 12 );
SET cNumero = CONCAT( cNumero, ze_CalculaDigito( cNumero, 11 ) );
SET cNumero = CONCAT( cNumero, ze_CalculaDigito( cNumero, 11 ) );
SET lOk =  ( Right( cCnpj, 2 ) = Right( cNumero, 2 ) );
IF lOk THEN
   SET cCnpj = CONCAT( SUBSTR( cNumero, 1, 2 ), '.',
               SUBSTR( cNumero, 3, 3 ), '.',
               SUBSTR( cNumero, 6, 3 ), '/',
               SUBSTR( cNumero, 9, 4 ), '-',
               SUBSTR( cNumero, 13, 2 ) );
END IF;

RETURN lOk;

END
Rotina de validar CPF

Código: Selecionar todos

CREATE FUNCTION `ze_ValidCPF`(
	`cCPF` VARCHAR(20)
)
RETURNS int(11)
BEGIN

DECLARE cNumero VARCHAR(20);
DECLARE lOk INTEGER;
SET cNumero = ze_SoNumeros( CCPF );
IF LENGTH( cNumero ) <> 11 THEN
   RETURN IF( LENGTH( cNumero ) = 0, 1, 0 );
END IF;
SET cNumero = LPAD( cNumero, 11, '0' );
SET cNumero = SUBSTR( cNumero, 1, 9 );
SET cNumero = CONCAT( cNumero, ze_CalculaDigito( cNumero, 10 ) );
SET cNumero = CONCAT( cNumero, ze_CalculaDigito( cNumero, 10 ) );
SET lOK = ( RIGHT( cCPF, 2 ) = RIGHT( cNumero, 2 ) );
IF lOK THEN
   SET CCPF = CONCAT(
              SUBSTR( cNumero, 1, 3 ), '.',
              SUBSTR( CNUMERO, 4, 3 ), '.',
              SUBSTR( CNUMERO, 7, 3 ), '-',
              SUBSTR( cNumero, 10, 2 ) );
END IF;

RETURN lOk;

END
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Dígito de controle

Mensagem por JoséQuintas »

Aproveitar pra comentar sobre um erro que cometi durante os testes:
esqueci de dentro do LOOP somar 1

O erro do MySQL foi que a variável não comportava o resultado da operação.
Pode ser interessante conhecer os erros, porque pode acontecer com qualquer um.
E a mensagem com certeza não vai ser igual ao Harbour, que são as mensagens que já conhecemos.

Só não estou gostando de não ter os mesmos recursos do Harbour.
Parece até que estamos voltando ao passado, no tempo de começar a programar, usando recursos mínimos.

Também é ruim não ter um ambiente de testes, ou um modo debug pra acompanhar passo a passo.
E é chato ter que separar CADA rotina em uma função diferente.
Mas... devagar acaba dando certo.

Tudo isso é novidade pra mim, ainda pegando o jeito.
Mas é igual comento com vocês: é começar com as rotinas pequenas, ir se acostumando/revisando, e aos poucos criando rotinas maiores.

Com a validação de CPF e CNPJ, posso, por exemplo, pedir para o MySQL os cadastros irregulares, sem precisar nenhuma checagem pelo programa.
É mais pra ir treinando criar funções.

Mas é como já falei:
Se decidir trocar de linguagem de programação, ou desenvolver pra WEB, ANDROID, etc., basta usar os recursos do MySQL.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Dígito de controle

Mensagem por JoséQuintas »

MySQL 5.7 é chato, comparado ao Mariadb 10.

Válido no Mariadb:

Código: Selecionar todos

DECLARE nVar INT(11);
DECLARE nVar INTEGER;
SET x = CAST( '1' AS INTEGER );
SET x = CAST( '1' AS INT );
SET x = CAST( '1' AS SIGNED );
Válido no MySQL 5.7:

Código: Selecionar todos

DECLARE nVar INT(11);
SET x = CAST( '1' AS SIGNED );
São essas coisas que atrapalham desenvolver no MariaDB e depois instalar no MySQL.

Vou acabar voltando o MySQL 5.7, mas NÃO por problema no MariaDB ou MySQL mais novo, mas pra não ter surpresa nos clientes.

No cliente é sempre a versão mais nova, mas na máquina de desenvolvimento melhor sempre o mais velho de todos os instalados.

Ou......
Começar a pensar em atualizar todos pra última versão do MariaDB.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Responder