JAVA存储过程出现ORA-24345错误

写了一个简单的JAVA存储过程,处理一个精度较大的数学问题,结果碰到了ORA-24345错误。

 

 

由于对JAVA不熟悉,JAVA存储过程也很少使用,因此费了不少时间,总算写了出来,但是在执行的时候发现了一个问题。

这个存储过程是用来计算圆周率的取值的,相关算法可以参考:http://yangtingkun.itpub.net/post/468/468870

关于存储过程就不详细描述了,下面直接看问题的产生:

SQL> create or replace and compile java source named "pi" as
  2  import java.math.BigDecimal;
  3  public class pi extends Object
  4  {
  5   public static String pi (int n)
  6   {
  7    BigDecimal result = new BigDecimal(1);
  8    for (int i=n;i>0;i--)
  9    {
 10     BigDecimal temp = new BigDecimal(i);
 11     result = new BigDecimal(2).add
 12      (result.multiply
 13       (temp.divide(new BigDecimal(1).add
 14        (temp.multiply
 15         (new BigDecimal(2))
 16        ),102,BigDecimal.ROUND_HALF_UP)
 17       )
 18      );
 19    }
 20    return result.toString();
 21   }
 22  }
 23  /

Java 已创建。

SQL> create or replace function f_pi (p_n in number) return varchar2 as
  2  language java name 'pi.pi(int) return String';
  3  /

函数已创建。

下面是调用结果:

SQL> select f_pi(10) from dual;

F_PI(10)
----------------------------------------------------------------------------------------------------
3.14084209564085725076437150740556313311731268387615136841143033093497489782319503681732783899966562

SQL> select f_pi(20) from dual;

F_PI(20)
----------------------------------------------------------------------------------------------------
3.14159211320774327955203808659259711079349608208228689356906807763678437061385664739133875908352702

SQL> select f_pi(50) from dual;
select f_pi(50) from dual
                     *
1 行出现错误:
ORA-24345:
出现截断或空读取错误


ERROR:
ORA-01002:
提取违反顺序

 

未选定行

数据量比较小的时候没有问题,一旦输入参数值比较大,就会出现上面的这个错误。

测试还发现,如果将java存储过程中的除法保留小数位数缩小一些,上面的查询就可以得到结果,但是如果继续增大数据量仍然会导致错误:

SQL> create or replace and compile java source named "pi" as
  2  import java.math.BigDecimal;
  3  public class pi extends Object
  4  {
  5   public static String pi (int n)
  6   {
  7    BigDecimal result = new BigDecimal(1);
  8    for (int i=n;i>0;i--)
  9    {
 10     BigDecimal temp = new BigDecimal(i);
 11     result = new BigDecimal(2).add
 12      (result.multiply
 13       (temp.divide(new BigDecimal(1).add
 14        (temp.multiply
 15         (new BigDecimal(2))
 16        ),10,BigDecimal.ROUND_HALF_UP)
 17       )
 18      );
 19    }
 20    return result.toString();
 21   }
 22  }
 23  /

Java 已创建。

SQL> select f_pi(100) from dual;
select f_pi(100) from dual
*
1 行出现错误:
ORA-29549:
YANGTK.pi已更改, Java 会话状态被清除


SQL> select f_pi(100) from dual;

F_PI(100)
----------------------------------------------------------------------------------------------------
3.14159265347479757400080071875069256317928871566570517689083488598820471276504302524793754286818752

SQL> select f_pi(200) from dual;

F_PI(200)
----------------------------------------------------------------------------------------------------
3.14159265347479757400080071875090016088532653926425891578738668564238870675937454358049319246851093

SQL> select f_pi(500) from dual;
select f_pi(500) from dual
                      *
1 行出现错误:
ORA-24345:
出现截断或空读取错误


ERROR:
ORA-01002:
提取违反顺序

 

未选定行

开始认为是JAVA缓冲区的问题,不过当前系统的SGAPGA的大小对于这个计算应该是绰绰有余的:

SQL> SHOW SGA

Total System Global Area  603979776 bytes
Fixed Size                  1249332 bytes
Variable Size             239079372 bytes
Database Buffers          356515840 bytes
Redo Buffers                7135232 bytes
SQL> SHOW PARAMETER SGA_TARGET

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------
sga_target                           big integer 576M
SQL> SHOW PARAMETER PGA

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------
pga_aggregate_target                 big integer 191M

查询了一下错误文档:

ORA-24345: A Truncation or null fetch error occurred
Cause: A truncation or a null fetch error"
Action: Please ensure that the buffer size is long enough to store the returned data.

这个描述就比较清晰了,由于VARCHAR2长度的限制导致了JAVA存储过程返回的结果没有办法传递给PL/SQL

那么只需要修改一下JAVA代码,返回适当长度的字符串即可:

SQL> create or replace and compile java source named "pi" as
  2  import java.math.BigDecimal;
  3  public class pi extends Object
  4  {
  5   public static String pi (int n)
  6   {
  7    BigDecimal result = new BigDecimal(1);
  8    for (int i=n;i>0;i--)
  9    {
 10     BigDecimal temp = new BigDecimal(i);
 11     result = new BigDecimal(2).add
 12      (result.multiply
 13       (temp.divide(new BigDecimal(1).add
 14        (temp.multiply
 15         (new BigDecimal(2))
 16        ),102,BigDecimal.ROUND_HALF_UP)
 17       )
 18      );
 19    }
 20    return result.toString().substring(0,102);
 21   }
 22  }
 23  /

Java 已创建。

SQL> select f_pi(100) from dual;
select f_pi(100) from dual
*
1 行出现错误:
ORA-29549:
YANGTK.pi已更改, Java 会话状态被清除


SQL> select f_pi(100) from dual;

F_PI(100)
----------------------------------------------------------------------------------------------------
3.14159265358979323846264338327929528649084412679106662169776161333278097211785395952441592543372994

 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/4227/viewspace-429853/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/4227/viewspace-429853/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值