Oracle PLSQL 函数抛出 PL/SQL: numeric or value error: string buffer too small , for return large data

Posted

技术标签:

【中文标题】Oracle PLSQL 函数抛出 PL/SQL: numeric or value error: string buffer too small , for return large data【英文标题】:Oracle PLSQL function throws PL/SQL: numeric or value error: character string buffer too small ,for returning large data 【发布时间】:2011-09-28 13:49:16 【问题描述】:

我有以下 PLSQL 函数,它们在返回大数据时会返回以下错误。

ORA-06502: PL/SQL: numeric or value error: character string buffer too small 

修改后的 PLSQL 函数

 CREATE OR REPLACE FUNCTION FRDUSER.FRD_TELECOP_DYN_REP_SELECT_OPT (p_select IN VARCHAR2)
   RETURN CLOB
AS
 -- v_temp           CLOB;
  v_out            CLOB; 
  TYPE RefCurTyp   IS REF CURSOR;      
 -- len     BINARY_INTEGER;
  v_cursor         RefCurTyp; 
  c_key            VARCHAR2 (1000);
  c_value          VARCHAR2 (1000);
  separator        VARCHAR2(3);

BEGIN

    OPEN v_cursor FOR p_select;

    -- Fetch rows from result set one at a time:
    separator := '';     

    LOOP      

      FETCH v_cursor INTO c_key,c_value;        
        EXIT WHEN v_cursor%NOTFOUND;

   --      dbms_lob.createtemporary(v_out, TRUE);
  --       dbms_lob.open(v_out, dbms_lob.lob_readwrite);
         v_out := v_out ||  separator || c_key || ',' || c_value;  
  --       dbms_lob.append(v_out,  v_temp);
         separator := ':';  

    END LOOP;

    -- Close cursor:
    CLOSE v_cursor;
    RETURN (v_out);
END;
/

我正在执行如下功能,

            SELECT   CASE  
                WHEN OPTIONS_TYPE = 'S' THEN    OPTIONS_VALUES
                WHEN OPTIONS_TYPE = 'D'  THEN TO_CLOB(FRD_TELECOP_DYN_REP_SELECT_OPT (OPTIONS_VALUES))  
                END  
      FROM FRD_REP_FW_REP_TEMPLATES A, FRD_REP_FW_TEMPLATES B
        WHERE A.REP_ID=1123 AND  A.TEMP_ID=B.TEMP_ID  
        ORDER BY A.REP_TEMP_ID ASC

当我运行上面的 sql 查询时,它会抛出以下错误 ORA-00932:不一致的数据类型:预期的 CHAR 得到了 CLOB

sql函数的参数(options_values)包含sql查询。

【问题讨论】:

好的。您可以发布完整的错误堆栈,包括引发错误的行号吗?你能指出你的代码的哪一行引发了错误吗?您能否告诉我们您使用的是哪个版本的 Oracle? @Justin : 对于修改后的 PLSQL,sql 查询返回此(错误 ORA-22835:缓冲区太小,无法将 CLOB 转换为 CHAR 或 BLOB 到 RAW 转换(实际:34743,最大值:4000))跨度> 【参考方案1】:

我怀疑你的逻辑有点过于复杂了。您可能只需要这样的东西(假设您实际上需要将查询动态传递给函数)

SQL> create table clob_test (
  2    key varchar2(100),
  3    val varchar2(100)
  4  );

Table created.

SQL> insert into clob_test
  2    select level, dbms_random.string( 'A', 100 )
  3      from dual
  4   connect by level <= 10000;

10000 rows created.

SQL> ed
Wrote file afiedt.buf

  1  create or replace function return_clob
  2    return clob
  3  as
  4    v_out clob;
  5    v_sql varchar2(1000) := 'select key, val from clob_test';
  6    v_key varchar2(100);
  7    v_val varchar2(100);
  8    v_rc  sys_refcursor;
  9  begin
 10    open v_rc for v_sql;
 11    loop
 12      fetch v_rc into v_key, v_val;
 13      exit when v_rc%notfound;
 14      v_out := v_out || v_key || ', ' || v_val;
 15    end loop;
 16    return v_out;
 17* end;
SQL> /

Function created.

SQL> select return_clob from dual;

RETURN_CLOB
--------------------------------------------------------------------------------

1, tzGWFXwKLgrRTGzTGbWMYMjVniIVMmCuGYGYydcrArHPRLExoFAJsZVhhPrRKyERExqRkbLGSebqX
<< more lob data removed>>

【讨论】:

感谢您的建议。我试过你的代码,它抛出 ORA-06502: PL/SQL: numeric or value error: raw variable length too long ORA-06512: at "FRDUSER.FRD_TELECOP_DYN_REP_SELECT_OPT", line 20. 我有大约 431 行要连接。跨度> @SureshS - 您要在V_OUT 中输入多少数据?显然,我选择 1000 有点武断。如果您尝试将超过 1000 个字节放入变量中,则需要使用更长的长度。如果您尝试在变量中放入超过 4000 个字节,则需要使用 LOB。 我正在尝试在 V_OUT 中放置大约 90000 字节的数据。我需要使用 DBMS_LOB 函数来写入 v_out 吗? @SureshS - 如果您需要超过 4000 个字节,则需要使用 CLOB。您可能希望使用某些DBMS_LOB 方法将数据写入LOB。但是,如果您使用的是最新版本的 Oracle,则字符串函数和运算符都应该被重载以支持 CLOB。 justin:你能指点一些链接吗,里面有一些关于如何阅读LOB的例子。【参考方案2】:

每Oracle:

解码:

如果 expr 和 search 是字符数据,那么 Oracle 使用 未填充的比较语义。 expr、search 和 result 可以是任何 数据类型 CHAR、VARCHAR2、NCHAR 或 NVARCHAR2。返回的字符串 是 VARCHAR2 数据类型,并且与第一个字符集相同 结果参数。

所以你试图强制解码的结果是一个 clob,它不会是。

您是否尝试过case statement 而不是解码? (我不值得一试;)

【讨论】:

我尝试使用 case 语句,但它抛出 ORA-00932: compatible datatypes: expected CHAR got CLOB

以上是关于Oracle PLSQL 函数抛出 PL/SQL: numeric or value error: string buffer too small , for return large data的主要内容,如果未能解决你的问题,请参考以下文章

JAVAEE框架数据库技术之13_oracle 之PLSQL技术及存储过程和函数

plsql使用教程

在 Java 中调用 Oracle PL/SQL 中的过程或函数。返回结果集 false

PL/SQL简介与基本语法

[Oracle] - 使用32位 PLSQL(PL/SQL Developer)登陆64位Oracle失败之解决

用pl sql为oracle表创建sequence有啥用 怎么创建?