如何解决PLSQL ORA-06502

时间:2015-08-10 13:46:28

标签: oracle plsql stored-functions ora-06502

我有一个使用动态sql的小函数。我还需要动态sql,因为我在存储过程的运行时期间获得了Viewname和Where_clause。

create or replace FUNCTION Costs_MK(VIEWNAME     IN VARCHAR2,
                                    WHERE_Clause IN VARCHAR2)
RETURN VARCHAR2
IS
  v_Costs VARCHAR2(3000);
BEGIN
  EXECUTE IMMEDIATE 'Select Listagg(Costs, ' || '''' || ';' || '''' || ' )
                     WITHIN GROUP (ORDER BY Costs)
                       from (select distinct (Costs)
                       from ' || Viewname || ' where ' || where_Clause || ')'
  INTO v_Costs;

  dbms_output.put_line(length(v_Costs));

  RETURN v_Costs;
END Costs_MK;

输出:

ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: in Line 9
1600

变量v_Costs的长度是1600,我已经将长度设置为3000.但是我每次都会收到此错误,我不知道我能做什么,解决这个问题。

第9行是:

Line 8: BEGIN
Line 9:
Line 10:   EXECUTE IMMEDIATE

匿名阻止:

DECLARE
  VIEWNAME VARCHAR2(200);
  WHERE_Clause VARCHAR2(200);
  v_Return VARCHAR2(200);
BEGIN
  VIEWNAME := 'Orders';
  WHERE_BEDINGUNG := 'Orders.key like ' || '''' || '  B01  230/01/123456%' || '''';

  v_Return := Costs_MK(
    VIEWNAME => VIEWNAME,
    WHERE_Clause => WHERE_Clause
  );

  /* Legacy output:
     DBMS_OUTPUT.PUT_LINE('v_Return = ' || v_Return);
   */
  :v_Return := v_Return;

  --rollback;
END;

现在我发现了错误。因为v_Return VARCHAR2(200)只有200.如果我把它提高到4000,我会得到所需的结果。好的,我猜,我知道如何解决这个问题。

2 个答案:

答案 0 :(得分:2)

您正在看

的输出
dbms_output.put_line(length(v_Costs));

...所以你的函数到达那一点,因此不会在第9行(这是一个空行)或生成该输出之前的任何其他地方抛出异常。

因此,它必须是获得异常的调用者;调用函数的过程,或调用过程的匿名块。但不是功能本身。

基于显示的异常堆栈来自匿名块,因为程序或函数名称都不在该堆栈中(尽管它可行,但您已将程序名称删除) 。匿名块的第9行必须为变量分配一个太长的值,但它与该函数无关,除非您将返回的数字附加到字符串中,并且它是太长了。

您的匿名阻止是这样做的:

DECLARE
  ...
  v_Return VARCHAR2(200);
BEGIN
  ...
  v_Return := Costs_MK(
    VIEWNAME => VIEWNAME,
    WHERE_Clause => WHERE_Clause
  );

因此,在第9行,您尝试将已知的1600个字符值分配给您已声明为200个字符的变量;因此错误。更改v_Return的声明以匹配函数变量的大小(或使它们都为4000以允许更多开销)。

答案 1 :(得分:0)

尝试将v_Costs扩展到4000.如果仍然收到错误,则问题是LISTAGG生成的字符串超过4000(VARCHAR2的最大长度)。

如果这是问题,您需要使用XMLAGG或此问题中提供的解决方案之一:How to tweak LISTAGG to support more than 4000 character in select query?