ITPUB??ì3
12月微软Hyper-V虚拟化沙龙主题征集
ITPUB论坛 » Oracle Fusion中间件 » Oracle8i和9i中PLSQL程序的不同运行结果

标题: [精华] Oracle8i和9i中PLSQL程序的不同运行结果
离线 depp
隐忍猪卷风


精华贴数 3
个人空间 0
技术积分 1545 (1109)
社区积分 58 (4602)
注册日期 2001-11-5
论坛徽章:5
管理团队成员ITPUB元老管理团队2006纪念徽章会员2006贡献徽章授权会员 
      

发表于 2004-8-24 16:26 
Oracle8i和9i中PLSQL程序的不同运行结果

在把ORACLE的数据库从8i升级到9i及以上的时候,一般认为原有的PLSQL程序应该完全兼容,即运行过程和运行结果完全一致。遗憾的是,事实并非如此,由于ORACLE PLSQL引擎的升级,它对某些代码解释做了更改,导致某些代码会有不同的运行结果。各位在升级数据库时必须重视,否则将导致无法估量的损失和难以恢复的灾难。

1,        PLSQL表作为参数传递

先看以下代码,在ORACLE 8i和9i中的运行结果。
declare

  type test_rec is record
      (
       col_1   varchar2(100)
      );

  type test_tbl is table of test_rec index by binary_integer;

  l_tbl test_tbl;

  procedure change_value
  is
  begin
     l_tbl(1).col_1 := 'I am changed!';
  end;
  
  procedure sub_test(pi_str in varchar2)
  is
  begin
    dbms_output.put_line('before: '||pi_str);
    change_value;
    dbms_output.put_line('after : '||pi_str);
  end;
  
begin

  l_tbl(1).col_1 := 'I am ok!';
  sub_test(l_tbl(1).col_1);

  exception  
    when others then
       dbms_output.put_line(sqlerrm);
end;
示例代码非常简单,即将PLSQL表的某个成员变量当作参数给另一过程,此过程改变了原PLSQL表的值,但未改变传入参数的值(当然不能改,表示为IN的参数的值是不能改的),观看改变前后,传入参数的值在Oracle 8i和9i的变化:

运行结果:
Oracle 8i                              Oracle 9i
before: I am ok!                   before: I am ok!
after : I am ok!        after : I am changed!

显然运行结果不一样!在Oracle 8i中,传入参数的值在原PLSQL表的值改变前后未变化,而在Oracle 9i中,传入参数的值被改动了。

Oracle给出的解释是:在Oracle 8i中,所有表示为IN的参数传递都是传值的,包括PLSQL表类型的参数。而到了Oracle 9i,他们觉得PLSQL表类型的参数传递应该传引用,在PLSQL引擎上做了这样的修改,而导致这个问题。

我们来回忆以下,传值意味2个变量传递的是真实的数值,各自有不同的内存空间,相当于变量被拷贝了一份,各为其主,互不相干。传引用意味2个变量传递的是内存空间的地址,指向同一块内存空间,如果此内存空间里放的数值被改变了,那么2个变量的值都会被改变。

了解问题产生的原因,回头再读前面的示例代码,就比较容易理解了。同样的程序,在数据库升级后产生了不同的运行结果,这个问题的危险程度相信大家一定能明白,必须重视。


2,        PLSQL表类型返回值NO_DATA_FOUND意外

看以下代码:
DECLARE
  l_test VARCHAR2(10);
  type test_rec is record (col_a varchar2(100));
  
  TYPE test_tab IS TABLE OF test_rec INDEX BY BINARY_INTEGER;
  
  l_test_tab test_tab;
  
  FUNCTION return_tbl ( pi_dummy IN VARCHAR2 )
    RETURN test_tab
  IS
    l_tbl test_tab;
  BEGIN
    l_tbl.DELETE;
    l_tbl(1).col_a := 'I am ok!';
    RETURN l_tbl;
  EXCEPTION
    WHEN OTHERS THEN
      l_tbl.DELETE;
      RETURN l_tbl;
  END;
BEGIN
  l_test_tab := return_tbl('');
  l_test := l_test_tab(1).col_a;
  DBMS_OUTPUT.PUT_LINE ( 'before: ' || l_pol_num );

  l_test := return_tbl('')(1).col_a;
  DBMS_OUTPUT.PUT_LINE ( 'after : ' || l_test );
EXCEPTION
  WHEN NO_DATA_FOUND THEN
    DBMS_OUTPUT.PUT_LINE ( 'NO_DATA_FOUND exception!' );
END;

