DICAS

Visite a biblioteca de dicas da comunidade.

Saiba mais

ARTIGOS

Abordagens detalhadas sobre assuntos diversos.

Saiba mais

INICIANTES

Aprenda a programar de um modo simples e fácil.

Saiba mais

DOWNLOADS

Acesse os materiais exclusivos aos membros.

Saiba mais
voltar

PARA QUEM GOSTA DE DELPHI

Stored Procedure e function ROUNDABNT para SQL Firebird

Fala galera do Show Delphi, tudo beleza?

Este dias estava tendo problemas com o uma nota de consumidor emitida e os dados salvos.
Percebi que tinha um caso em que o valor total do item era 1,365.

Para a NFC-e ia 1,36 e para o banco 1,37.

As configurações era para arredondar.

Ai estudando percebi que o arredondamento interno utilizado era conforme a ABNT e neste caso 1,345 fica 1,34.

Exemplo
de 0 a 4 na segunda casa, 5 na terceira arredonda para baixo,
5 a 9 na segunda casa, 5 arredonda para cima.

Como meu procedimento estava no banco, precisei uma forma de fazer este arredondamento via SQL.

E no caso estava utilizando o Firebird.

Para minha sorte encontrei uma function para firebird 3.0 e uma stored procedure para firebird 2.5.

Então vamos ao código!

FUNCTION – PARA FIREBIRD 3.0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
CREATE OR ALTER FUNCTION ROUNDABNT (
    AVALOR DOUBLE PRECISION,
    ADECIMAIS SMALLINT)
RETURNS DOUBLE PRECISION
AS
DECLARE variable cDecimais VARCHAR(100);
DECLARE variable vlrstr VARCHAR(100);
DECLARE variable nSubsequente SMALLINT;
DECLARE variable posponto SMALLINT;
BEGIN
 vlrstr = CAST(AVALOR AS VARCHAR(100));
 posponto = POSITION('.',vlrstr);
 cDecimais = SUBSTRING(vlrstr FROM posponto+1 FOR CHAR_LENGTH(vlrstr));
 nSubsequente = ADECIMAIS+1;
 IF (:ADECIMAIS < 1) THEN
  RETURN TRUNC(AVALOR);
 ELSE
 IF (CHAR_LENGTH(cDecimais) <= :ADECIMAIS) THEN
  RETURN AVALOR;
 ELSE
  BEGIN
   IF ((CAST(SUBSTRING(cDecimais FROM nSubsequente FOR 1) AS INTEGER) > 5) OR
       (CAST(SUBSTRING(cDecimais FROM nSubsequente FOR 1)AS DOUBLE PRECISION)  < 5))  THEN
    RETURN ROUND(AVALOR,ADECIMAIS);
   ELSE
   IF (CAST(SUBSTRING(cDecimais FROM nSubsequente FOR 1)AS DOUBLE PRECISION) = 5) THEN
    IF (MOD(CAST(SUBSTRING(cDecimais FROM ADECIMAIS FOR 1)AS DOUBLE PRECISION) ,2) <> 0) THEN
     RETURN ROUND(AVALOR,ADECIMAIS);
   ELSE
   IF (CAST(SUBSTRING(cDecimais FROM nSubsequente+1 FOR 1)AS DOUBLE PRECISION) > 0) THEN
    RETURN ROUND(AVALOR,ADECIMAIS);
   ELSE
    RETURN TRUNC(AVALOR,ADECIMAIS);
  END
END

Exemplo de uso da function em firebird 3.0

1
2
3
4
5
6
7
8
9
10
SELECT
roundabnt(1.645, 2) AS exemplo1,
 
roundabnt(1.655, 2) AS exemplo2,
 
roundabnt(1.605, 2) AS exemplo3,
 
roundabnt(1.605, 2) AS exemplo4
 
FROM rdb$database

