2016-05-12 6 views
0

Ich habe den ganzen Tag damit verbracht, bestehende StackOverflow Fragen und Antworten zu diesem Thema zu sehen, aber bisher hat noch nichts funktioniert.ORA-06502 numerische oder vlaue error building string für clob

Ich denke, mein Problem ist etwas anders als alle anderen.

Ich baue eine JSON-Zeichenfolge basierend auf einer SELECT aus der Datenbank. Dies muss in der Lage sein, 50k + Datensätze zu verarbeiten. Ich verwende 11g, aber es wird auch auf 10g bereitgestellt werden.

Ich verwende eine CLOB, um diese Return-JSON-Zeichenfolge zu speichern, da es eine Kapazität von 4 GB hat. Allerdings bekomme ich immer den Fehler: ORA-06502: PL/SQL: numeric or value error. Zuvor bekam ich diesen Fehler, wenn ich eine varchar an meine clob anfügte, zum Beispiel returnString := returnString || "some text;, also glaube ich, dass es den Clob zu einem Varchar umgewandelt hat und dies verursachte. Seitdem habe ich von überall losgeworden denke ich, ein gegossenes auftreten könnte, durch dbms_log.append()

Hier verwendet, ist meine 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; 

Hinweis Ich drucke die Größe returnString auf jeder aus Schleife dbms_output.put_line(length(returnString)); Hier verwendet, ist der Ausgang (oder die letzte) davon: (450kb)

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 sieht es aus wie sein auf rund 45.008 Bytes in Schwierigkeiten zu geraten.

Wie kann das sein, wenn ein clob ein Limit von 4 GB hat?

+1

Vielleicht ist das Problem 'Länge()'. Das erfordert ein Zeichenargument und keinen CLOB. Versuchen Sie 'dbms_lob.getlength()'. –

+1

Wie ist die 'bind'-Ergebnisvariable definiert? Es kann hilfreich sein, die 'when anderen' vorübergehend zu entfernen, damit Sie den vollständigen Fehler-Stack sehen können, einschließlich der Zeilennummer, die den Fehler verursacht. Oder re-raise es, oder benutze die Fehler-Formatierungs-Tools ... Ich schätze, dass die Variable zu klein ist, aber es wäre hilfreich zu sehen, ob diese Aufgabe fehlschlägt. –

+0

Nein, es ist nicht 'length()'. Das gibt es nur für das Debuggen. Wenn ich es entferne, bekomme ich den gleichen Fehler. – eoinzy

Antwort

4

Ich habe den Code ausgeführt, indem ich ein paar kleine Änderungen vornahm und es scheint, jenseits der 450kb zu arbeiten.

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; 

Hier ist die Ausgabe für die letzten paar Zeilen.

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. 

Bitte beachten Sie, dass ich die folgende Zeile kommentiert habe.

:result := returnString; 

Also würde ich sagen, dass das Problem nicht in der Schleife liegt, wie Alex Poole bereits darauf hingewiesen hat.

Können Sie bitte diese Änderungen in Ihrem Code ausprobieren.

+0

Hi, ja es klappt mit dem ': result' auskommentiert. Aus irgendeinem Grund wird es nicht konvertieren. Das Problem ist, dass ich das JSON über das Ergebnis zurückgeben muss. Gibt es eine Möglichkeit, die JSON ohne diesen Fehler ordnungsgemäß zurückzugeben? Vielen Dank. – eoinzy

+0

Können Sie das versuchen? Ändern Sie den Quellentyp Ihres Get Handlers von PLSQL in Query. Jetzt geben Sie anstelle von PLSQL einfach Ihre Abfrage in Source ein. Wählen Sie person_code, person_type aus ca_mips_queue –

+0

Ja, das funktioniert. Der Zweck dieses SQL ist es, 3 Dinge zu tun: Die 'SELECT', die' UPDATE' und 'das Ergebnis der SELECT' zurückgeben. Ich bin ein Anfänger in Sachen Datenbank, also denke ich, ich werde nur 2 Endpunkte. Eine, um das 'SELECT' zu erhalten und eine zweite, um das' UPDATE' zu tun. Es sei denn, sie können in einem gemacht werden? (was ich gesagt habe, ist das, was ich hier versucht habe) – eoinzy