同事遇到一个问题,执行了一个匿名PL/SQL块遇到ORA-06502错误。
简单重现一下:
Microsoft Windows XP [版本 5.1.2600] (C) 版权所有 1985-2001 Microsoft Corp.
C:\Documents and Settings\yan>sqlplus admin/admin
SQL*Plus: Release 10.2.0.1.0 - Production on 星期二 9月 27 17:19:59 2011
Copyright (c) 1982, 2005, Oracle. All rights reserved.
连接到: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production With the Partitioning, OLAP and Data Mining options
SQL> set serverout on SQL> declare 2 lv_tmplevel T_GCHKDEG.LEVNO%TYPE ; 3 begin 4 select levno into lv_tmplevel from T_GCHKDEG where rownum=1; 5 dbms_output.put_line(lv_tmplevel); 6 end; 7 / 01
PL/SQL 过程已成功完成。
SQL> declare 2 lv_tmplevel T_GCHKDEG.LEVNO%TYPE ; 3 begin 4 select min(levno) into lv_tmplevel from T_GCHKDEG; 5 dbms_output.put_line(lv_tmplevel); 6 end; 7 / declare * 第 1 行出现错误: ORA-06502: PL/SQL: 数字或值错误 : 字符串缓冲区太小 ORA-06512: 在 line 4
SQL> desc T_GCHKDEG 名称 是否为空? 类型 ----------------------------------------- -------- ----------------------------
LEVNO NOT NULL CHAR(2) LEVELTYPE CHAR(1) RISKTYPE NOT NULL CHAR(2) VALTYPE NOT NULL CHAR(1) BEGNUM NOT NULL NUMBER ENDNUM NUMBER MINVALUE NUMBER(12,2) MAXVALUE NUMBER(12,2) BEGDATE NOT NULL DATE ENDDATE NOT NULL DATE GAVENO CHAR(10) GAVEDATE DATE MOVENO CHAR(10) MOVEDATE DATE LASTUPDOPER CHAR(10) LASTUPDTRA VARCHAR2(14) LASTUPDTIME CHAR(14)
SQL> select min(levno) from T_GCHKDEG;
MI -- 01
SQL> select length(min(levno)) from T_GCHKDEG;
LENGTH(MIN(LEVNO)) ------------------ 2
LEVNO定义的是CHAR(2),MIN(LEVNO)也不可能会超出2个字符。
加了个TO_CHAR函数就能执行成功了。
SQL> declare 2 lv_tmplevel T_GCHKDEG.LEVNO%TYPE ; 3 begin 4 select to_char(min(levno)) into lv_tmplevel from T_GCHKDEG; 5 dbms_output.put_line(lv_tmplevel); 6 end; 7 / 01
PL/SQL 过程已成功完成。
查询了METALINK,发现是ORACLE的BUG。
Bug:4458790 ORA-6502 selecting MAX/MIN into a CHAR variable in PLSQL
SELECT containing a MIN or MAX into a CHAR variable inside a PL/SQL block Fails With ORA-06502 [ID 311653.1]
ORACLE给出了一下3种解决方法:
1、setting initialisation parameter BLANK_TRIMMING=TRUE
2、declare PL/SQL CHAR and VARCHAR2 variable used in the INTO clause of SELECT statement as 4,000 bytes.
3、se CAST SQL function to constraint the size to that of the variable size like
SELECT CAST(MIN('Y') AS CHAR(1)) INTO C FROM DUAL;
SQL> declare 2 lv_tmplevel char(4000) ; 3 begin 4 select min(levno) into lv_tmplevel from T_GCHKDEG; 5 dbms_output.put_line(lv_tmplevel); 6 end; 7 / 01
PL/SQL 过程已成功完成。
SQL> declare 2 lv_tmplevel T_GCHKDEG.LEVNO%TYPE ; 3 begin 4 select cast (min(levno) as char(2)) into lv_tmplevel from T_GCHKDEG; 5 dbms_output.put_line(lv_tmplevel); 6 end; 7 / 01
PL/SQL 过程已成功完成。
|