Oui. Un LOB est un pointeur/référence vers une mémoire/un stockage sur disque. Vous devez d'abord "memalloc()" (... initialiser) le stockage, affecter le pointeur/référence à votre variable LOB. C'est ce que dbms_lob.createTemporary()
est pour. Sauf si vous initialisez une variable LOB avec un localisateur LOB valide, toutes vos opérations sur cette variable LOB échoueront avec ORA-22275: invalid LOB locator specified
.
Amélioration : Faites refactoriser un peu votre fonction PL/SQL :(Et veuillez noter que j'ai utilisé une requête factice pour le last_60_cpu_cursor
le curseur. Ne réutilisez pas le curseur, utilisez le vôtre ! :-))
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;
- Vous n'avez pas besoin d'ouvrir+récupérer+fermer le curseur. Une boucle de curseur régulière fera très bien l'affaire (sinon encore mieux, grâce à la récupération implicite en bloc sous les capots).
- Déclarer explicitement le LOB temporaire comme mis en cache (
cache => true
; comme vous l'avez déjà). Cela garantit que les blocs de données sont ajoutés au LOB en mémoire, au lieu d'être ajoutés sur le disque (cache => false
). - Concaténer les chaînes à ajouter au LOB afin de minimiser le nombre d'appels au
dbms_lob.append()
. - Supprimez le
dbms_output.put_line()
de votre fonction. Dans le cas d'un contenu LOB supérieur à 32 Ko, cela lèverait de toute façon une exception.
De plus, une fois que vous avez terminé de renvoyer le LOB à votre environnement Java, libérez le LOB temporaire . (Je ne suis pas un gars Java, je ne peux pas écrire l'extrait de code Java moi-même.)
De plus, vous avez une erreur conceptuelle dans votre code Java ; enregistrer le retour de la fonction en tant que Types.VARCHAR
est faux. Vous devriez plutôt utiliser le le type CLOB dédié d'Oracle
. (J'en ai vu en C#, Java doit en avoir aussi.)
En outre, il existe un problème de performances avec votre solution. Votre fonction renvoie un LOB. En PL/SQL, chaque valeur de fonction est renvoyée à son appelant sous la forme d'une copie complète de la valeur interne. Par conséquent, si vous renvoyez un LOB à partir d'une fonction, le contenu du LOB est dupliqué en arrière-plan avec un nouveau localisateur de LOB (/pointeur/référence). Vous devez utiliser Vous pouvez envisager d'utiliser une procédure stockée au lieu d'une fonction et transmettre le LOB à Java en tant que out nocopy
paramètre. La procédure stockée ressemblerait alors à ceci :
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;
À quoi ressemblerait votre appel Java, cela dépend de vous et de Documentation JDBC ; mais, à coup sûr, un LOB renvoyé de cette manière signifierait qu'il n'y aurait pas de copie du contenu en arrière-plan. Bien sûr, la nécessité de libérer le LOB temporaire alloué s'applique toujours.