ORA-06502: 字符串缓冲区太小。即使字符串大小低于声明的大小限制

Posted

技术标签:

【中文标题】ORA-06502: 字符串缓冲区太小。即使字符串大小低于声明的大小限制【英文标题】:ORA-06502: character string buffer too small. Even though the string size is under declared size limit 【发布时间】:2016-01-11 11:22:05 【问题描述】:
 FOR this_loop
     IN (SELECT field_A, field_B
           FROM TABLE_NAME
          WHERE    num = i_num)
  LOOP
     IF this_loop.field_B BETWEEN 1 AND 3
     THEN
        v_A :=  v_A || ' ' || this_loop.field_A;
     ELSIF this_loop.field_B BETWEEN 4 AND 8
     THEN
        v_field_A := v_field_A || ' ' || this_loop.field_A;  -- Error is at this line
     ELSIF this_loop.field_B BETWEEN 9 AND 15
     THEN
        v_B :=  v_B || ' ' || this_loop.field_A;
     END IF;
  END LOOP;

变量声明为

v_field_A            VARCHAR2 (100);

我知道的-

    变量 v_field_A 的值不能超过 100 个字符 我从SELECT 查询得到的输出不超过 10 个字符。

我的问题 - 当字符在 varchar2 的限制范围内时,怎么可能面对这个空间缓冲区问题? 几年前我遇到过这个问题,但上次原因是select 查询的输出。它有超过 100 个字符,因此存在大小问题,但这次不超过 10 个字符。我很困惑。任何帮助表示赞赏

【问题讨论】:

你的表有多少行? 有超过一百万行,但这只发生在少数行中。 更具体地说,循环获取多少行? 10 char * 11 循环迭代 == 你会遇到错误,因为你在每次迭代时都将值连接到变量 为什么不能增加 v_field_A 的大小?这将解决问题 @Sathya 这取决于。通常不超过 3-4 行。 【参考方案1】:

变量 v_field_A 的值不能超过 100 个字符

为什么不呢?这是很有可能的,因为您在 CURSOR FOR LOOP 中为每一行连接变量。

例如,

SQL> DECLARE
  2    v_name VARCHAR2(50);
  3  BEGIN
  4    FOR i IN
  5    (SELECT ename FROM emp
  6    )
  7    LOOP
  8      v_name := v_name || i.ename;
  9    END LOOP;
 10  END;
 11  /
DECLARE
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at line 8

使用 DBMS_OUTPUT 查看变量的当前大小和附加的新值。

让我们调试

SQL> DECLARE
  2    v_name VARCHAR2(50);
  3  BEGIN
  4    FOR i IN
  5    (SELECT ename FROM emp
  6    )
  7    LOOP
  8      dbms_output.put_line('Length of new value = '||LENGTH(i.ename));
  9      v_name := v_name || i.ename;
 10      dbms_output.put_line('Length of variable = '||LENGTH(v_name));
 11    END LOOP;
 12  END;
 13  /
Length of new value = 5
Length of variable = 5
Length of new value = 5
Length of variable = 10
Length of new value = 4
Length of variable = 14
Length of new value = 5
Length of variable = 19
Length of new value = 6
Length of variable = 25
Length of new value = 5
Length of variable = 30
Length of new value = 5
Length of variable = 35
Length of new value = 5
Length of variable = 40
Length of new value = 4
Length of variable = 44
Length of new value = 6
Length of variable = 50
Length of new value = 5

错误

DECLARE
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at line 9

很明显,我们想要将一个长度为5 的字符串连接到声明为最大大小50 的变量,该变量当前保存一个大小为50 的值。因此,它会抛出错误ORA-06502: PL/SQL: numeric or value error: character string buffer too small

【讨论】:

如果我错了,请纠正我。如果变量可以容纳超过 50 或 100 个字符。根本不应该有大小的问题吧? @PirateX 您忘记了将值连接到循环中的变量这一事实,因此,在某些时候,在遍历 roes 时,它超过了声明的大小。我在回答中添加了一个示例。 好的,我想我明白了。它是串联,在某些时候超过了 100 的限制,从而引发错误。对吧? @PirateX 没错。这就是您在我向您展示的示例中的 DBMS_OUTPUT 中看到的内容。 @PirateX 请将其标记为已回答,也会对其他人有所帮助!我看到您的任何问题都没有被标记为已回答。这是一个很好的姿态,社区建议接受解决您问题的答案。祝你好运!【参考方案2】:

11 行 * 10 个字符 > 100 个字符 => 错误 - 您将多行 10 个字符连接在一起成为三个变量之一。每次循环中,其中一个都会增长。

我错过了什么?

还要注意字符与字节。在 varchar2 中,每个 CHARACTER 可能占用 2 个字节。

【讨论】:

【参考方案3】:

检查此条件执行了多少次以及连接了哪些值。由于这被连接了多次,因此 v_field_A 的大小可能超过 50 个字符

ELSIF this_loop.field_B BETWEEN 4 AND 8
 THEN
    v_field_A := v_field_A || ' ' || this_loop.field_A; 

要解决此问题,您可以增加此变量的大小。最多可以声明 32,767 个字节的 varchar

【讨论】:

【参考方案4】:

您可以在 SQL 查询中进行字符串连接:

SELECT field_A,
       LISTAGG(CASE WHEN field_B BETWEEN 1 AND 3 THEN field_A END, ' ') WITHIN GROUP (ORDER BY field_A) as val1,
       LISTAGG(CASE WHEN field_B BETWEEN 4 AND 8 THEN field_A END, ' ') WITHIN GROUP (ORDER BY field_A) as val2,
       LISTAGG(CASE WHEN field_B BETWEEN 9 AND 15 THEN field_A END, ' ') WITHIN GROUP (ORDER BY field_A) as val3
FROM TABLE_NAME
WHERE num = i_num;

这是为了简化您的代码。您仍然受到 Oracle 字符串长度的限制。您可以使用 CLOB 绕过 PL/SQL 中的 Oracle 限制,但当最终字符串只有几百个字符时,这是不必要的。

【讨论】:

即使LISTAGG 也有4000SQL 限制【参考方案5】:

你的问题的答案在于循环多少次 执行以及进入 IF 条件的次数。

示例:

条件4 AND 8

this_loop.field_A:= 'test';

循环执行次数 = 100

由于 CONCATINATION,大​​小肯定会超过 100 个字符。

与其他 LOOP 条件类似。

解决方案:尝试使用 CLOB 而不是 VARCHAR 来消除此问题。

Oracle 错误非常具有描述性。如果它抛出一些错误,它几乎可以解释这个场景:P。

【讨论】:

以上是关于ORA-06502: 字符串缓冲区太小。即使字符串大小低于声明的大小限制的主要内容,如果未能解决你的问题,请参考以下文章

ORA-06502 来自 PHP OCI 调用但不是 SQL Developer 的字符串缓冲区太小

oracle 11g ORA-06502:PL/SQL:数字或值错误:字符串缓冲区太小

ORA-06502:PLSQL:数值或值错误:字符串缓冲区太小

Oracle.DataAccess.Client.OracleException ORA-06502:PL/SQL:数字或值错误:字符串缓冲区太小。 ExecuteReader 步骤出错

ORA-06502: PL/SQL: 数字或值错误 : 字符串缓冲区太小解决办法

PL/SQL - 防止 ORA-06502