我申请这个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
woBM;B0  2  import java.math.BigDecimal;
AOJ @5Q/aa!B0  3  public class pi extends Object
#s z R#};G0b0  4  {ITPUB个人空间;@!|-@op[4l%?:iI;S
  5   public static String pi (int n)
fs~;J"|?7g2I9iF0  6   {ITPUB个人空间&`*q-z,XTLv` h
  7    BigDecimal result = new BigDecimal(1);ITPUB个人空间 R#mY1zx
  8    for (int i=n;i>0;i--)ITPUB个人空间 `)p `2Bx!_M
  9    {ITPUB个人空间2u&GEoM(XKo
 10     BigDecimal temp = new BigDecimal(i);ITPUB个人空间;I,@i!P7Bed
 11     result = new BigDecimal(2).addITPUB个人空间c(V~mu8g:R
 12      (result.multiply
#gR2n~LnsFHLZ \0 13       (temp.divide(new BigDecimal(1).add
bJf6p#hq0 14        (temp.multiply
/kz},BX ?pH0 15         (new BigDecimal(2))ITPUB个人空间FOQ)f4s?
 16        ),102,BigDecimal.ROUND_HALF_UP)
:@\9l_-yE`1m0 17       )ITPUB个人空间%G|iI"p%_6~-XX
 18      );ITPUB个人空间Ov!uR8vPB*s
 19    }ITPUB个人空间B7e%wD1h!r
 20    return result.toString();
9k!u,V9y2b0 21   }
k(f-C(J[0 22  }ITPUB个人空间2~+Yk*b6L*_
 23  /

Java已创建。

SQL> create or replace function f_pi (p_n in number) return varchar2 asITPUB个人空间5Bh(Z/r-}]Z
  2  language java name 'pi.pi(int) return String';
3CK*UI Kz~m|G_ y0  3  /

函数已创建。

下面是调用结果:

SQL> select f_pi(10) from dual;

F_PI(10)
F:JA BO$u0----------------------------------------------------------------------------------------------------
0xh3ddi-K%b03.14084209564085725076437150740556313311731268387615136841143033093497489782319503681732783899966562

SQL> select f_pi(20) from dual;

F_PI(20)ITPUB个人空间2E0y YG2`k:i L4cK
----------------------------------------------------------------------------------------------------
.w.e,vL,^a03.14159211320774327955203808659259711079349608208228689356906807763678437061385664739133875908352702

SQL> select f_pi(50) from dual;ITPUB个人空间"Ie:n ~ Ple
select f_pi(50) from dualITPUB个人空间k-s%TC0F-jQFvj
                     *
0z$H-_5X6O9_'DV1H0
1行出现错误:ITPUB个人空间)k3X'q#V a,ST v_eW
ORA-24345:
出现截断或空读取错误


