Liquibase script to change BLOB data to CLOB in oracle - oracle

I need to change one BLOB column type into CLOB so it will store data in json form. But I need to migrate all existing data to new format. Is there a way in liquibase to convert all stored BLOBs into CLOB.
Any links/ reference would be helpful

It will help u
CREATE OR REPLACE FUNCTION blob_to_clob (blob_in IN BLOB)
RETURN CLOB
AS
v_clob CLOB;
v_varchar VARCHAR2(32767);
v_start PLS_INTEGER := 1;
v_buffer PLS_INTEGER := 32767;
BEGIN
DBMS_LOB.CREATETEMPORARY(v_clob, TRUE);
FOR i IN 1..CEIL(DBMS_LOB.GETLENGTH(blob_in) / v_buffer)
LOOP
v_varchar := UTL_RAW.CAST_TO_VARCHAR2(DBMS_LOB.SUBSTR(blob_in, v_buffer, v_start));
DBMS_LOB.WRITEAPPEND(v_clob, LENGTH(v_varchar), v_varchar);
v_start := v_start + v_buffer;
END LOOP;
RETURN v_clob;
END blob_to_clob;
/
https://community.oracle.com/thread/206993

Related

How to pass a parameter of CLOB type to Oracle stored procedure which is having 100k+ length string?

Create procedure p(p1 clob) as
(
##code goes here..
);
exec p('100k+ length string...');
When I tried above procedure with 100k+ length string it is throwing ORA-20002: -20002:ORA-20002: -6502:ORA-06502: PL/SQL: numeric or value error\nORA-06512: at
How can we pass the value to the stored procedure?
Do we need to increase the db_block_size to increase the capacity of CLOB datatype?
You can pass the clob to the procedure just like other data types (on db<>fiddle):
create or replace procedure p (p1 clob) as
begin
dbms_output.put_line ('clob len='||length (p1));
end;
/
declare
c clob := '123';
begin
for i in 1..4 loop
dbms_lob.append (c, rpad ('A', 32767, 'A')); end loop;
p (c);
end;
/
clob len=131071
I think you are mistaken what a CLOB datatype can store with the procedure put_line of dbms_output
DBMS_OUTPUT.PUT_LINE ( item IN VARCHAR2);
The item is a varchar2 object. So, if you want to print the output of a clob greater than the limit of a varchar, you need to create a different kind of code. In my case, I use always the below code to print a clob column:
create or replace procedure print_clob_to_output (p_clob in clob)
is
l_offset pls_integer := 1;
l_chars pls_integer;
begin
loop
exit when l_offset > dbms_lob.getlength(p_clob);
l_chars := dbms_lob.instr(p_clob, chr(10), l_offset, 1);
if l_chars is null or l_chars = 0 then
l_chars := dbms_lob.getlength(p_clob) + 1;
end if;
dbms_output.put_line(dbms_lob.substr(p_clob, l_chars - l_offset, l_offset));
l_offset := l_chars + 1;
end loop;
end print_clob_to_output;

Oracle - extract images from BLOB

