国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 數(shù)據(jù)庫 > Oracle > 正文

Oracle8i和9i中PLSQL程序的不同運(yùn)行結(jié)果

2024-08-29 13:37:48
字體:
供稿:網(wǎng)友

  在把Oracle的數(shù)據(jù)庫從8i升級(jí)到9i及以上的時(shí)候,一般認(rèn)為原有的PLSQL程序應(yīng)該完全兼容,即運(yùn)行過程和運(yùn)行結(jié)果完全一致。遺憾的是,事實(shí)并非如此,由于ORACLE PLSQL引擎的升級(jí),它對(duì)某些代碼解釋做了更改,導(dǎo)致某些代碼會(huì)有不同的運(yùn)行結(jié)果。 各位在升級(jí)數(shù)據(jù)庫時(shí)必須重視,否則將導(dǎo)致無法估量的損失和難以恢復(fù)的災(zāi)難。
  
  1, PLSQL表作為參數(shù)傳遞
  先看以下代碼,在ORACLE 8i和9i中的運(yùn)行結(jié)果。
  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;
  示例代碼非常簡(jiǎn)單,即將PLSQL表的某個(gè)成員變量當(dāng)作參數(shù)給另一過程,此過程改變了原PLSQL表的值,但未改變傳入?yún)?shù)的值(當(dāng)然不能改,表示為IN的參數(shù)的值是不能改的),觀看改變前后,傳入?yún)?shù)的值在Oracle 8i和9i的變化:
  
  運(yùn)行結(jié)果:
  Oracle 8i Oracle 9i
  before: I am ok! before: I am ok!
  after : I am ok! after : I am changed!
  
  顯然運(yùn)行結(jié)果不一樣!在Oracle 8i中,傳入?yún)?shù)的值在原PLSQL表的值改變前后未變化,而在Oracle 9i中,傳入?yún)?shù)的值被改動(dòng)了。
  
  Oracle給出的解釋是:在Oracle 8i中,所有表示為IN的參數(shù)傳遞都是傳值的,包括PLSQL表類型的參數(shù)。而到了Oracle 9i,他們覺得PLSQL表類型的參數(shù)傳遞應(yīng)該傳引用,在PLSQL引擎上做了這樣的修改,而導(dǎo)致這個(gè)問題。
  
  我們往返憶以下,傳值意味2個(gè)變量傳遞的是真實(shí)的數(shù)值,各自有不同的內(nèi)存空間,相當(dāng)于變量被拷貝了一份,各為其主,互不相干。傳引用意味2個(gè)變量傳遞的是內(nèi)存空間的地址,指向同一塊內(nèi)存空間,假如此內(nèi)存空間里放的數(shù)值被改變了,那么2個(gè)變量的值都會(huì)被改變。
  
  了解問題產(chǎn)生的原因,回頭再讀前面的示例代碼,就比較輕易理解了。同樣的程序,在數(shù)據(jù)庫升級(jí)后產(chǎn)生了不同的運(yùn)行結(jié)果,這個(gè)問題的危險(xiǎn)程度相信大家一定能明白,必須重視。
  
  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;
  
  這段代碼意味某函數(shù)返回一個(gè)PLSQL表類型的值,然后不同的引用方式,在屏幕上顯示。
  運(yùn)行結(jié)果:
  Oracle 8i Oracle 9i
  before: I am ok! before: I am ok!
  after : I am ok! NO_DATA_FOUND exception!
  
  在Oracle 8i中,直接用函數(shù)名和下標(biāo)訪問PLSQL表的成員變量是合法的,但到了Oracle 9i,這種方式會(huì)導(dǎo)致一個(gè)運(yùn)行期NO_DATA_FOUND意外,而產(chǎn)生不同的運(yùn)行結(jié)果。

  
  這個(gè)問題Oracle沒有給出嚴(yán)格解釋,只是指出這樣的方式不再合法而已。大家同樣需要重視這個(gè)問題,以免掉入這個(gè)陷阱。
  
  數(shù)據(jù)庫的升級(jí)導(dǎo)致PLSQL程序有不同的運(yùn)行結(jié)果,這樣的問題讓人擔(dān)憂,ORACLE的行事方式讓人頭疼。若有很多的FORM、REPORT和PLSQL存儲(chǔ)過程,這個(gè)問題導(dǎo)致的代碼檢查修改和產(chǎn)生的工作量是非常巨大的,而且后期測(cè)試也需要消耗大量的資源。希望ORACLE以后不要再發(fā)生這樣的事情,那真會(huì)傷了一直很信任你的粉絲們的心。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 衡阳县| 巴南区| 南昌县| 延川县| 聂拉木县| 额济纳旗| 华蓥市| 乌审旗| 仙游县| 诸暨市| 新闻| 怀仁县| 涿鹿县| 涟源市| 宜宾县| 泰州市| 抚顺市| 株洲县| 汾西县| 宜都市| 西青区| 营口市| 黄石市| 靖宇县| 永州市| 阳西县| 通许县| 洪湖市| 师宗县| 京山县| 旌德县| 华亭县| 张掖市| 大荔县| 南召县| 贡觉县| 荃湾区| 赤峰市| 忻州市| 尚义县| 龙里县|