我申请这个blog是为了督促自己,把自己平时的一些想法和思考结果保留下来。 本博客所有内容均为原创,如有转载请注明作者和出处

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

上一篇 / 下一篇  2008-08-18 23:50:52 / 个人分类:ORACLE

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

 

 

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

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

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

SQL> create or replace and compile java source named "pi" as
&Tj!ceO\Q0  2  import java.math.BigDecimal;
$SL8y*ZE*s0  3  public class pi extends Object
O1Zpd2N6bYx"l9E0  4  {ITPUB个人空间d5S,esO.p!T
  5   public static String pi (int n)
2AT!o [\0  6   {
D#enxuP6bI7I0  7    BigDecimal result = new BigDecimal(1);
}{3\ K)] pO0  8    for (int i=n;i>0;i--)
-` dug| HO#`}0  9    {
n0[Aj\/B.A#h0 10     BigDecimal temp = new BigDecimal(i);ITPUB个人空间f \L,^"v3II-AcR\(r
 11     result = new BigDecimal(2).addITPUB个人空间[!Lx5z [
 12      (result.multiply
gMU Nh1wM0 13       (temp.divide(new BigDecimal(1).addITPUB个人空间)a+y'Txp~@
 14        (temp.multiplyITPUB个人空间cX R,sk4Z4T
 15         (new BigDecimal(2))
tN+yzsH+k0 16        ),102,BigDecimal.ROUND_HALF_UP)
4a/prKF"y0 17       )
.fL0s%U7z N9KZ0 18      );ITPUB个人空间FC wW FF
 19    }
u?Y!C^(yA~ Iy0 20    return result.toString();
UT @{K[M0hy7d0 21   }ITPUB个人空间1QqP]Bj$`k k
 22  }ITPUB个人空间3p$?.Va3G|Z3v
 23  /

Java已创建。

SQL> create or replace function f_pi (p_n in number) return varchar2 as
*@ |b3\c+o v0  2  language java name 'pi.pi(int) return String';ITPUB个人空间%kQZFSj _
  3  /

函数已创建。

下面是调用结果:

SQL> select f_pi(10) from dual;

F_PI(10)ITPUB个人空间8alMtvw#?
----------------------------------------------------------------------------------------------------
8L$T7fP9_'INnP03.14084209564085725076437150740556313311731268387615136841143033093497489782319503681732783899966562

SQL> select f_pi(20) from dual;

F_PI(20)ITPUB个人空间4VX$}5sJ
----------------------------------------------------------------------------------------------------ITPUB个人空间W}ww0c4mG
3.14159211320774327955203808659259711079349608208228689356906807763678437061385664739133875908352702

SQL> select f_pi(50) from dual;ITPUB个人空间BRuS8r d0D6l
select f_pi(50) from dualITPUB个人空间0|H2|Zv }7WO
                     *
1U(NI?+f!G0
1行出现错误:
~n1}Z\B0ORA-24345:
出现截断或空读取错误

ITPUB个人空间5Z @\wn+xHP6V%Pta
ERROR:ITPUB个人空间/H1l\QV|$cbi
ORA-01002:
提取违反顺序

 

未选定行

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

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

SQL> create or replace and compile java source named "pi" as
cRF'M6O:PYU4y0  2  import java.math.BigDecimal;
e5D1yA d SE3u0  3  public class pi extends ObjectITPUB个人空间f,\ ?'U#m
  4  {ITPUB个人空间2y9s4YMK:s$?;~s
  5   public static String pi (int n)
3_(j$\E \%Z9u0  6   {
^ m@{ sF2sD ~w:z@0  7    BigDecimal result = new BigDecimal(1);
)v*y&d%OkF*d8w `0  8    for (int i=n;i>0;i--)ITPUB个人空间xXW)q)bL\
  9    {
s9oxV m?/zf @0 10     BigDecimal temp = new BigDecimal(i);
1_0Cij W%D @O0 11     result = new BigDecimal(2).add
a/W"DY7l0 12      (result.multiplyITPUB个人空间7Wsa PB
 13       (temp.divide(new BigDecimal(1).addITPUB个人空间 }1eS Nj&KT
 14        (temp.multiplyITPUB个人空间'H_4D!Q e)SxLu
 15         (new BigDecimal(2))
D Ph1vFK&nh%s0 16        ),10,BigDecimal.ROUND_HALF_UP)ITPUB个人空间tu%GJq\.Z$F
 17       )ITPUB个人空间_~C*\z9^$a6j
 18      );
oAH8Oj`0 19    }ITPUB个人空间,wO3XqM-W
 20    return result.toString();ITPUB个人空间:l"unusqCi
 21   }ITPUB个人空间%Au8SH,RK
 22  }
4j"J2c;Y aS"@*S0 23  /

Java已创建。

SQL> select f_pi(100) from dual;ITPUB个人空间MU F-x/XR#nW
select f_pi(100) from dualITPUB个人空间0DT?` ?)|xL9Gw:^
*
'yfq,["Mn#g f$t0
1行出现错误:ITPUB个人空间vG7V.e!ZK:p:e,P/A
ORA-29549:
YANGTK.pi已更改, Java会话状态被清除