I'm really green. I want to extract images (JPGs) from Oracle PDB. Table Looks something like this:
select * from BOB.USER_ID t
LINK_ID ID_SCAN
1 340101001 <BLOB>...
2 340101002 <BLOB>...
3 340101003 <BLOB>...
4 340101004 <BLOB>...
5 ...
If possible, I want to extract them, with LINK_ID names (340101001.jpg).
I can extract them one-by-one, but there are ~5000 images... I would love to do it with some command or something...
I've looked for solution, but things that I could understand a little, they didn't work.
Thank you and sorry for inconvenience.
I tried to do "cart" method,? but it didn't work out. I couldn't open files that were extracted. I also tried third-party software, OraLobEditor.
Other then that, I could not understand codes and commands, I found in internet.
I'm trying to use SQL and PL/SQL Developer.
Here's a package that has a bunch of file utilities that all work with Oracle DIRECTORY objects and the files within them. With this and some PL/SQL, you could easily extract BLOB's to files at the OS level. The procedure you're going to want to work with is blob_into_file. But you need to start by creating an Oracle directory object, which points to the location on the OS that you want to save the files. Note that the directory needs to be writable by the same OS user that the database is running as.
Example, where MY_IMAGES is the Oracle directory object, and '/tmp/my_images' is the directory on the filesystem, wriable by the user running the database - "oracle", for example.
Create or replace directory MY_IMAGES as '/tmp/my_images';
Grant read, write on directory MY_IMAGES to BOB;
Next, a simple loop that will write the objects to the OS after you've compiled the fileutils package provided below. This can be run via SQL*Plus or SQL-Developer.
--
-- This is the code that does the export of the images
--
Set serveroutput on;
Begin
For i in (Select link_id, id_scan from bob.user_id) loop
dbms_output.put_line('Exporting image '||i.link_id||'.jpg');
fileutils.blob_into_file('MY_IMAGES',i.link_id||'.jpg',i.id_scan);
End loop;
End;
/
Package spec
Create or replace package fileutils as
--
-- This procedure deletes a file, and depends on an Oracle DIRECTORY object being passed
--
Procedure delete_os_file (i_directory varchar2, i_filename varchar2);
--
-- This procedure moves and optionally renames a file,
-- and depends on an Oracle DIRECTORY object being passed
--
Procedure move_os_file ( i_source_directory in varchar2, i_source_file in varchar2, i_target_directory in varchar2, i_target_file in varchar2);
--
-- This procedure takes a blob variable and writes it to a file,
-- and depends on an Oracle DIRECTORY object being passed
--
Procedure blob_into_file (i_directory in varchar2, i_file_name in varchar2, i_blob in blob);
--
-- This procedure takes a file and uploads it into a blob variable
-- and depends on an Oracle DIRECTORY object being passed
--
Procedure file_into_blob(i_directory in varchar2, i_file_name in varchar2, o_blob out blob);
--
-- This procedure converts a clob to a blob
--
Procedure convert_clob_to_blob (i_clob in clob, o_blob out blob);
--
-- This procedure converts a blob to a clob
--
Procedure convert_blob_to_clob (i_blob in blob, o_clob out clob);
--
-- This one checks for file existence without Java
--
Function file_exists (i_directory in varchar2, i_filename in varchar2) return boolean;
--
-- Returns the basename of a filename
-- Works with Windows and UNIX pathnames
--
Function basename (i_filename in varchar2) return varchar2;
--
-- This takes a Base64 string and converts it to a binary BLOB
--
Procedure base64_string_to_blob (i_clob in clob, o_blob out blob);
Function base64_string_to_blob (i_clob in clob) return blob;
--
-- This takes a binary BLOB and converts it to a Base64 string
--
Procedure blob_to_base64_string (i_blob in blob, o_clob out clob);
Function blob_to_base64_string (i_blob in blob) return clob;
End fileutils;
/
Show error;
Package body
Set define off;
Create or replace package body fileutils as
Procedure delete_os_file (i_directory varchar2, i_filename varchar2)
is
Begin
utl_file.fremove(i_directory,i_filename);
End;
Procedure move_os_file
(
i_source_directory in varchar2,
i_source_file in varchar2,
i_target_directory in varchar2,
i_target_file in varchar2
)
is
srcdir varchar2(255) := upper(i_source_directory);
tgtdir varchar2(255) := upper(i_target_directory);
begin
--
-- NOTE: If you're getting the all-too-familiar
-- ORA-29292: file rename operation failed
-- and you're SURE that your directory names are correct,
-- and you're SURE that your privileges are correct, both at the
-- OS level, and within the database, there's one last thing that
-- can get you. I learned the hard way that this command will NOT
-- work successfully renaming a file from one filesystem to another,
-- at least when those filesystems are NFS mounted. That is all.
--
utl_file.frename(srcdir,i_source_file,tgtdir,i_target_file,TRUE);
end move_os_file;
Procedure blob_into_file (i_directory in varchar2, i_file_name in varchar2, i_blob in blob)
is
l_file utl_file.file_type;
l_buffer raw(32767);
l_amount binary_integer := 32767;
l_pos integer := 1;
i_blob_len integer;
Begin
i_blob_len := dbms_lob.getlength(i_blob);
l_pos:= 1;
-- Open the destination file.
l_file := utl_file.fopen(i_directory,i_file_name,'wb', 32767);
-- Read chunks of the BLOB and write them to the file
-- until complete.
while l_pos < i_blob_len loop
dbms_lob.read(i_blob, l_amount, l_pos, l_buffer);
utl_file.put_raw(l_file, l_buffer, TRUE);
l_pos := l_pos + l_amount;
end loop;
-- Close the file.
utl_file.fclose(l_file);
End blob_into_file;
Procedure file_into_blob(i_directory in varchar2, i_file_name in varchar2, o_blob out blob)
is
src_loc bfile := bfilename(i_directory, i_file_name);
Begin
-- Initialize the dest blob
o_blob := empty_blob();
-- Open source binary file from OS
dbms_lob.open(src_loc, dbms_lob.lob_readonly);
-- Create temporary LOB object
dbms_lob.createtemporary(
lob_loc => o_blob
, cache => true
, dur => dbms_lob.session
);
-- Open temporary lob
dbms_lob.open(o_blob, dbms_lob.lob_readwrite);
-- Load binary file into temporary LOB
dbms_lob.loadfromfile(
dest_lob => o_blob
, src_lob => src_loc
, amount => dbms_lob.getLength(src_loc));
-- Close lob objects
dbms_lob.close(o_blob);
dbms_lob.close(src_loc);
End file_into_blob;
Function basename (i_filename in varchar2) return varchar2
is
v_basename varchar2(1024);
Begin
--
-- If the regex's below don't match, then it's already at its base name
-- Return what was passed.
--
v_basename := i_filename;
if regexp_like(i_filename,'^.*\\') then
dbms_output.put_line('This is a Windows file');
v_basename := regexp_substr(i_filename,'[^\]*$');
dbms_output.put_line('Basename is : '||v_basename);
end if;
if regexp_like(i_filename,'^/') then
dbms_output.put_line('This is a UNIX file');
v_basename := regexp_substr(i_filename,'[^/]*$');
dbms_output.put_line('Basename is : '||v_basename);
end if;
return v_basename;
End basename;
Function file_exists (i_directory in varchar2, i_filename in varchar2) return boolean
is
v_exists boolean;
v_file_length number;
v_block_size number;
Begin
utl_file.fgetattr(upper(i_directory), i_filename, v_exists, v_file_length, v_block_size);
if (v_exists) then
dbms_output.put_line('File '||i_filename||' exists, '||v_file_length||' bytes');
else
dbms_output.put_line('File '||i_filename||' does not exist');
end if;
return v_exists;
end file_exists;
Procedure convert_clob_to_blob (i_clob in clob, o_blob out blob)
is
v_in pls_Integer := 1;
v_out pls_Integer := 1;
v_lang pls_Integer := 0;
v_warning pls_Integer := 0;
Begin
dbms_lob.createtemporary(o_blob,TRUE);
dbms_lob.converttoblob(o_blob,i_clob,DBMS_lob.getlength(i_clob),v_in,v_out,dbms_lob.default_csid,v_lang,v_warning);
End convert_clob_to_blob;
Procedure convert_blob_to_clob (i_blob in blob, o_clob out clob)
is
v_in pls_Integer := 1;
v_out pls_Integer := 1;
v_lang pls_Integer := 0;
v_warning pls_Integer := 0;
Begin
dbms_lob.createtemporary(o_clob,TRUE);
dbms_lob.converttoclob(o_clob,i_blob,DBMS_lob.getlength(i_blob),v_in,v_out,dbms_lob.default_csid,v_lang,v_warning);
End convert_blob_to_clob;
Procedure blob_to_base64_string (i_blob in blob, o_clob out clob)
is
v_out_cl clob;
file_len pls_integer;
modulo pls_integer;
pieces pls_integer;
amt binary_integer := 23808;
buf raw (32767);
buf_tx varchar2(32767);
pos pls_integer := 1;
filepos pls_integer := 1;
counter pls_integer := 1;
Begin
dbms_lob.createtemporary (v_out_cl, true, dbms_lob.call);
file_len := dbms_lob.getlength (i_blob);
modulo := mod (file_len, amt);
pieces := trunc (file_len / amt);
while (counter <= pieces) loop
dbms_lob.read (i_blob, amt, filepos, buf);
buf_tx:=utl_raw.cast_to_varchar2 (utl_encode.base64_encode (buf));
dbms_lob.writeappend (v_out_cl,length(buf_tx),buf_tx);
filepos := counter * amt + 1;
counter := counter + 1;
end loop;
if (modulo <> 0) THEN
dbms_lob.read (i_blob, modulo, filepos, buf);
buf_tx:=utl_raw.cast_to_varchar2 (utl_encode.base64_encode (buf));
dbms_lob.writeappend (v_out_cl,length(buf_tx),buf_tx);
end if;
o_clob := v_out_cl;
End blob_to_base64_string;
Function blob_to_base64_string (i_blob in blob) return clob
is
v_out_cl clob;
file_len pls_integer;
modulo pls_integer;
pieces pls_integer;
amt binary_integer := 23808;
buf raw (32767);
buf_tx varchar2(32767);
pos pls_integer := 1;
filepos pls_integer := 1;
counter pls_integer := 1;
Begin
dbms_lob.createtemporary (v_out_cl, true, dbms_lob.call);
file_len := dbms_lob.getlength (i_blob);
modulo := mod (file_len, amt);
pieces := trunc (file_len / amt);
while (counter <= pieces) loop
dbms_lob.read (i_blob, amt, filepos, buf);
buf_tx:=utl_raw.cast_to_varchar2 (utl_encode.base64_encode (buf));
dbms_lob.writeappend (v_out_cl,length(buf_tx),buf_tx);
filepos := counter * amt + 1;
counter := counter + 1;
end loop;
if (modulo <> 0) THEN
dbms_lob.read (i_blob, modulo, filepos, buf);
buf_tx:=utl_raw.cast_to_varchar2 (utl_encode.base64_encode (buf));
dbms_lob.writeappend (v_out_cl,length(buf_tx),buf_tx);
end if;
return v_out_cl;
End blob_to_base64_string;
Procedure base64_string_to_blob (i_clob in clob, o_blob out blob)
is
v_out_bl blob;
clob_size number;
pos number;
charBuff varchar2(32767);
dBuffer RAW(32767);
v_readSize_nr number;
v_line_nr number;
begin
dbms_lob.createTemporary (v_out_bl, true, dbms_lob.call);
v_line_nr:=greatest(65, instr(i_clob,chr(10)), instr(i_clob,chr(13)));
v_readSize_nr:= floor(32767/v_line_nr)*v_line_nr;
clob_size := dbms_lob.getLength(i_clob);
pos := 1;
while (pos < clob_size) loop
dbms_lob.read (i_clob, v_readSize_nr, pos, charBuff);
dBuffer := UTL_ENCODE.base64_decode (utl_raw.cast_to_raw(charBuff));
dbms_lob.writeAppend (v_out_bl,utl_raw.length(dBuffer),dBuffer);
pos := pos + v_readSize_nr;
end loop;
o_blob := v_out_bl;
end base64_string_to_blob;
Function base64_string_to_blob (i_clob in clob) return blob
is
v_out_bl blob;
clob_size number;
pos number;
charBuff varchar2(32767);
dBuffer RAW(32767);
v_readSize_nr number;
v_line_nr number;
begin
dbms_lob.createTemporary (v_out_bl, true, dbms_lob.call);
v_line_nr:=greatest(65, instr(i_clob,chr(10)), instr(i_clob,chr(13)));
v_readSize_nr:= floor(32767/v_line_nr)*v_line_nr;
clob_size := dbms_lob.getLength(i_clob);
pos := 1;
while (pos < clob_size) loop
dbms_lob.read (i_clob, v_readSize_nr, pos, charBuff);
dBuffer := UTL_ENCODE.base64_decode (utl_raw.cast_to_raw(charBuff));
dbms_lob.writeAppend (v_out_bl,utl_raw.length(dBuffer),dBuffer);
pos := pos + v_readSize_nr;
end loop;
return v_out_bl;
end base64_string_to_blob;
end fileutils;
/
Show error;