STORED PROCEDURE – PARA FIREBIRD 2.5

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
CREATE OR ALTER PROCEDURE SP_ROUNDABNT (
    AVALOR DOUBLE PRECISION,
    ADECIMAIS SMALLINT)
RETURNS
  (
   VALOR DOUBLE PRECISION
  )
AS
DECLARE VARIABLE CDECIMAIS VARCHAR(100);
DECLARE VARIABLE VLRSTR VARCHAR(100);
DECLARE VARIABLE NSUBSEQUENTE SMALLINT;
DECLARE VARIABLE POSPONTO SMALLINT;
BEGIN
     VLRSTR = CAST(AVALOR AS VARCHAR(100));
     POSPONTO = POSITION('.',VLRSTR);
     CDECIMAIS = SUBSTRING(VLRSTR FROM POSPONTO+1 FOR CHAR_LENGTH(VLRSTR));
     NSUBSEQUENTE = ADECIMAIS+1;
     IF (:ADECIMAIS < 1) THEN
     BEGIN
        VALOR = TRUNC(AVALOR);
        SUSPEND;
        exit;
     END
     ELSE
     IF (CHAR_LENGTH(CDECIMAIS) <= :ADECIMAIS) THEN
     BEGIN
        VALOR = AVALOR;
        SUSPEND;
        exit;
     END
     ELSE
     BEGIN
       IF ((CAST(SUBSTRING(CDECIMAIS FROM NSUBSEQUENTE FOR 1) AS INTEGER) > 5) OR
           (CAST(SUBSTRING(CDECIMAIS FROM NSUBSEQUENTE FOR 1)AS DOUBLE PRECISION)  < 5))  THEN
       BEGIN
           VALOR = ROUND(AVALOR,ADECIMAIS);
           SUSPEND;
           exit;
       END
       ELSE
       IF (CAST(SUBSTRING(CDECIMAIS FROM NSUBSEQUENTE FOR 1)AS DOUBLE PRECISION) = 5) THEN
       BEGIN
               IF (MOD(CAST(SUBSTRING(CDECIMAIS FROM ADECIMAIS FOR 1)AS DOUBLE PRECISION) ,2) <> 0) THEN
               BEGIN
                  VALOR = ROUND(AVALOR,ADECIMAIS);
                  SUSPEND;
                  exit;
               END
               ELSE IF (CAST(SUBSTRING(CDECIMAIS FROM NSUBSEQUENTE+1 FOR 1)AS DOUBLE PRECISION) > 0) THEN
               BEGIN
                  VALOR = ROUND(AVALOR,ADECIMAIS);
                  SUSPEND;
                  exit;
               END
               ELSE
               BEGIN
                   VALOR = TRUNC(AVALOR,ADECIMAIS);
                   SUSPEND;
                   exit;
               END
       END
    END
END

Fonte Base: https://www.projetoacbr.com.br/forum/topic/9709-minha-pequena-contribui%C3%A7%C3%A3o-arredondamento-abnt/

Exemplo de uso da stored procedure em firebird 2.5

1
2
3
4
5
6
7
8
9
10
SELECT
(SELECT a.valor FROM SP_ROUNDABNT(1.645, 2) a) AS exemplo1,
 
(SELECT a.valor FROM SP_ROUNDABNT(1.655, 2) a) AS exemplo2,
 
(SELECT a.valor FROM SP_ROUNDABNT(1.605, 2) a) AS exemplo3,
 
(SELECT a.valor FROM SP_ROUNDABNT(1.605, 2) a) AS exemplo4
 
FROM rdb$database

Pessoal, os códigos acima foram muito úteis para mim e espero que ajude a todos.

Um abraço e até a próxima.

Valeu!

Facebook Comments Box
  • Giovani Da Cruz
  • 4.152 views
  • 0 comentários
  • 27 de dezembro de 2019

Está gostando do conteúdo? Considere pagar um cafezinho para nossa equipe!

Deixe um comentário

Ir ao topo

© 2024 Infus Soluções em Tecnologia - Todos os Direitos Reservados