Đúng. LOB là một con trỏ / tham chiếu đến bộ nhớ / ổ lưu trữ. Trước tiên, bạn cần phải "memalloc ()" (... khởi tạo) bộ lưu trữ, gán con trỏ / tham chiếu cho biến LOB của bạn. Đó là những gì dbms_lob.createTemporary()
là cho. Trừ khi bạn khởi tạo biến LOB bằng bộ định vị LOB hợp lệ, tất cả các thao tác của bạn trên biến LOB đó sẽ không thành công với ORA-22275: invalid LOB locator specified
.
Cải tiến: Đã cấu trúc lại hàm PL / SQL của bạn một chút:(Và xin lưu ý rằng tôi đã sử dụng một truy vấn giả cho last_60_cpu_cursor
con trỏ. Không sử dụng lại con trỏ, hãy sử dụng con trỏ của riêng bạn! :-))
create or replace
function statistics_function
( namein in varchar2 )
return clob
is
line clob;
cursor last_60_cpu_cursor is
select 1 as last_60_cpu, sysdate as last_60_event_date
from dual
;
begin
dbms_lob.createtemporary(lob_loc => line, cache => true, dur => dbms_lob.call);
for cv in last_60_cpu_cursor loop
dbms_lob.append(line, to_char(cv.last_60_event_date)||'i'||to_char(cv.last_60_cpu)||chr(10));
end loop;
dbms_lob.append(line, 'last_60_cpu'||chr(10));
return line;
end statistics_function;
- Bạn không cần mở + tìm nạp + đóng con trỏ. Vòng lặp con trỏ thông thường sẽ hoạt động tốt (nếu không tốt hơn nữa, nhờ tính năng tìm nạp hàng loạt ngầm bên dưới).
- Khai báo rõ ràng LOB tạm thời là được lưu trong bộ nhớ cache (
cache => true
; như bạn đã có). Điều này đảm bảo các khối dữ liệu được thêm vào LOB trong bộ nhớ, thay vì được thêm vào đĩa (cache => false
). - Nối các chuỗi sẽ được nối vào LOB để giảm thiểu số lượng lệnh gọi đến
dbms_lob.append()
. - Xóa
dbms_output.put_line()
từ chức năng của bạn. Trong trường hợp nội dung LOB lớn hơn 32K, điều này sẽ đưa ra một ngoại lệ.
Ngoài ra, sau khi bạn hoàn tất việc gửi LOB trở lại môi trường Java của mình, giải phóng LOB tạm thời . (Tôi không phải dân Java, không thể tự viết đoạn mã Java.)
Ngoài ra, bạn có một lỗi khái niệm trong mã Java của mình; đăng ký trả về của hàm dưới dạng Types.VARCHAR
sai. Bạn nên sử dụng loại CLOB chuyên dụng của Oracle
. (Tôi đã thấy chúng trong C #, Java cũng phải có chúng.)
Ngoài ra, có một vấn đề về hiệu suất với giải pháp của bạn. Hàm của bạn trả về một LOB. Trong PL / SQL, mỗi giá trị hàm được trả về trình gọi của nó dưới dạng bản sao sâu của giá trị bên trong. Do đó, nếu bạn trả về LOB từ một hàm, nội dung LOB sẽ được sao chép trong nền với bộ định vị LOB mới (/ pointer / reference). Bạn nên sử dụng Bạn có thể cân nhắc việc sử dụng một thủ tục được lưu trữ thay vì một hàm và chuyển LOB sang Java dưới dạng out nocopy
tham số. Proc được lưu trữ sau đó sẽ trông giống như sau:
create or replace
procedure statistics_function
( namein in varchar2
, lob_out out nocopy clob )
is
cursor last_60_cpu_cursor is
select 1 as last_60_cpu, sysdate as last_60_event_date
from dual
;
begin
dbms_lob.createtemporary(lob_loc => lob_out, cache => true, dur => dbms_lob.session);
for cv in last_60_cpu_cursor loop
dbms_lob.append(lob_out, to_char(cv.last_60_event_date)||'i'||to_char(cv.last_60_cpu)||chr(10));
end loop;
dbms_lob.append(lob_out, 'last_60_cpu'||chr(10)||chr(10));
end statistics_function;
Lệnh gọi Java của bạn trông như thế nào, tùy thuộc vào bạn và Tài liệu JDBC ; nhưng, chắc chắn, một LOB được trả về theo cách này sẽ có nghĩa là không có nội dung nền nào được sao chép. Tất nhiên, nhu cầu giải phóng LOB tạm thời được phân bổ vẫn được áp dụng.