Oracle loop through CLOB to get string

I want to convert all data in CLOB to string. DBMC_LOB.SUBSTR provides a way to fetch 4000 characters at once. I am from MS SQL background and not aware of Oracle queries. Can someone help me with the syntax.
I want to make a function and do something like
// Get the length of CLOB
// totalIterationsRequired = length/4000;
// LOOP around the CLOB and fetch 4000 char at once
For i in 1..totalIterationsRequired
LOOP
// Insert the substring into a varchar2
// DBMC_LOB.SUBSTR(xml_value,4000*i,(4000*(i-1)+1)
END LOOP
// The function will return the varchar2
create table save_table(rec varchar2(4000));
create or replace PROCEDURE save_clob (p_clob IN CLOB)
AS
l_length INTEGER;
l_start INTEGER := 1;
l_recsize CONSTANT INTEGER := 4000;
BEGIN
l_length := DBMS_LOB.getlength (p_clob);
WHILE l_start <= l_length
LOOP
INSERT INTO save_table (rec)
VALUES (DBMS_LOB.SUBSTR (p_clob, l_recsize, l_start));
l_start := l_start + l_recsize;
END LOOP;
END save_clob;
Below is the function definition
create or replace function getclobastable (id IN VARCHAR2)
return clob_table
is
l_length INTEGER;
l_start INTEGER := 1;
l_recsize CONSTANT INTEGER := 4000;
i_clob CLOB;
n BINARY_INTEGER := 0;
save_table clob_table := clob_table();
BEGIN
save_table := clob_table();
-- Get the CLOB data into i_clob
l_length := DBMS_LOB.getlength (i_clob);
WHILE l_start <= l_length
LOOP
n := n + 1;
save_table.EXTEND();
save_table(n) := DBMS_LOB.SUBSTR (i_clob, l_recsize, l_start);
l_start := l_start + l_recsize;
END LOOP;
RETURN save_table;
END;

