Provided that the stored procs will nevertheless be a viable alternative for you, here is one possible solution to your problem ...
First, let me make this nice base64encode() Tim Hall function into a procedure ...
create or replace procedure base64encode ( i_blob in blob , io_clob in out nocopy clob ) is l_step pls_integer := 22500;
The βtrickβ here is to directly use persistent large object locators in procedure / function calls. Why "stubborn"? Because if you create a function that returns a LOB, then a temporary LOB is created that is created in the background, and that means using a TEMP disk / memory and copying the contents of the LOB. For large large objects, this can mean a performance hit. To meet your requirements, to make it most efficient, you should avoid using the TEMP space. Therefore, a stored procedure should be used instead of a function for this approach.
Then, of course, the procedure should be served with constant locators of large objects. You must do this, again, using a stored procedure where you, for example. first insert the empty LOB (actually creating a new LOB locator) into the table, and then providing this newly created LOB locator to the base64 encoding procedure ...
create or replace procedure load_and_encode_image ( i_file_name in varchar2 ) is l_input_bfile bfile := bfilename('DIR_ANYTHING', i_file_name); l_image_base64_lob test.imageBase64%type; l_image_raw test.image%type; begin insert into test(image, imageBase64) values (empty_blob(), empty_clob()) returning image, imageBase64 into l_image_raw, l_image_base64_lob; begin dbms_lob.fileopen(l_input_bfile); dbms_lob.loadfromfile( dest_lob => l_image_raw, src_lob => l_input_bfile, amount => dbms_lob.getlength(l_input_bfile) ); dbms_lob.fileclose(l_input_bfile); exception when others then if dbms_lob.fileisopen(l_input_bfile) = 1 then dbms_lob.fileclose(l_input_bfile); end if; raise; end; base64encode( i_blob => l_image_raw, io_clob => l_image_base64_lob ); end;
Note: Of course, if you base64 encode only small files (the actual size depends on your PGA settings, I guess; a question for the database administrator, this is), then the function-based approach can be equally implemented than this one based on procedure. The Base64-encoded 200 MB file on my laptop took 55 seconds using the function + update approach, 14 seconds using the procedure. Not exactly a speed demon, so choose what suits your needs.
Note. . I believe that this procedure-based approach can be further accelerated by reading the file so that the pieces are briefly in a loop, base64-encoding the fragments into other memory fragments and adding them constant LOBs to the target. Therefore, you should make the workload even easier by avoiding re-reading the full contents of the test.image LOB using the base64encode() procedure.