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


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


1383
2017-08-26 02:09


起源

为什么你认为这是一个错误?我的意思是与我的问题相关 资金计算,java和Oracle / PL SQL之间的比较使用 有人甚至建议使用pl / sql 100% - royjavelosa
Oracle几乎无处不在地使用十进制数字(您必须尽量使用二进制数字)。但是,插入到表中会默默地将值截断为数字格式,因此存在一些舍入错误的范围(如果其他人投票重新打开问题,我会扩展它) - Gary Myers
我真的不知道为什么他们关闭这个问题时,我问的是新的pl / sql程序员常犯的错误?这个问题的目的是避免这些错误,并从SO中的pl / sql专家那里学习最佳实践。这个问题甚至没有将pl / sql与任何事情进行比较以引发任何辩论或争论。除非pl / sql在处理货币计算时没有任何已建立的最佳实践,否则我找不到关于陷阱和最佳实践的任何问题,我强烈怀疑这是因为pl / sql已经存在了很长时间。 - royjavelosa
我承认这是一个有点主观的问题,但这是一个主题,对于有财务应用程序使用PL / SQL经验的开发人员可能会有特定的,可支持的建议。 (可悲的是,我不是那个人。)重新开放。 - Dave Costa
@dave costa谢谢戴夫:) - royjavelosa


答案:


使用此示例:

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语句时,使用锚定到基础表的类型(包括长度/比例/精度)的绑定变量。


6
2017-08-27 04:06



更多请:)你也知道任何关于货币计算的pl / sql最佳实践的链接/博客吗? - royjavelosa


以下是2个快速提示:

实用的Oracle技巧:使用NUMBER(没有scale / prec)作为表列类型和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


5
2017-08-28 20:39





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

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

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


4