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技术及存储过程和函数
在 Java 中调用 Oracle PL/SQL 中的过程或函数。返回结果集 false