Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Niechciane nowe wiersze podczas buforowania wyniku sqlplus do pliku xml

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.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Błąd wyzwalacza Oracle PL/SQL

  2. Połącz ponownie infrastrukturę sieciową

  3. Zagnieżdżony kursor w kursorze

  4. Jak utworzyć obiekt oracle.sql.ARRAY?

  5. Jak działa funkcja HEXTORAW()? Jaki jest algorytm?