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;
Is it possible to concatenate the .jpg filename in order to upload several images to a table?
I want it to do it with a cursor.
Here is the code:
CREATE OR REPLACE PROCEDURE upload_pics AS
CURSOR c_id IS
SELECT DISTINCT id_pic
FROM id_table;
r_id c_id%rowtype;
v_blob BLOB;
v_bfile BFILE;
BEGIN
FOR r_id IN c_id LOOP
v_bfile := bfilename('TMP_DIR', r_id.id_pic || '.jpg');
dbms_lob.open(v_bfile, dbms_lob.lob_readonly);
dbms_lob.loadfromfile(v_blob, v_bfile, dbms_lob.getlength(v_bfile));
UPDATE pic_table
SET
picture = v_blob
WHERE
id = r_id.id_pic;
dbms_lob.close(v_bfile);
END LOOP;
END;
Yes possible, here's is an alternative way which worked for me :
SQL> set serveroutput on;
SQL> Create or Replace Procedure upload_pics As
v_blob blob := null;
Function load_blob_from_file( filename varchar2, directoryname varchar2 ) Return blob Is
filecontent blob := null;
v_bfile bfile := bfilename(directoryname, filename);
v_offset pls_integer := 1;
v_var pls_integer;
Begin
v_var := dbms_lob.fileexists(v_bfile);
if v_var = 1 then
dbms_lob.createtemporary(filecontent, true, dbms_lob.session);
dbms_lob.fileopen(v_bfile, dbms_lob.file_readonly);
dbms_lob.loadblobfromfile(filecontent,v_bfile,dbms_lob.getlength(v_bfile),v_offset,v_offset);
dbms_lob.fileclose(v_bfile);
end if;
Return filecontent;
End;
Begin
for r_id in (
select distinct id_pic
from id_table
)
loop
v_blob := load_blob_from_file(to_char(r_id.id_pic)||'.jpg', 'TMP_DIR');
if v_blob is not null then
update pic_table set picture = v_blob where id = r_id.id_pic; commit;
dbms_output.put_line(to_char(r_id.id_pic)||' is OK');
end if;
end loop;
exception when others then dbms_output.put_line(sqlerrm);
End;
/
SQL> exec upload_pics;
I am writing a stored procedure where I have to do following: I want to have a file (any format properties, json, xml) which will have information of which columns I want to extract from my table.
For example: my table has columns A,B,C,D,E, and suppose my file.properties has below information
A=1
B=0
C=1
D=1
F=0
So my generated query should be Select A,C,D from my table;
How can I do this in Oracle 11G?
I think you need this
SQL> set serveroutput on;
SQL> create or replace procedure pr_dynamic_sql( v_result out sys_refcursor ) is
v_outfile utl_file.file_type;
v_path varchar2(100) := 'UTL_FILE_DIR';
-- alias for the directory where your text files generated at OS.
v_row varchar2(100);
v_file varchar2(100);
v_letter varchar2(10);
v_number varchar2(10);
v_sql varchar2(100):= 'select ';
begin
v_file := 'myfile.properties';
v_outfile := utl_file.fopen(v_path, v_file, 'r');
loop
begin
utl_file.get_line(v_outfile,v_row);
v_letter := regexp_substr(v_row,'[^=]');
v_number := substr(regexp_substr(v_row,'[^=]+$'),1,1);
if v_number = '1' then
v_sql := v_sql||v_letter||',';
end if;
exception when no_data_found then exit;
end;
end loop;
utl_file.fclose(v_outfile);
v_sql := rtrim(v_sql,',')||' from mytable';
open v_result for v_sql;
end;
and call
SQL> begin
pr_dynamic_sql(v_result => :v_result);
end;
/
to get results as of cursor type.
I am using Oracle 12, and I want to make a dynamic procedure which selects rows from specific table but according to an unknown conditio. That condition will be specified as input parameter.
Suppose I have a column called employee id and I want to call the procedure
with the following condition
execute s('employeeid = 2')
My code is
create or replace procedure s (condition varchar)
as
TYPE EmpCurTyp IS REF CURSOR; -- define weak REF CURSOR type
emp_cv EmpCurTyp; -- declare cursor variable
my_ename VARCHAR2(15);
my_sal NUMBER := 2;
mycondition varchar2(100):=condition;
BEGIN
OPEN emp_cv FOR -- open cursor variable
'SELECT employeeid, employeename FROM employees WHERE = :s' USING mycondition;
END;
but I am getting an error
missing expression
What am I doing wrong, and will the result of this procedure be selected rows from employees table that satisfy applied condition ?
The USING is meant to handle values, not pieces of code; if you need to edit your query depending on an input parameter ( and I believe this is a very dangerous way of coding), you should treat the condition as a string to concatenate to the query.
For example, say you have this table:
create table someTable(column1 number)
This procedure does somthing similar to what you need:
create or replace procedure testDyn( condition IN varchar2) is
cur sys_refcursor;
begin
open cur for 'select column1 from sometable where ' || condition;
/* your code */
end;
Hot it works:
SQL> exec testDyn('column1 is null');
PL/SQL procedure successfully completed.
SQL> exec testDyn('column99 is null');
BEGIN testDyn('column99 is null'); END;
*
ERROR at line 1:
ORA-00904: "COLUMN99": invalid identifier
ORA-06512: at "ALEK.TESTDYN", line 4
ORA-06512: at line 1
This is not embedded in a procedure yet but I tested this and works:
DECLARE
TYPE OUT_TYPE IS TABLE OF VARCHAR2 (20)
INDEX BY BINARY_INTEGER;
l_cursor INTEGER;
l_fetched_rows INTEGER;
l_sql_string VARCHAR2 (250);
l_where_clause VARCHAR2 (100);
l_employeeid VARCHAR2 (20);
l_employeename VARCHAR2 (20);
l_result INTEGER;
o_employeeid OUT_TYPE;
o_employeename OUT_TYPE;
BEGIN
l_cursor := DBMS_SQL.OPEN_CURSOR;
l_sql_string := 'SELECT employeeid, employeename FROM employees WHERE ';
l_where_clause := 'employeeid = 2';
l_sql_string := l_sql_string || l_where_clause;
DBMS_SQL.PARSE (l_cursor, l_sql_string, DBMS_SQL.V7);
DBMS_SQL.DEFINE_COLUMN (l_cursor,
1,
l_employeeid,
20);
DBMS_SQL.DEFINE_COLUMN (l_cursor,
2,
l_employeename,
20);
l_fetched_rows := 0;
l_result := DBMS_SQL.EXECUTE_AND_FETCH (l_cursor);
LOOP
EXIT WHEN l_result = 0;
DBMS_SQL.COLUMN_VALUE (l_cursor, 1, l_employeeid);
DBMS_SQL.COLUMN_VALUE (l_cursor, 2, l_employeename);
l_fetched_rows := l_fetched_rows + 1;
o_employeeid (l_fetched_rows) := l_employeeid;
o_employeename (l_fetched_rows) := l_employeename;
l_result := DBMS_SQL.FETCH_ROWS (l_cursor);
END LOOP;
DBMS_SQL.CLOSE_CURSOR (l_cursor);
DBMS_OUTPUT.PUT_LINE (o_employeeid (1));
DBMS_OUTPUT.PUT_LINE (o_employeename (1));
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.PUT_LINE ('GENERAL FAILURE: ' || SQLERRM);
END;
I'm trying to execute a stored procedure, but I'm not sure if my syntax is wrong or not.
set dbms_output.put_line on;
declare
v_premnum NUMBER(10);
v_util_type CHAR(10);
v_result VARCHAR2(200);
Begin
execute myprocedure( 'E', v_util_type, 73105 , v_premnum);
dbms_output.put_line = v_result
end;
/
There are two ways. Either your procedure has an output parameter:
declare
v_premnum NUMBER(10) := 1234;
v_util_type CHAR(10) := 'the type';
v_result VARCHAR2(200);
begin
myprocedure('E', v_util_type, 73105 , v_premnum, v_result);
dbms_output.put_line(v_result);
end;
Or it should be a function returning the desired value:
declare
v_premnum NUMBER(10) := 1234;
v_util_type CHAR(10) := 'the type';
v_result VARCHAR2(200);
begin
v_result := myfunction('E', v_util_type, 73105 , v_premnum);
dbms_output.put_line(v_result);
end;