Working with dbms_lob.copy and error ORA-06502:

I am bit lost with working with dbms_lob.copy
CREATE OR REPLACE PROCEDURE Ex_PRC IS
dest_lob CLOB;
src_lob CLOB;
BEGIN
SELECT F_CLOB INTO dest_lob
FROM EX_EMPLOYEE
WHERE id = 1;
dbms_lob.copy (dest_lob, src_lob, 30, 1, 1);
COMMIT;
END;
/
I got error
numeric or value error invalid lob locator specified ora-22275
I followed up this SO answer because thats what I needed is to split the blob and move them .but I didnt understand why he used dbms_lob.createtemporary
set serveroutput on
create or replace procedure test_clob (p_clob_res out clob) is
cursor c_tabs is
select ename from emp;
v_clob clob;
amt integer := 0;
begin
dbms_lob.createtemporary(v_clob,true,dbms_lob.session);
for r_tabs in c_tabs
loop
dbms_lob.writeappend(v_clob,length(r_tabs.ename)+1,r_tabs.ename||' ');
amt := amt + length(r_tabs.ename);
end loop;
p_clob_res := v_clob;
end test_clob;
/
create or replace procedure call_clob is
p_clob clob;
my_buff varchar2 (2000);
amt binary_integer := 2000;
begin
test_clob(p_clob);
my_buff := dbms_lob.substr(p_clob,amt,1);
dbms_output.put_line(my_buff);
end call_clob;
/
begin
call_clob();
end;
/

