Oracle:如何实现*几乎*确定性函数?

时间:2013-11-13 11:53:09

标签: oracle oracle10g

我有一个项目,实质上是一批计算。它取决于相当多的参数,虽然它们不是常量(它们可能随时间而变化)但它们无法在批处理上下文中进行更改。

为了清楚起见,请考虑增值税税率:它可能会随着时间的推移而发生变化,但是当一个会计期结束时,它就会对结束本身的行为产生一种常数。

因为这些参数已经到位,我想找到一种尽可能限制数据库查找的方法。理想情况下,我会实现一个DETERMINISTIC函数,但是,这是不可能的 - 正如相关文档所建议的那样。

有任何想法/建议吗?

提前谢谢。

编辑: 还要记住,这些值存储在数据库中 - 因为我们可以保留增值税率,以便我们可以知道其在给定时间点的价值。虽然不会出现这种情况,但有可能是某个前一段时间的批次会再次运行 - 并且需要知道其参数的值,因为它们是然后

DETERMINISTIC函数的好处是,鉴于它产生一致的结果(相同的输入总是给出相同的输出),如果这些值是常量我会做什么,我不想跟踪它们。但文档明确指出,如果函数执行数据库查找,则它绝不能是决定性的。

1 个答案:

答案 0 :(得分:1)

您无法创建“几乎”确定性功能。如果正确调用它,可以创建确定性函数。如果我们假设您正在创建一个简单的函数来计算增值税金额,您可以采取两种方式;首先直接在函数中引用表:

create or replace function calculate_vat is ( 
       P_Sale_Value in number ) return number is

   l_vat number;

begin

   select trunc(vat_rate * P_Sale_Value, 2) into l_vat
     from vat_table
    where ...

   return l_vat;

end;
/

这将被称为:

select sale_value, calculate_vat(sale_value)
  from sales_table

无法将此函数创建为确定性函数,因为表中的值可能会更改。正如the documentation says

  

不要指定此子句来定义使用包变量的函数或以任何可能影响函数返回结果的方式访问数据库

但是,如果将VAT值作为参数传递,则可以以不同方式创建函数:

create or replace function calculate_vat is ( 
       P_Sale_Value in number
     , P_VAT_Rate in number
       ) return number deterministic is

begin    
   return trunc(P_VAT_Rate* P_Sale_Value, 2);    
end;
/

然后,您可以在VAT表上使用JOIN调用它,以便为您提供有效的确定性功能。

select s.sale_value, calculate_vat(s.sale_value, v.vat_rate)
  from sales_table s
  join vat_table v
    on ...
 where ...