Jak zasugerował @kfinity, jest to związane z obsługą CLOB, ale także z tym, jak dbms_output
Pracuje. Czytasz CLOB w kawałkach po 32k i zapisujesz każdy z tych kawałków za pomocą put_line()
, który dodaje znak nowej linii po każdym 32-kilometrowym fragmencie. Nie są one wyrównane z istniejącymi podziałami wierszy w dokumencie XML, więc otrzymujesz oryginalne podziały, a następnie dodatkowe — które wydają się nieco losowe i znajdują się w środku tekstu, ale w rzeczywistości znajdują się w przewidywalnych miejscach.
Oczywistym rozwiązaniem jest przejście z put_line()
do put()
, ale to złamie maksymalny rozmiar bufora i wyrzuci coś w stylu "ORU-10028:przepełnienie długości linii, limit 32767 bajtów na linię".
Zamiast czytać w stałych porcjach 32k, możesz czytać jedną linię na raz; CLOB tak naprawdę nie rozumie wierszy jako takich, ale możesz szukać łamania wierszy, na przykład:
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
szuka znaku nowej linii po aktualnej pozycji. Jeśli go znajdzie, to kwota jest obliczana jako liczba znaków od bieżącej pozycji do nowej linii (lub raczej minus jeden - ponieważ nie chcesz samej nowej linii), odczytuje tyle znaków, a następnie dostosowuje pozycję o odczytaną ilość plus jeden (aby pominąć nową linię - czego nie chcesz/nie potrzebujesz jako put_line()
dodaje jeszcze jeden).
Jeśli go nie znajdzie, odczytuje do 32 tys. - miejmy nadzieję, że tylko raz; jeśli jest więcej znaków, które mogą pozostać bez łamania linii, to wykona drugi odczyt, ale nadal doda tę nieuczciwą dodatkową nową linię i złamie tę linię. Niewiele można z tym zrobić za pomocą dbms_output
jednak musisz przełączyć się na utl_file
zapisywanie na serwerze zamiast buforowania do klienta.