DBMS_LOB.SUBSTR()抛出“字符串缓冲区太小”错误

时间:2012-12-11 11:36:24

标签: oracle oracle10g

oracle是否有根据CLOB字段的字节数获取子字符串的方法?

select DBMS_LOB.SUBSTR(a.COMMENTS, 3998, 1)
FROM FOO;

我收到错误:

  

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

。 问题在于特殊字符。每个新的特殊字符占用8个字节,因此当我将字符串限制减少到3992时,它就可以工作。

DBMS_LOB.SUBSTR(a.COMMENTS, 3992, 1) works.

出于测试目的,我放了许多特殊字符,并再次抛出同样的错误。

oracle有没有找到基于字节数而不是字符数的子字符串的方法?

实际上,我们从表中获取数据,需要在UI上显示,限制为4000个字符。所以,我们只想获取前4000个字符。因为,字符大小是1字节,我们可以容纳4000字节。因此,如果我们使用DBMS_LOB.CONVERTTOBLOB,我们可能无法正确显示所提取的字符串。我们能否以某种方式将它转换回charater string?

4 个答案:

答案 0 :(得分:2)

我成功使用了旧的SUBSTR函数,它也适用于clob类型。在这种情况下,它的SUBSTR(a.COMMENTS,1,3992)

答案 1 :(得分:0)

试试这个方法::

使用Oracle函数 LENGTHB()来获得此结果。有一种方法可以使用 DBMS_LOB.CONVERTTOBLOB CLOB 转换为 BLOB 并使用 DBMS_LOB.GET_LENGTH()。这将返回no字节。

您可以使用此主题获得完整答案:: 的 https://forums.oracle.com/forums/thread.jspa?threadID=2133623

答案 2 :(得分:0)

首先,尝试替换字符串中的所有特殊字符,然后尝试对其进行子字符串转换为字符。

示例:-DBMS_LOB.SUBSTR(REGEXP_REPLACE(your_column,'[^ 0-9A-Za-z]',''),3999,1)

答案 3 :(得分:0)

这是一个老问题,但是我没有找到任何解决方案,所以我将发布我的方法来找到该问题的解决方案,以防万一有人需要处理此问题...

我的任务是从CLOB中检索“最多”字符。

DBMS_LOB.SUBSTR或SUBSTR都将获得正确的结果...

在使用DBMS_LOB.SUBSTR的情况下,我不断将ORA-12801与ORA-06502一起使用 使用SUBSTR的另一个ORA-64203 ..

建议说SUBSTR最多为1000,因为字符的最大字节数为4,因此您得到的字节数不会超过4000,不幸的是,这对我来说不够好,因为这样您可能只会收到2000字节,以防某些行不包含多字节字符...

我的解决方案不应该用于重复查询(而是用于将数据提取和加载/存储到VARCHAR2列中),

create or replace FUNCTION SUBSTR_MULTIBYTE_CLOB
(
  P_DATA IN CLOB 
, P_START_INDEX IN NUMBER 
) RETURN VARCHAR2 AS 
P_OUT VARCHAR2(4000 BYTE);
P_LENGTH NUMBER := 4000;
BEGIN
    FOR loop_counter IN 1..400 LOOP    
        BEGIN
            P_OUT := DBMS_LOB.SUBSTR(P_DATA,P_LENGTH-((loop_counter-1)*10),P_START_INDEX);
            RETURN P_OUT;
         EXCEPTION
            WHEN OTHERS THEN
               IF SQLCODE = -12801 OR SQLCODE = -6502 OR SQLCODE = -1401 OR SQLCODE = -1489 THEN
                  NULL; -- suppresses ORA-12801 "error signal from parallel server" or ORA-06502 exception "character string buffer too small" and some others I've got...
               ELSE
                  RAISE;
               END IF;
         END;         
    END LOOP;
END SUBSTR_MULTIBYTE_CLOB;

如果需要,您可以将循环更改为4000,并将其减少1个字节,我决定将其减少10个字节,只是为了使其速度更快一点...