o#nhu Y M0SQL> select f_pi(100) from dual;

F_PI(100)ITPUB个人空间5l1paCUN_8ve
----------------------------------------------------------------------------------------------------
G*j!DasQ03.14159265347479757400080071875069256317928871566570517689083488598820471276504302524793754286818752

SQL> select f_pi(200) from dual;

F_PI(200)ITPUB个人空间Z/OQ$y*t:r Ef
----------------------------------------------------------------------------------------------------ITPUB个人空间%a']iOz5S6ckFX o
3.14159265347479757400080071875090016088532653926425891578738668564238870675937454358049319246851093

SQL> select f_pi(500) from dual;
zg3d h ]]0Dw.X|&W0select f_pi(500) from dualITPUB个人空间3CSO9ROq_(g8[
                      *ITPUB个人空间5eOGA&Ao$x
1行出现错误:
;q4p I,[ri0ORA-24345:
出现截断或空读取错误


8E4_ ^c*~:y0ERROR:
s5Kw6\4YE4M C0ORA-01002:
提取违反顺序

 

未选定行

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

SQL> SHOW SGA

Total System Global Area  603979776 bytes
m9n-GA7p,f0Fixed Size                  1249332 bytes
AYM%o0WnS3g ~0Variable Size             239079372 bytesITPUB个人空间2Z R9wYRKV
Database Buffers          356515840 bytesITPUB个人空间#QKL Z$pp7uv4QR1^
Redo Buffers                7135232 bytesITPUB个人空间(x8vB8V7v/Au d2r
SQL> SHOW PARAMETER SGA_TARGET

NAME                                 TYPE        VALUE
5tFh q!SQqYq0------------------------------------ ----------- ------------ITPUB个人空间oT6E*za+sa+G:r
sga_target                           big integer576MITPUB个人空间 ^d~[EP/l7?
SQL> SHOW PARAMETER PGA

NAME                                 TYPE        VALUEITPUB个人空间T$|"rC#]!d
------------------------------------ ----------- ------------ITPUB个人空间9\UL+V+Zv4C
pga_aggregate_target                 big integer191M

查询了一下错误文档:

ORA-24345: A Truncation or null fetch error occurred
c:FnvT%iy fF[0Cause: A truncation or a null fetch error"
+^![%}%Nz.K0Action: 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
[a5U6An-r8[g0  2  import java.math.BigDecimal;
`;_7\IR8gX q!p0  3  public class pi extends Object
${kS0dv7x1ue0  4  {ITPUB个人空间.Il6et;Y!|W
  5   public static String pi (int n)ITPUB个人空间cEjj!w
  6   {ITPUB个人空间9s/n'm4Z EEiO^
  7    BigDecimal result = new BigDecimal(1);ITPUB个人空间QYz,{u |{HwMQ
  8    for (int i=n;i>0;i--)ITPUB个人空间d S;S9f?+Y0\/[%[
  9    {
pT(?%t8L pp0 10     BigDecimal temp = new BigDecimal(i);ITPUB个人空间sS1t%z-L
 11     result = new BigDecimal(2).addITPUB个人空间U"tp/q.GL p
 12      (result.multiply
_4C,Ktn*Q0 13       (temp.divide(new BigDecimal(1).add
1t4J4vjhT0 14        (temp.multiply
J9Ok-U'}x4p+?0 15         (new BigDecimal(2))ITPUB个人空间S)Z:k*L?5oH
 16        ),102,BigDecimal.ROUND_HALF_UP)
0b5T.h'w5H#t.aKCkJw0 17       )ITPUB个人空间 {6E0]0@8W2a
 18      );
/@JF%zIe(hT0 19    }
&@:eFa b~G0 20    return result.toString().substring(0,102);ITPUB个人空间j3G;f{.C\4a8O l
 21   }
Z B4O2C ~4kU@0 22  }
S9?:i(wq5a5es.Y0 23  /

Java已创建。

SQL> select f_pi(100) from dual;ITPUB个人空间{/^8p+E ^P9g/j
select f_pi(100) from dualITPUB个人空间n_zy7QF`V(zF3J
*
:p@R~}-xH0
1行出现错误:ITPUB个人空间'Z*c~4Q%Kr!qY
ORA-29549:
YANGTK.pi已更改, Java会话状态被清除


LB1A"Wm:g0SQL> select f_pi(100) from dual;

F_PI(100)
0ZU7^9qYi0----------------------------------------------------------------------------------------------------
Tsn3x.V} v H03.14159265358979323846264338327929528649084412679106662169776161333278097211785395952441592543372994

 


TAG:

L_yongfei的个人空间 引用 删除 L_yongfei   /   2008-08-20 11:28:47
学习
 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

Open Toolbar