eoinzy
eoinzy

Reputation: 2242

ORA-06502 numeric or vlaue error building string for clob

I've spent all day looking at existing StackOverflow questions and answers on this, but so far nothing has worked.

I think my problem is slightly different to everyone elses.

I am building a JSON string based on a SELECT from the database. This needs to be able to handle 50k+ records. I am using 11g but it will be deployed on 10g as well.

I am using a CLOB to store this return json string, because it has a capacity of 4GB. However, I keep getting the error: ORA-06502: PL/SQL: numeric or value error. Previously I was getting this error when appending a varchar onto my clob, for example returnString := returnString || "some text; so I believe it was casting the clob to a varchar and causing this. Since then, I've gotten rid of anywhere I think a cast could be occuring, by using dbms_log.append()

Here is my PL/SQL:

declare

  v_person_code ca_mips_queue.person_code%type;
  v_person_type ca_mips_queue.person_type%type;

  cursor cur_mips is
    select person_code,person_type from ca_mips_queue 
    where terminal_code = :terminal_code and (download_stage='1' or download_stage = '2');

  returnString clob;
  v_isFirst boolean := TRUE;

begin

  dbms_lob.createtemporary(returnString, true);
  dbms_lob.open(returnString, DBMS_LOB.LOB_READWRITE);
  dbms_lob.append(returnString, '{"items":[');

  for person_rec in cur_mips
  loop
      v_person_code := person_rec.person_code;
      v_person_type := person_rec.person_type;

      update ca_mips_queue
      set download_stage = '2'
      where terminal_code = :terminal_code
      and person_code = v_person_code
      and person_type = v_person_type;

      if v_isFirst then
          dbms_lob.append(returnString, '{"person_code": "');
          v_isFirst := FALSE;
      else
          dbms_lob.append(returnString,  ',{"person_code": "');
      end if;

      dbms_lob.append(returnString, v_person_code);
      dbms_lob.append(returnString, '", "person_type": "');
      dbms_lob.append(returnString, v_person_type);
      dbms_lob.append(returnString, '"}');

      dbms_output.put_line(length(returnString));

  end loop;

  commit;

  dbms_lob.append(returnString, ']}');
  :result := returnString;

  dbms_lob.close(returnString);

  :status_code := 200;

  exception 
    when others then
      :status_code := 500;
      :exception := SQLERRM;
      DBMS_OUTPUT.PUT_LINE(:exception);

end;

Notice I am printing out the size of returnString on each loop using dbms_output.put_line(length(returnString)); Here is the output (or the last few) of that:

43933
43976
44019
44062
44105
44148
44191
44234
44277
44320
44363
44406
44449
44492
44535
44578
44621
44664
44707
44750
44793
44836
44879
44922
44965
45008
ORA-06502: PL/SQL: numeric or value error

So it looks like its getting into trouble at around 45008 bytes (450kb?).

How can this be if a clob has a limit of 4GB?

Upvotes: 0

Views: 2249

Answers (1)

phonetic_man
phonetic_man

Reputation: 1088

I ran the code by doing some slight changes and it seems to be working beyond the 450kb.

declare

  v_person_code ca_mips_queue.person_code%type;
  v_person_type ca_mips_queue.person_type%type;

  cursor cur_mips is
    select person_code,person_type from ca_mips_queue;

  returnString clob;
  v_isFirst boolean := TRUE;

begin

  dbms_lob.createtemporary(returnString, true);
  dbms_lob.open(returnString, DBMS_LOB.LOB_READWRITE);
  dbms_lob.append(returnString, '{"items":[');

  for person_rec in cur_mips
  loop
      v_person_code := person_rec.person_code;
      v_person_type := person_rec.person_type;

      if v_isFirst then
          dbms_lob.append(returnString, '{"person_code": "');
          v_isFirst := FALSE;
      else
          dbms_lob.append(returnString,  ',{"person_code": "');
      end if;

      dbms_lob.append(returnString, v_person_code);
      dbms_lob.append(returnString, '", "person_type": "');
      dbms_lob.append(returnString, v_person_type);
      dbms_lob.append(returnString, '"}');

      dbms_output.put_line(length(returnString));

  end loop;

  commit;

  dbms_lob.append(returnString, ']}');
--  :result := returnString;

  dbms_lob.close(returnString);

  :status_code := 200;

end;

Here is the output for the last few rows.

146471
146545
146639
146726
146803
146880
146958
147036
147116
147194
147267
147350
147419
147489
147559
147630
147706
147778
147850
147923
147995
148068
148135
148203
148278
148360
148437
148510
148585
148666
148746
148821
148899
148985
149060
149137
149211
149305

Statement processed.

Please note that I have commented the following line.

:result := returnString;

So I would say that the problem does not reside in the loop as Alex Poole has already pointed out.

Can you please try these changes in your code.

Upvotes: 4

Related Questions