中国IT动力,最新最全的IT技术教程
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档 | 网通镜像
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 硬件维护 | 未整理篇 | 站长教程
ASP JS PHP工程 ASP.NET 网站建设 UML J2EESUN .NET VC VB VFP 网络维护 数据库 DB2 SQL2000 Oracle Mysql
服务器 Win2000 Office C DreamWeaver FireWorks Flash PhotoShop 上网宝典 CorelDraw 协议大全 网络安全 微软认证
硬件维护  CPU  主板  硬盘  内存  显卡  显示器  键盘鼠标  声卡音箱  打印机  机箱电源  BIOS  网卡  C#  Java  Delphi  vs.net2005
  当前位置:> 程序开发 > 数据库开发 > Oracle
Oracle8i和9i中PLSQL程序不同运行结果
作者:SHENSGANG 时间:2007-06-15 17:37 出处:ccidnet.com 责编:月夜寒箫
              摘要: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以后不要再发生这样的事情,那真会伤了一直很信任你的粉丝们的心。

关闭本页
 
首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
Copyright ©2005-2008 chinaitpower.com All rights reserved. www.chinaitpower.com 版权所有