ORA-06502:PL / SQL:数字或值错误:处理多字节字符时字符串缓冲区太小错误

时间:2017-07-27 11:38:03

标签: plsql

当我尝试处理包含德语字符(Multibhyte字符)的输入字符串时,程序因ORA-06502错误而失败。

该过程解析输入字符串,该字符串是CSV中的一行,csv的每个列值都添加到列表中并返回。

输入字符串:

  

SIPCORE1000; SKYGUIDE,SociétéAnonymeSuisse pour les Services; Any2Any; Yes; SSM; No; None; 6730:14892466 ;; 109

程序:

 PROCEDURE ParseCSV(
        i_csvline IN VARCHAR2,
        i_Delimiter   IN            VARCHAR2 DEFAULT ';',
        i_Enclosed IN VARCHAR2 DEFAULT '"',
        o_ColumnValueList OUT dimension.NAMELIST )
    IS 
      --
      CARRIAGE_RETURN CONSTANT CHAR(1) := chr(13);
      LINE_FEED       CONSTANT CHAR(1) := chr(10);
      --
      l_char           CHAR(1);
      l_lookahead      CHAR(1);
      l_pos            NUMBER          := 0;
      l_columnValue          VARCHAR2(32767) := NULL;
      l_columnValue_complete BOOLEAN         := false;
      l_line_complete  BOOLEAN         := false;
      l_new_column      BOOLEAN         := true;
      l_enclosed       BOOLEAN         := false;
      v_namelist dimension.NAMELIST :=dimension.NAMELIST();
      v_lastchar        VARCHAR2(10);
    BEGIN 
      SELECT SUBSTR(i_csvline,-1) INTO v_lastchar FROM dual;
      LOOP
        -- increment postion index
        l_pos := l_pos + 1;
        -- get the next character from input CSV line
        l_char := dbms_lob.substr( i_csvline, 1, l_pos);

        -- Exit when no more characters to process
        EXIT WHEN l_char IS NULL OR l_pos > dbms_lob.getLength( i_csvline );

        -- If the first character of new token is optionally enclosed character 
        -- note that and skip it and get the next character
        IF l_new_column AND l_char = i_Enclosed THEN
          l_enclosed             := true;
          l_pos                  := l_pos + 1;
          l_char                 := dbms_lob.substr( i_csvline, 1, l_pos);
        END IF;
        l_new_column := false;

        -- get the lookahead character
        l_lookahead := dbms_lob.substr( i_csvline, 1, l_pos+1 );

        -- Inspect the character (and lookahead) to determine what to do
        IF l_char             = i_Enclosed AND l_enclosed THEN
          IF l_lookahead      = i_Enclosed THEN
            l_pos            := l_pos + 1;
            l_columnValue          := l_columnValue || l_lookahead;
          elsif l_lookahead   = i_Delimiter THEN
            l_pos            := l_pos + 1;
            l_columnValue_complete := true;
          ELSE
            l_enclosed := false;
          END IF;
        elsif l_char IN ( CARRIAGE_RETURN, LINE_FEED ) AND NOT l_enclosed THEN
          l_columnValue_complete := true;
          l_line_complete  := true;
          IF l_lookahead  IN ( CARRIAGE_RETURN, LINE_FEED ) THEN
            l_pos := l_pos + 1;
          END IF;
        elsif l_char        = i_Delimiter AND NOT l_enclosed THEN
          l_columnValue_complete := true;
        elsif l_pos         = dbms_lob.getLength( i_csvline ) THEN
          l_columnValue          := l_columnValue || l_char;
          l_columnValue_complete := true;
          l_line_complete  := true;
        ELSE
          l_columnValue := l_columnValue || l_char;
        END IF;
        -- process a new token
        IF l_columnValue_complete THEN
          v_namelist.EXTEND;
          v_namelist(v_namelist.LAST):=l_columnValue;
          l_columnValue                    := NULL;
          l_enclosed                 := false;
          l_new_column                := true;
          l_columnValue_complete           := false;
        END IF;
        IF l_line_complete THEN
          l_line_complete := false;
        END IF;
      END LOOP;
      IF v_lastchar=i_Delimiter
      THEN
          v_namelist.EXTEND;
          v_namelist(v_namelist.LAST):=NULL;
      END IF; 
      o_ColumnValueList:=v_namelist;
    END ParseCSV;

1 个答案:

答案 0 :(得分:0)

当涉及多字节编码字符时(在我的情况下为德语字符),保存这些字符的变量应为VARCHAR2且大小至少为2.我已将变量类型定义为VARCHAR2,大小为10.现在程序按预期工作。