`#W7t4`5X:i^0ERROR:
R,O7g8YZ1zx2[Qt0ORA-01002:
提取违反顺序

 

未选定行

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

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

SQL> create or replace and compile java source named "pi" as
[!X1hn$h(E0  2  import java.math.BigDecimal;ITPUB个人空间@+^MEkP
  3  public class pi extends ObjectITPUB个人空间k4X,qx\ A"\+n [-H
  4  {
m+B-B0U%z_{0  5   public static String pi (int n)
u#a1e~]7or%^:B t0  6   {
n9w0O rV'gwY l$o0  7    BigDecimal result = new BigDecimal(1);
?$}-dA)ATw$y0  8    for (int i=n;i>0;i--)ITPUB个人空间Yk bUQh`T
  9    {ITPUB个人空间\,D4v_/[;`6Z
 10     BigDecimal temp = new BigDecimal(i);ITPUB个人空间6t0oe*C:@Z
 11     result = new BigDecimal(2).addITPUB个人空间c(v g CB"KW
 12      (result.multiply
;r2`%~:}7a0 13       (temp.divide(new BigDecimal(1).addITPUB个人空间x4zQ1p0[(X#@ H9e7Y9c
 14        (temp.multiplyITPUB个人空间T)m%r!w M_
 15         (new BigDecimal(2))ITPUB个人空间;SVf PQ)D
 16        ),10,BigDecimal.ROUND_HALF_UP)
#b/K;\~R{0 17       )ITPUB个人空间*SHw[.ia2j
 18      );
8K0MUh"lr5Gq0X3n0 19    }ITPUB个人空间^!Y|Sr0k+N,k
 20    return result.toString();
h)SsE5S-H-Db0 21   }ITPUB个人空间r[ X*u+PW
 22  }ITPUB个人空间\,nap [:wF
 23  /

Java已创建。

SQL> select f_pi(100) from dual;
5E-vH#We0select f_pi(100) from dual
&x{W3]j,z:[ {-d0*ITPUB个人空间K:`U&ix(Z
1行出现错误:ITPUB个人空间!itn T5Q3^3NS
ORA-29549:
YANGTK.pi已更改, Java会话状态被清除


4Nhu {5Q%L,W'?1e0SQL> select f_pi(100) from dual;

F_PI(100)
S!X@x c~,`.Z#v1Q0----------------------------------------------------------------------------------------------------ITPUB个人空间#e wAH:} s
3.14159265347479757400080071875069256317928871566570517689083488598820471276504302524793754286818752

SQL> select f_pi(200) from dual;

F_PI(200)
/m[ wy*O)tQ,p5u@;M0----------------------------------------------------------------------------------------------------ITPUB个人空间;R9Oo@1|y
3.14159265347479757400080071875090016088532653926425891578738668564238870675937454358049319246851093

SQL> select f_pi(500) from dual;ITPUB个人空间 T1ZVyz~GBn'AP
select f_pi(500) from dual
lyy@;p:}O}(q0                      *
,X/C|Y$wC.w p0
1行出现错误:
{1u2?T }OA0ORA-24345:
出现截断或空读取错误

ITPUB个人空间t5ZQ2|0z Z0KV|V
ERROR:
'u ct8CMw1Qq lw0ORA-01002:
提取违反顺序

 

未选定行

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

SQL> SHOW SGA

Total System Global Area  603979776 bytesITPUB个人空间'C&kTB5Nl9_
Fixed Size                  1249332 bytesITPUB个人空间6NF4}N6[ f.i
Variable Size             239079372 bytes
#F+R[!?9M_0Database Buffers          356515840 bytes
?|[Rs_ d0Redo Buffers                7135232 bytesITPUB个人空间j dK+h)p
SQL> SHOW PARAMETER SGA_TARGET

NAME                                 TYPE        VALUEITPUB个人空间?1M#GsBDG
------------------------------------ ----------- ------------ITPUB个人空间bNyt+m"[-}R Z
sga_target                           big integer576M
Q2^g%W w:t0SQL> SHOW PARAMETER PGA

NAME                                 TYPE        VALUEITPUB个人空间]%GMC [
------------------------------------ ----------- ------------
6L}Hq,t:n5g5f0pga_aggregate_target                 big integer191M

查询了一下错误文档:

ORA-24345: A Truncation or null fetch error occurredITPUB个人空间J+P-|@:~9i \
Cause: A truncation or a null fetch error"
iIAMS2ju B4e0Action: 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" asITPUB个人空间%iEj&v U,F ~r
  2  import java.math.BigDecimal;ITPUB个人空间KFG/`M&F:U(fE
  3  public class pi extends ObjectITPUB个人空间4L x'{]g4^ `
  4  {
B H(_n;tx%W0  5   public static String pi (int n)ITPUB个人空间/myd1s5K-Z4j&Dj%`[
  6   {
)XA|w X~'h0  7    BigDecimal result = new BigDecimal(1);
hxx)`8Q0  8    for (int i=n;i>0;i--)ITPUB个人空间 Y;KA{Vz-J[t}
  9    {
Gnd/h mO!p0 10     BigDecimal temp = new BigDecimal(i);
5W-rVH"[h5NY0 11     result = new BigDecimal(2).add
G9D~N o0 12      (result.multiplyITPUB个人空间5D'r!h v B
 13       (temp.divide(new BigDecimal(1).addITPUB个人空间2M-@4yvr ~ZHi
 14        (temp.multiply
wp$xe9j/a0 15         (new BigDecimal(2))
,wK6R"G ce&v0 16        ),102,BigDecimal.ROUND_HALF_UP)
^(`'D w9Rk0 17       )
P8[`G-L7e)c~A0 18      );ITPUB个人空间:BG~&G]S
 19    }ITPUB个人空间e/U3a6V~5L$O/V*~-z
 20    return result.toString().substring(0,102);
UInC:n L8RT|D0 21   }
Yk#|Mq0 22  }
e}~7Kf'tiX0 23  /

Java已创建。

SQL> select f_pi(100) from dual;ITPUB个人空间NO#QS*}B1F
select f_pi(100) from dualITPUB个人空间-PR'\8H Y&H"W3q"B
*
|'mm&H3N/~0
1行出现错误:
E)O)EF8o0ORA-29549:
YANGTK.pi已更改, Java会话状态被清除


~Sl(]2|5K r0SQL> select f_pi(100) from dual;

F_PI(100)
E5k^"jn0----------------------------------------------------------------------------------------------------
^Q.]'\I m03.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