Jak navrhl @kfinity, souvisí to se zpracováním CLOB, ale také se způsobem dbms_output
funguje. Čtete CLOB v blocích po 32 kB a každý z těchto kousků zapisujete pomocí put_line()
, který za každý 32k blok připojí znak nového řádku. Ty nejsou zarovnány s žádnými existujícími zalomeními řádků v dokumentu XML, takže získáte původní zalomení a pak další - které se objevují poněkud náhodně a uprostřed textu, ale ve skutečnosti jsou na předvídatelných místech.
Zřejmým řešením je přejít z put_line()
na put()
, ale to naruší maximální velikost vyrovnávací paměti a vyvolá něco jako "ORU-10028:přetečení délky řádku, limit 32767 bajtů na řádek".
Spíše než čtení v pevných 32k blocích, můžete číst jeden řádek najednou; CLOB ve skutečnosti nerozumí řádkům jako takovým, ale můžete hledat konce řádků, něco jako:
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
hledá znak nového řádku za aktuální pozicí. Pokud najde jeden, pak se množství vypočítá jako počet znaků od aktuální pozice k tomuto novému řádku (nebo spíše mínus jeden – protože samotný nový řádek nechcete), přečte tolik znaků a poté upraví pozici o přečtenou částku plus jedna (pro přeskočení nového řádku – což nechcete/nepotřebujete jako put_line()
přidá ještě jednu).
Pokud žádný nenajde, přečte až 32k – doufejme, že pouze jednou; pokud zbývá více znaků bez zalomení řádku, provede se druhé čtení, ale stále přidá ten nepoctivý další nový řádek a zalomí tento řádek. Pomocí dbms_output
s tím moc nenaděláte ale budete muset přepnout na utl_file
zápisu na server namísto zařazování do klienta.