0

我有一个使用动态 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,我会得到想要的结果。好的,所以我想,我知道如何解决这个问题。

4

2 回答 2

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 以允许更多开销)。

于 2015-08-10T14:21:46.780 回答
0

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

如果这是问题所在,您将需要使用 XMLAGG 或此问题中提供的解决方案之一:如何调整 LISTAGG 以在选择查询中支持超过 4000 个字符?

于 2015-08-10T13:52:37.203 回答