Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Unerwünschte neue Zeilen beim Spoolen eines SQLPlus-Ergebnisses in eine XML-Datei

Wie @kfinity vorgeschlagen hat, hängt dies mit der Handhabung von CLOBs zusammen, aber auch damit, wie dbms_output funktioniert. Sie lesen das CLOB in Blöcken von 32 KB und schreiben jeden dieser Blöcke mit put_line() aus , das nach jedem 32k-Block ein Zeilenumbruchzeichen anfügt. Diese sind nicht an vorhandenen Zeilenumbrüchen in Ihrem XML-Dokument ausgerichtet, also erhalten Sie die ursprünglichen Umbrüche, dann zusätzliche - die etwas zufällig und mitten im Text erscheinen, sich aber tatsächlich an vorhersehbaren Stellen befinden.

Eine naheliegende Lösung ist der Wechsel von put_line() zu put() , aber das wird die maximale Puffergröße überschreiten und so etwas wie "ORU-10028:Zeilenlängenüberlauf, Begrenzung auf 32767 Bytes pro Zeile" auslösen.

Anstatt in festen 32k-Blöcken zu lesen, könnten Sie jeweils eine Zeile lesen; das CLOB versteht Zeilen nicht wirklich, aber Sie können nach Zeilenumbrüchen suchen, etwa so:

WHILE pos < v_clob_length LOOP
  -- read to next newline if there is one, rest of CLOB if not
  if dbms_lob.instr(v_clob, chr(10), pos) > 0 then
    amount := dbms_lob.instr(v_clob, chr(10), pos) - pos;
    dbms_lob.read(v_clob, amount, pos, buffer);
    pos := pos + amount + 1; -- skip newline character
  else
    amount := 32767;
    dbms_lob.read(v_clob, amount, pos, buffer);
    pos := pos + amount;
  end if;

  dbms_output.put_line(buffer);
END LOOP;

Der if sucht nach einem Zeilenumbruchzeichen nach der aktuellen Position. Wenn es eines findet, wird der Betrag als die Anzahl der Zeichen von der aktuellen Position bis zu dieser neuen Zeile berechnet (oder besser gesagt minus eins - da Sie den Zeilenumbruch selbst nicht wollen), es liest so viele Zeichen und passt dann die Position an um die gelesene Menge plus eins (um den Zeilenumbruch zu überspringen - was Sie als put_line() nicht wollen/brauchen fügt noch eins hinzu).

Wenn es keinen findet, liest es bis zu 32k - hoffentlich nur einmal; Wenn mehr als das möglicherweise Zeichen ohne Zeilenumbruch übrig sind, wird es ein zweites Mal gelesen, aber immer noch diese schurkische zusätzliche neue Zeile hinzufügen und diese Zeile umbrechen. Mit dbms_output können Sie dagegen nicht viel tun Sie müssten jedoch zu utl_file wechseln auf den Server schreiben statt auf den Client zu spoolen.