pl / sql程序员用钱计算会犯的常见错误是什么?

时间:2011-08-26 02:09:24

标签: oracle plsql

您好我正在寻找pl / sql程序员在编写处理大量货币计算的应用程序时所犯的常见错误。 (折扣,税,税率等) 我一直在使用java和hibernate进行货币计算,据我所知,java有一套规则和最佳实践,如BigDecimal,以保持精度等等。现在我试图提高我的pl / sql处理财务模块的技巧这就是为什么我想知道这些陷阱并避免它们。还有任何现有的口头禅或pl / sql最佳实践吗? 先谢谢你们。

3 个答案:

答案 0 :(得分:6)

使用此示例:

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;

您可以看到代码插入,例如,0.11111,它隐式舍入为0.11 当代码立即尝试计算0.11111的值时,它无法找到任何匹配项。

类似地,(1/14)和(1/15)的值都四舍五入为0.07。

这不是PL / SQL特有的问题,当'client'中的值在进入数据库时​​被舍入时,我在Java和PHP代码中看到了类似的问题。 PL / SQL确实提供了更好的解决方案,因为您可以声明特定表/列类型的变量,即使列已更改,也会保持此绑定。

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;
/

因此,最佳实践是,在处理SQL语句时,使用锚定到基础表的类型(包括长度/比例/精度)的绑定变量。

答案 1 :(得分:6)

以下是2个快速提示:

实用的Oracle技巧:使用NUMBER(无缩放/精确)作为表列类型和PL / SQL ..为您节省了很多麻烦。 NUMBER(x,y)不会为您节省任何存储空间或CPU周期..

一般提示(你想先了解大局):

  • 首先,研究一下你对小数运算的具体应用要求是什么:你做税吗?如果是,美国还是欧盟?舍入规则因管辖权和/或申请而异。 Oracle SQL是否支持所需的东西?是PL / SQL吗?如果没有,那么错误就是使用PL / SQL来做那些事情。

  • 即将出现的十进制算术黄金标准是IEEE decimal128。您可能希望阅读维基百科,并可能以http://www.carus-hannover.de/doc/DFP_PW6_in_SAP_NetWeaver_0907.pdf为例。它支持所有舍入等风格。不知道何时涉及到Oracle QL / PL / SQL

答案 2 :(得分:5)

使用任何语言处理MONEY类型的问题是:

  • 截断 - 当你应该舍入但是结果被截断时。
  • 舍入 - 如果你应该截断,但它已经四舍五入。

如果你在每一步都要小心这些,那么处理MONEY并不是一项艰巨的工作。