ORA-06502 assigning values from SQL to PL/SQL variables

简介:     最近SQL查询返回的结果给PL/SQL变量出现ORA-06502错误。这个错误的描述是ORA-06502: PL/SQL: numeric or value error: character string buffer too small.

    最近SQL查询返回的结果给PL/SQL变量出现ORA-06502错误。这个错误的描述是ORA-06502: PL/SQL: numeric or value error: character string buffer too small. 显而易见的是字符变量定义的长度不够,加到20,到100,继续06502,汗,咋回事呢?疑问

1、问题描述
  --出现问题是在一个package里,有两个参数游标,一个父游标,一个子游标,当父游标输出的结果传递值给子游标时提示值太大
  --父游标原sql语句较长,且复杂,为简化描述下面构造其环境

  -->Oracle 版本  
  goex_admin@CNMMBO> select * from v$version;
  
  BANNER
  ----------------------------------------------------------------
  Oracle Database 10g Release 10.2.0.3.0 - 64bit Production
  PL/SQL Release 10.2.0.3.0 - Production
  CORE    10.2.0.3.0      Production
  TNS for Linux: Version 10.2.0.3.0 - Production
  NLSRTL Version 10.2.0.3.0 - Production
  
  -->创建一个测试表t并插入3条记录
  goex_admin@CNMMBO> create table t(dt char(8));
  
  Table created.
  
  goex_admin@CNMMBO> insert into t select '20121218' from dual;
  
  1 row created.
  
  goex_admin@CNMMBO> insert into t select '20121219' from dual;
  
  1 row created.
  
  goex_admin@CNMMBO> insert into t select '20121220' from dual;
  
  1 row created.
  
  goex_admin@CNMMBO> commit;
  
  Commit complete.
  
  -->使用下面的查询输出结果时报ora-06502错误
  -->查询语句也比较简单,取表t的dt列的最小值,在外层查询赋值给变量
  -->外层的子查询貌似画蛇添足,纯粹是模拟原有环境
  goex_admin@CNMMBO> DECLARE
    2     tradedate_out   CHAR (100);
    3  BEGIN
    4     SELECT tradedate
    5       INTO tradedate_out
    6       FROM (SELECT MIN (dt) AS tradedate FROM t) d;
    7  
    8     DBMS_OUTPUT.Put_Line ('trade_date = ' || tradedate_out);
    9  END;
   10  /
  DECLARE
  *
  ERROR at line 1:
  ORA-06502: PL/SQL: numeric or value error: character string buffer too small
  ORA-06512: at line 4

2、改写查询
  -->如果我们去掉外层查询没有类似的错误发生
  -->如此这般,难道是值由子查询到外层的时候产生了变异?
  goex_admin@CNMMBO> DECLARE
    2     tradedate_out   CHAR (100);
    3  BEGIN
    4     SELECT MIN (dt) INTO tradedate_out FROM t;
    5  
    6     DBMS_OUTPUT.Put_Line ('trade_date = ' || tradedate_out);
    7  END;
    8  /
  trade_date = 20121218
  
  PL/SQL procedure successfully completed.

3、尝试不同版本执行该查询
  -->下面在Oracle 11g做类似模拟
  SQL> select * from v$version;
  
  BANNER
  --------------------------------------------------------------------------------
  Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
  PL/SQL Release 11.2.0.1.0 - Production
  CORE    11.2.0.1.0      Production
  TNS for Linux: Version 11.2.0.1.0 - Production
  NLSRTL Version 11.2.0.1.0 - Production
  
  -->Author : Robinson
  -->Blog   : http://blog.csdn.net/robinson_0612
  
  SQL> create table t(dt char(8));
  
  Table created.
  
  SQL> insert into t select '20121218' from dual;
  
  1 row created.
  
  SQL> insert into t select '20121219' from dual;
  
  1 row created.
  
  SQL> insert into t select '20121220' from dual;
  
  1 row created.
  
  SQL> commit;
  
  Commit complete.
  
  -->同样是原来的语句,而在Oracle 11g中没有这个问题
  SQL> set serveroutput on;
  SQL> DECLARE
    2     tradedate_out   CHAR (100);
    3  BEGIN
    4     SELECT tradedate
    5       INTO tradedate_out
    6       FROM (SELECT MIN (dt) AS tradedate FROM t) d;
    7  
    8     DBMS_OUTPUT.Put_Line ('trade_date = ' || tradedate_out);
    9  END;
   10  /
  trade_date = 20121218
  
  PL/SQL procedure successfully completed.

