Như @kfinity đã đề xuất, điều này liên quan đến xử lý CLOB, nhưng cũng liên quan đến cách dbms_output
làm. Bạn đang đọc CLOB theo từng đoạn 32k và viết từng đoạn đó bằng put_line()
, thêm một ký tự dòng mới sau mỗi đoạn 32k. Những dấu ngắt đó không được căn chỉnh với bất kỳ dấu ngắt dòng hiện có nào trong tài liệu XML của bạn, vì vậy bạn sẽ nhận được các dấu ngắt ban đầu, sau đó là các dấu ngắt phụ - có vẻ hơi ngẫu nhiên và ở giữa văn bản, nhưng thực sự ở những vị trí có thể dự đoán được.
Một giải pháp rõ ràng là chuyển từ put_line()
thành put()
, nhưng điều đó sẽ phá vỡ kích thước bộ đệm tối đa và ném ra một thứ như "ORU-10028:tràn độ dài dòng, giới hạn 32767 byte mỗi dòng".
Thay vì đọc theo từng đoạn 32k cố định, bạn có thể đọc từng dòng một; CLOB không thực sự hiểu các dòng như vậy, nhưng bạn có thể tìm các dấu ngắt dòng, đại loại như:
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
tìm kiếm một ký tự dòng mới, sau vị trí hiện tại. Nếu nó tìm thấy một thì số tiền được tính bằng số ký tự từ vị trí hiện tại đến dòng mới đó (hoặc đúng hơn là trừ đi một - vì bạn không muốn dòng mới), nó đọc nhiều ký tự đó và sau đó điều chỉnh vị trí bằng số tiền đã đọc cộng với một (để bỏ qua dòng mới - mà bạn không muốn / cần là put_line()
thêm một vẫn).
Nếu nó không tìm thấy thì nó đọc lên đến 32k - hy vọng chỉ một lần; nếu có nhiều hơn những ký tự đó có thể còn lại mà không có dấu ngắt dòng thì nó sẽ thực hiện lần đọc thứ hai nhưng vẫn thêm dòng mới giả mạo đó và ngắt dòng đó. Bạn không thể làm gì nhiều về điều đó bằng cách sử dụng dbms_output
tuy nhiên, bạn sẽ cần chuyển sang utl_file
ghi vào máy chủ thay vì lưu vào máy khách.