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语句执行计划

目录
相关文章
|
SQL 存储 Oracle
Oracle的PL/SQL定义变量和常量:数据的稳定与灵动
【4月更文挑战第19天】在Oracle PL/SQL中,变量和常量扮演着数据存储的关键角色。变量是可变的“魔术盒”,用于存储程序运行时的动态数据,通过`DECLARE`定义,可在循环和条件判断中体现其灵活性。常量则是不可变的“固定牌”,一旦设定值便保持不变,用`CONSTANT`声明,提供程序稳定性和易维护性。通过 `%TYPE`、`NOT NULL`等特性,可以更高效地管理和控制变量与常量,提升代码质量。善用两者,能优化PL/SQL程序的结构和性能。
|
SQL Oracle 关系型数据库
Oracle的PL/SQL隐式游标:数据的“自动导游”与“轻松之旅”
【4月更文挑战第19天】Oracle PL/SQL中的隐式游标是自动管理的数据导航工具,简化编程工作,尤其适用于简单查询和DML操作。它自动处理数据访问,提供高效、简洁的代码,但不适用于复杂场景。显式游标在需要精细控制时更有优势。了解并适时使用隐式游标,能提升数据处理效率,让开发更加轻松。
|
SQL Oracle 关系型数据库
【Oracle】玩转Oracle数据库(五):PL/SQL编程
【Oracle】玩转Oracle数据库(五):PL/SQL编程
367 8
|
SQL 开发框架 .NET
【YashanDB知识库】使用c-调用yashandb odbc驱动执行SQL时报YAS-08008 not all variables bounded
本文来自YashanDB官网,讨论了某客户在使用C# ASP.NET应用时遇到的异常问题。问题表现为YashanDB ODBC驱动不支持.NET框架通过绑定变量执行SQL语句,导致应用无法正常运行。该问题影响所有YashanDB版本及其ODBC驱动版本。解决方法包括避免使用绑定变量或升级ODBC驱动版本。文章通过示例代码展示了问题复现过程,并总结了最小化问题场景以定位和解决问题的经验。
|
SQL 开发框架 .NET
【YashanDB 知识库】使用 c- 调用 yashandb odbc 驱动执行 SQL 时报 YAS-08008 not all variables bounded
某客户C# ASP.NET应用在使用yashandb ODBC驱动时,因驱动不支持绑定变量执行SQL语句而报错“YAS-08008 not all variables bounded”,导致应用无法正常运行。影响所有yashandb及ODBC驱动版本。解决方法为避免使用绑定变量或升级驱动版本。通过简化场景成功复现问题。
|
SQL 数据采集 监控
局域网监控电脑屏幕软件:PL/SQL 实现的数据库关联监控
在当今网络环境中,基于PL/SQL的局域网监控系统对于企业和机构的信息安全至关重要。该系统包括屏幕数据采集、数据处理与分析、数据库关联与存储三个核心模块,能够提供全面而准确的监控信息,帮助管理者有效监督局域网内的电脑使用情况。
249 2
|
SQL Oracle 关系型数据库
SQL与PL/SQL:数据库编程语言的比较
【8月更文挑战第31天】
606 1
|
SQL Oracle 关系型数据库
Oracle的PL/SQL游标属性:数据的“导航仪”与“仪表盘”
【4月更文挑战第19天】Oracle PL/SQL游标属性如同车辆的导航仪和仪表盘,提供丰富信息和控制。 `%FOUND`和`%NOTFOUND`指示数据读取状态,`%ROWCOUNT`记录处理行数,`%ISOPEN`显示游标状态。还有`%BULK_ROWCOUNT`和`%BULK_EXCEPTIONS`增强处理灵活性。通过实例展示了如何在数据处理中利用这些属性监控和控制流程,提高效率和准确性。掌握游标属性是提升数据处理能力的关键。
289 9
|
SQL Oracle 安全
Oracle的PL/SQL循环语句:数据的“旋转木马”与“无限之旅”
【4月更文挑战第19天】Oracle PL/SQL中的循环语句(LOOP、EXIT WHEN、FOR、WHILE)是处理数据的关键工具,用于批量操作、报表生成和复杂业务逻辑。LOOP提供无限循环,可通过EXIT WHEN设定退出条件;FOR循环适用于固定次数迭代,WHILE循环基于条件判断执行。有效使用循环能提高效率,但需注意避免无限循环和优化大数据处理性能。掌握循环语句,将使数据处理更加高效和便捷。
|
SQL Oracle 关系型数据库
Oracle的PL/SQL表达式:数据的魔法公式
【4月更文挑战第19天】探索Oracle PL/SQL表达式,体验数据的魔法公式。表达式结合常量、变量、运算符和函数,用于数据运算与转换。算术运算符处理数值计算,比较运算符执行数据比较,内置函数如TO_CHAR、ROUND和SUBSTR提供多样化操作。条件表达式如CASE和NULLIF实现灵活逻辑判断。广泛应用于SQL查询和PL/SQL程序,助你驾驭数据,揭示其背后的规律与秘密,成为数据魔法师。