4、解决
  -->为保持原有查询语句不做大量修改,通过为外层查询添加TRIM函数后问题解决
  goex_admin@CNMMBO> DECLARE
    2     tradedate_out   CHAR (100);
    3  BEGIN
    4     SELECT TRIM (tradedate)
    5       INTO tradedate_out
    6       FROM (SELECT MIN (dt) AS tradedate FROM t) d;
    7  
    8     DBMS_OUTPUT.Put_Line ('trade_date = ' || tradedate_out);
    9  END;
   10  /
  trade_date = 20121218
  
  PL/SQL procedure successfully completed.

5、Oracle BUG
  -->Metalink 上溜达了一下,还真有点收获,又是一个BUG,汗....
  Bug:5564384 ORA-06502 assigning values from SQL to PL/SQL variables
     Component: RDBMS
     Fixed Ver(s): 10204 111
      Symptom(s):
       - When executing a SQL that contains a concatenation / MAX of CHAR values and assigning the result to a
         PL/SQL output variable an ORA-6502 may be raised.
         For example:
          CREATE TABLE TESTE (T1 CHAR(1), T2 CHAR(1), T3 CHAR(1));
          INSERT INTO TESTE VALUES ('S', 'S', 'S');
          DECLARE
           V_DUMMY    VARCHAR2(3);
          BEGIN
           SELECT MAX(X) INTO V_DUMMY FROM (SELECT T1||T2||T3 X FROM TESTE);
          END;
          /
          ^
          ORA-06502: PL/SQL: numeric or value error: character string buffer too small
      Available Workaround(s): 
           Declare the PLSQL output variables as varchar2(4000);
      References:
        Note:5564384.8 Bug 5564384 - ORA-6502 assigning values from SQL to PLSQL variables

更多参考

DML Error Logging 特性 

PL/SQL --> 游标

PL/SQL --> 隐式游标(SQL%FOUND)

批量SQL之 FORALL 语句

批量SQL之 BULK COLLECT 子句

PL/SQL 集合的初始化与赋值

PL/SQL 联合数组与嵌套表
PL/SQL 变长数组
PL/SQL --> PL/SQL记录

SQL tuning 步骤

高效SQL语句必杀技

父游标、子游标及共享游标

绑定变量及其优缺点

dbms_xplan之display_cursor函数的使用

dbms_xplan之display函数的使用

执行计划中各字段各模块描述

使用 EXPLAIN PLAN 获取SQL语句执行计划

目录
相关文章
|
13天前
|
SQL 人工智能 算法
【SQL server】玩转SQL server数据库:第二章 关系数据库
【SQL server】玩转SQL server数据库:第二章 关系数据库
52 10
|
1月前
|
SQL 数据库 数据安全/隐私保护
Sql Server数据库Sa密码如何修改
Sql Server数据库Sa密码如何修改
|
2月前
|
SQL 算法 数据库
【数据库SQL server】关系数据库标准语言SQL之数据查询
【数据库SQL server】关系数据库标准语言SQL之数据查询
96 0
|
23天前
|
SQL
启动mysq异常The server quit without updating PID file [FAILED]sql/data/***.pi根本解决方案
启动mysq异常The server quit without updating PID file [FAILED]sql/data/***.pi根本解决方案
17 0
|
13天前
|
SQL 算法 数据库
【SQL server】玩转SQL server数据库:第三章 关系数据库标准语言SQL(二)数据查询
【SQL server】玩转SQL server数据库:第三章 关系数据库标准语言SQL(二)数据查询
78 6
|
1天前
|
SQL 关系型数据库 MySQL
:“You have an error in your SQL syntax; check the manual that corresponds to your MySQL server versi
:“You have an error in your SQL syntax; check the manual that corresponds to your MySQL server versi
6 0
|
8天前
|
SQL 安全 网络安全
IDEA DataGrip连接sqlserver 提示驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接的解决方法
IDEA DataGrip连接sqlserver 提示驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接的解决方法
19 0
|
13天前
|
SQL 存储 数据挖掘
数据库数据恢复—RAID5上层Sql Server数据库数据恢复案例
服务器数据恢复环境: 一台安装windows server操作系统的服务器。一组由8块硬盘组建的RAID5,划分LUN供这台服务器使用。 在windows服务器内装有SqlServer数据库。存储空间LUN划分了两个逻辑分区。 服务器故障&初检: 由于未知原因,Sql Server数据库文件丢失,丢失数据涉及到3个库,表的数量有3000左右。数据库文件丢失原因还没有查清楚,也不能确定数据存储位置。 数据库文件丢失后服务器仍处于开机状态,所幸没有大量数据写入。 将raid5中所有磁盘编号后取出,经过硬件工程师检测,没有发现明显的硬件故障。以只读方式将所有磁盘进行扇区级的全盘镜像,镜像完成后将所
数据库数据恢复—RAID5上层Sql Server数据库数据恢复案例
|
17天前
|
SQL 数据安全/隐私保护
SQL Server 2016安装教程
SQL Server 2016安装教程
19 1