oracle10201 plsql 中max的Ora-06502異常

regonly1發表於2010-01-06

先看例子:
SQL> select * from v$version;
 
BANNER
----------------------------------------------------------------
Personal Oracle Database 10g Release 10.2.0.1.0 - Production
PL/SQL Release 10.2.0.1.0 - Production
CORE 10.2.0.1.0 Production
TNS for 32-bit Windows: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production
 
SQL>
SQL> declare
  2      v_x varchar2(10);
  3  begin
  4      select max('1')
  5        into v_x
  6        from dual;
  7  end;
  8  /
 
declare
    v_x varchar2(10);
begin
    select max('1')
      into v_x
      from dual;
end;
 
ORA-06502: PL/SQL: 數字或值錯誤 :  字串緩衝區太小
ORA-06512: 在 line 5
 可以看到,使用max時,出現了該異常。
開始看到這個現象的時候,以為是變數定義範圍太小的緣故。但是從同事那邊來看,如果是這麼簡單,應該他早就發現了。所以我想應該不能從這個方向去解決問題。所以我嘗試使用直接字串1來替換max中的內容,這樣v_x這個變數的範圍肯定可以容下這個字串了。結果即在意料之外,又在意料之中。意料之外是1這樣的字串也丟擲了異常。如果是a這樣的字元,還有點道理。但是1卻沒有料到。意料之中是這個問題的確不像我之前所說的那麼簡單。
於是我考慮是不是max在plsql中取值的時候都是按照數字來轉換的,而不會做預設的轉換,只要遇到字串就丟擲該異常。因此我嘗試用to_char轉換:
SQL> declare
  2      v_x varchar2(10);
  3  begin
  4      select max(to_char('1'))
  5        into v_x
  6        from dual;
  7  end;
  8  /
 
PL/SQL procedure successfully completed
發現是可以的。但是進一步的檢查發現:
SQL> declare
  2      v_x varchar2(10);
  3  begin
  4      select to_char(max('1'))
  5        into v_x
  6        from dual;
  7  end;
  8  /
 
PL/SQL procedure successfully completed
to_char放在外面也是可以的。這個就搞不懂了。經過google,發現這原來是oracle10g的一個bug,當max中的資料型別是char時就會丟擲這個異常,但是如果是varchar2就不會有該異常,在9i上測試沒有該問題。
轉成varchar2後的測試:
SQL> declare
  2      v_x varchar2(10);
  3  begin
  4      select max(cast('1' as varchar2(10)))
  5        into v_x
  6        from dual;
  7  end;
  8  /
 
PL/SQL procedure successfully completed
實際上to_char也是將對應的字串轉成varchar2。
該問題對應的bug#4458790

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12932950/viewspace-624492/,如需轉載,請註明出處,否則將追究法律責任。

相關文章