Is there any way to use the utl_file to generate a csv from data more than 32000 in oracle plsql

..
FILE1 := UTL_FILE.FOPEN('DIR','cg.csv','w',32000);
..
we are generating a csv file which has concatenated value of many columns of a view.
Is there any way to use the utl_file to generate a csv from data more than 32000 in oracle plsql
declare
FILEHANDLE UTL_FILE.FILE_TYPE;
WRITEMESSAGE varchar2(200);
longLine varchar2(32767);
newline char(2) := CHR(13) || CHR(10);
begin
longLine := LPAD('aaaa', 32766,'x');
FILEHANDLE := UTL_FILE.FOPEN('XMLDIR','lonLineFile.txt','wb',32767);
for i in 1 .. 5 loop
UTL_FILE.PUT_RAW (filehandle,UTL_RAW.CAST_TO_RAW (longLine),true);
UTL_FILE.PUT_RAW (filehandle,UTL_RAW.CAST_TO_RAW (longLine),true);
UTL_FILE.PUT_RAW (filehandle,UTL_RAW.CAST_TO_RAW (longLine),true);
UTL_FILE.PUT_RAW (filehandle,UTL_RAW.CAST_TO_RAW (newline),true);
end loop;
UTL_FILE.FCLOSE(filehandle);
end;
/
Open file in 'wb' write byte mode. Next write raw to file and end of line char.
According to Oracle's documentation for the function UTL_FILE.FOPEN:
FOPEN max_linesize parameter must be a number in the range 1 and 32767
so you can increase it to 32767, but not further then that.
You might want to consider creating multiple files.
Yes there is a way - use clob data type instead of varchar2. clob maximum size in PL/SQL is 128TB.
In your PL/SQL code first collect data to a temporary clob. Second iterate the clob in chunks and feed those to utl_file.
Below is a random internet code snippet that writes an arbitrary clob to a user defined file:
procedure save (
p_text in clob,
p_path in varchar2,
p_filename in varchar2
) as
v_lob_temp blob;
begin
--
-- exit if any parameter is null
--
if p_text is null
or p_path is null
or p_filename is null then
return;
end if;
--
-- convert a clob to a blob
--
declare
v_dest_offset pls_integer := 1;
v_src_offset pls_integer := 1;
v_lang_context pls_integer := dbms_lob.default_lang_ctx;
v_warning pls_integer := dbms_lob.no_warning;
begin
dbms_lob.createtemporary(lob_loc => v_lob_temp,
cache => true,
dur => dbms_lob.call);
dbms_lob.converttoblob(dest_lob => v_lob_temp,
src_clob => p_text,
amount => dbms_lob.lobmaxsize,
dest_offset => v_dest_offset,
src_offset => v_src_offset,
blob_csid => dbms_lob.default_csid,
lang_context => v_lang_context,
warning => v_warning);
-- TODO raise (what?) when warning
end;
--
-- write a blob to a file
--
declare
v_lob_len pls_integer;
v_fh utl_file.file_type;
v_pos pls_integer := 1;
v_buffer raw(32767);
v_amount pls_integer := 32767;
begin
v_fh := utl_file.fopen(p_path, p_filename, 'wb', 32767);
v_lob_len := dbms_lob.getlength(v_lob_temp);
while v_pos < v_lob_len loop
dbms_lob.read(v_lob_temp, v_amount, v_pos, v_buffer);
utl_file.put_raw(file => v_fh,
buffer =>v_buffer,
autoflush => false);
v_pos := v_pos + v_amount;
end loop;
utl_file.fclose(v_fh);
dbms_lob.freetemporary(v_lob_temp);
end;
end;

Resources