Question Quelles sont les erreurs courantes des programmeurs pl / sql avec le calcul de l'argent?


Salut, je cherche des erreurs communes que les programmeurs de pl / sql font quand ils programment des applications qui traitent beaucoup de calculs monétaires. (Réductions, taxes, tarifs, etc.) J'avais utilisé java et hibernate pour les calculs monétaires car pour autant que je me souvienne, java possède un ensemble de règles et de bonnes pratiques telles que BigDecimal pour préserver la précision, etc. C'est pour ça que je veux savoir cela et les éviter. Y a-t-il également une meilleure pratique pour le mantra ou le pl / sql? Merci d'avance les gars.


11
2017-08-26 02:09


origine


Réponses:


En utilisant cet exemple:

create table t_val
  (id number(10,0),
  value number(5,2));

declare
  v_dummy number;
begin
  delete from t_val;
  for i in 9 .. 20 loop
    insert into t_val values (i, 1/i);
    select count(*)
    into v_dummy 
    from t_val 
    where value = 1/i;
    dbms_output.put_line(to_char(i,'00')||':'||v_dummy||':'||
              to_char(1/i,'000.999999'));  
  end loop;
  --
end;
/

select id, value from t_val order by 1;

Vous pouvez voir que le code insère, par exemple, 0.11111 qui est implicitement arrondi à 0.11 Lorsque le code essaie immédiatement de compter les valeurs pour 0.11111, il ne parvient pas à trouver de correspondances.

De même, les valeurs pour (1/14) et (1/15) sont arrondies à 0,07.

Ce n'est pas un problème spécifique à PL / SQL, et j'ai vu des problèmes similaires dans le code Java et PHP lorsque la valeur dans le "client" est arrondie quand elle entre dans la base de données. PL / SQL offre cependant une meilleure solution, car vous pouvez déclarer une variable du type d'une table / colonne spécifique, et cette liaison est maintenue même si la colonne est modifiée.

declare
  v_value  t_val.value%type;
  v_dummy number;
begin
  delete from t_val;
  for i in 9 .. 20 loop
    v_value := 1/i;
    insert into t_val values (i, v_value);
    select count(*)
    into v_dummy 
    from t_val 
    where value = v_value;
    dbms_output.put_line(to_char(i,'00')||':'||v_dummy||':'||
            to_char(1/i,'000.999999')||':'||to_char(v_value,'000.999999'));  
  end loop;
  --
end;
/

La meilleure pratique consiste donc à utiliser des variables de liaison ancrées au type (y compris la longueur / l’échelle / la précision) de la table sous-jacente.


6
2017-08-27 04:06



Voici 2 astuces rapides:

L'astuce Oracle pratique: utilisez NUMBER (sans scale / prec) à la fois en tant que type de colonne de table et en PL / SQL .. vous évite beaucoup de maux de tête. NUMBER (x, y) ne vous permet pas de sauvegarder vos cycles de stockage ou processeurs.

L'indice général (vous voulez d'abord avoir la grande image):

  • Tout d'abord, recherchez quelles sont vos exigences spécifiques en matière d'arithmétique décimale: faites-vous des taxes? si oui, US ou UE? les règles d'arrondi sont différentes selon la juridiction et / ou l'application. Oracle SQL prend-il en charge les éléments souhaités? Est-ce que PL / SQL? Sinon, l'erreur consiste à utiliser PL / SQL pour faire cela de toute façon.

  • Le prochain standard en or pour l'arithmétique décimale est IEEE decimal128. Vous voudrez peut-être lire sur Wikipedia et probablement http://www.carus-hannover.de/doc/DFP_PW6_in_SAP_NetWeaver_0907.pdf par exemple. Il ne supporte que les arrondis, etc. Ne sait pas quand il s'agit d'Oracle QL / PL / SQL


5
2017-08-28 20:39



Le problème avec les types d’argent dans toutes les langues est le suivant:

  • Troncature - Quand vous auriez dû arrondir mais à la place le résultat a été tronqué.
  • Arrondi - Quand tu aurais dû tronquer, mais ça a été arrondi.

Si vous faites attention à ces étapes, la manipulation de MONEY n'est pas une tâche difficile.


4