这段代码意味某函数返回一个PLSQL表类型的值,然后不同的引用方式,在屏幕上显示。
运行结果:
Oracle 8i                            Oracle 9i
before: I am ok!                 before: I am ok!
after : I am ok!        NO_DATA_FOUND exception!

在Oracle 8i中,直接用函数名和下标访问PLSQL表的成员变量是合法的,但到了Oracle 9i,这种方式会导致一个运行期NO_DATA_FOUND意外,而产生不同的运行结果。

这个问题Oracle没有给出严格解释,只是指出这样的方式不再合法而已。大家同样需要重视这个问题,以免掉入这个陷阱。

数据库的升级导致PLSQL程序有不同的运行结果,这样的问题让人担忧,ORACLE的行事方式让人头疼。若有很多的FORM、REPORT和PLSQL存储过程,这个问题导致的代码检查修改和产生的工作量是非常巨大的,而且后期测试也需要消耗大量的资源。希望ORACLE以后不要再发生这样的事情,那真会伤了一直很信任你的粉丝们的心。


__________________
天生蠢材也有用,美眉跑掉还会来混迹于应用服务器版 ,如有兴趣可致邮depp@itpub.net欢迎光临我的博客站MSN:joizhang@21cn.com
顶部
离线 gengmao
谦卑之心


精华贴数 1
个人空间 0
技术积分 1011 (1844)
社区积分 27 (6668)
注册日期 2001-10-9
论坛徽章:6
ITPUB元老管理团队2006纪念徽章会员2006贡献徽章授权会员生肖徽章2007版:鼠生肖徽章2007版:鸡
      

发表于 2004-8-24 22:46 
Sigh...
pl/sql从来没有严格的语言规范。即使有,oracle也是想改就改。。。


顶部
离线 孤岛
资深会员



精华贴数 0
个人空间 0
技术积分 633 (3056)
社区积分 16598 (93)
注册日期 2003-4-12
论坛徽章:63
Heart of PUBITPUB北京九华山庄2008年会纪念徽章2008北京奥运纪念徽章:篮球生肖徽章2007版:狗2008北京奥运纪念徽章:手球2008北京奥运纪念徽章:跳水
2008北京奥运纪念徽章:排球2008北京奥运纪念徽章:沙滩排球2008北京奥运纪念徽章:蹦床   

发表于 2008-1-8 16:51 
恩,这个帖子真的是非常震撼阿,搞了这么多年这些东西,都没有发现有这样的问题,不知道楼主是这么发现的,佩服一下这种钻研精神啊。

对于第一个,我个人还是比较赞同oracle公司的解释:这个表变量,顾名思义,我们就把他当成一个table来理解:
在同一个session,改变了表的值,最后取得值应该是这个表的最新值。
这样子去想,个人感觉,传引用比传值更合理阿


__________________
空白
顶部
离线 flowerbird
老会员


精华贴数 0
个人空间 0
技术积分 750 (2575)
社区积分 1788 (670)
注册日期 2004-12-25
论坛徽章:16
红孩儿2008北京奥运纪念徽章:足球2008北京奥运纪念徽章:垒球2008北京奥运纪念徽章:花样游泳生肖徽章2007版:羊生肖徽章2007版:牛
生肖徽章2007版:兔生肖徽章2007版:鸡生肖徽章2007版:鼠生肖徽章2007版:鼠生肖徽章2007版:鼠生肖徽章2007版:鼠

发表于 2008-1-14 13:34 
......


__________________
以儒修身,以道端行,以佛悯苍生
http://www.frappr.com/?a=myfrappr&id=536261
顶部
离线 jetbo
思维创造动力


精华贴数 0
个人空间 0
技术积分 566 (3452)
社区积分 53 (4814)
注册日期 2003-10-10
论坛徽章:2
授权会员ITPUB新首页上线纪念徽章    
      

发表于 2008-3-17 13:56 
类似问题遇到的太多了,8i,9i,10g,经常会遇到...


__________________
提供Oracle EBS银行、航空、钢铁、贸易、制造行业财务、分销、制造业务及二次开发解决方案
UnderWorld:OracleERP有一感觉叫"口渴",有一种动作叫"喝水"...
顶部
离线 ora2008


精华贴数 0
个人空间 40
技术积分 2465 (648)
社区积分 134 (3027)
注册日期 2008-5-6
论坛徽章:5
      
      

发表于 2008-5-6 21:50 
8i可惜沒用過


__________________
享受ORACLE......,我的观点是快乐ORACLE.---米卢
顶部
 
    


CopyRight 1999-2006 itpub.net All Right Reserved.
北京皓辰广域网络信息技术有限公司. 版权所有
E-mail:Webmaster@itpub.net
京ICP证:010037号 联系我们 法律顾问