Som @kfinity föreslog är detta relaterat till CLOB-hantering, men också till hur dbms_output
Arbetar. Du läser CLOB i bitar av 32k och skriver ut var och en av dessa bitar med put_line()
, som lägger till ett nyradstecken efter varje 32k bit. De är inte anpassade till några befintliga radbrytningar i ditt XML-dokument, så du får de ursprungliga brytningarna, sedan extra - som visas något slumpmässigt och mitt i texten, men som faktiskt finns på förutsägbara platser.
En uppenbar lösning är att byta från put_line()
till put()
, men det kommer att bryta den maximala buffertstorleken och kasta något i stil med "ORU-10028:radlängdsspill, gräns på 32767 byte per rad".
Istället för att läsa i fasta 32k-bitar, kan du läsa en rad i taget; CLOB förstår inte riktigt linjer som sådana, men du kan leta efter radbrytningar, något i stil med:
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;
if
letar efter ett nyradstecken efter den aktuella positionen. Om den hittar en så beräknas beloppet som antalet tecken från den aktuella positionen till den nya raden (eller snarare minus en - eftersom du inte vill ha själva nyraden), den läser så många tecken och justerar sedan positionen med beloppet läst plus ett (för att hoppa över nyraden - som du inte vill ha/behöver som put_line()
lägger till en fortfarande).
Om den inte hittar en så läser den upp till 32k - förhoppningsvis bara en gång; om det finns fler än så kan tecken kvar utan radbrytning så kommer den att göra en andra läsning men ändå lägga till den där skurkaktiga extra raden och bryta den raden. Du kan inte göra så mycket åt det med dbms_output
men du skulle behöva byta till utl_file
skriva till servern istället för att spoola till klienten.