UTL_FILE saving in local machine - sql

Hello,
I wanted to save all the functions,procedures,packages in my local machine. I tried with SPOOL but with spool im not sure to get the filename and save it. So i tried with UTL_FILE.. But the problem is my database is in UNIX and I wanted to save in my windows local machine. Im getting the below mentioned error
Fehlerbericht -
ORA-29283: Ungültiger Dateivorgang
ORA-06512: in "SYS.UTL_FILE", Zeile 536
ORA-29283: Ungültiger Dateivorgang
ORA-06512: in Zeile 24
29283. 00000 - "invalid file operation%s"
*Cause: An attempt was made to read from a file or directory that does
not exist, or file or directory access was denied by the
operating system.
*Action: Verify file and directory access privileges on the file system,
and if reading, verify that the file exists.
And the below is my code.
CREATE DIRECTORY FUNC_DIR AS 'C:\Workspace\BE\DB\Funktionen\';
CREATE DIRECTORY PROC_DIR AS 'C:\Workspace\BE\DB\Prozeduren';
CREATE DIRECTORY PACK_DIR AS 'C:\Workspace\BE\DB\Package\';
CREATE DIRECTORY PACBO_DIR AS 'C:\Workspace\BE\DB\Package_Body';
GRANT READ,WRITE ON DIRECTORY FUNC_DIR TO PUBLIC;
GRANT READ,WRITE ON DIRECTORY PROC_DIR TO PUBLIC;
GRANT READ,WRITE ON DIRECTORY PACK_DIR TO PUBLIC;
GRANT READ,WRITE ON DIRECTORY PACBO_DIR TO PUBLIC;
DECLARE
fileHandler UTL_FILE.FILE_TYPE;
filename VARCHAR2(60);
filetext VARCHAR2(32766);
filetype VARCHAR2(20);
BEGIN
FOR a IN (SELECT distinct name,type INTO filename,filetype
FROM all_source
WHERE type IN
('FUNCTION','PROCEDURE','PACKAGE','PACKAGE_BODY')
AND OWNER='HR')
LOOP
filetype := a.object_type;
filename := a.object_name;
IF (filetype = 'FUNCTION') THEN
fileHandler := UTL_FILE.FOPEN('FUNC_DIR', filename||'.sql', 'W');
ELSIF filetype = 'PROCEDURE' THEN
fileHandler := UTL_FILE.FOPEN('PROC_DIR', filename||'.sql', 'W');
ELSIF filetype = 'PACKAGE' THEN
fileHandler := UTL_FILE.FOPEN('PACK_DIR', filename||'.sql', 'W');
ELSIF filetype = 'PACKAGE_BODY' THEN
fileHandler := UTL_FILE.FOPEN('PACBO_DIR', filename||'.sql', 'W');
FOR b IN (SELECT text INTO filetext FROM all_source WHERE TYPE IN('FUNCTION')AND OWNER = 'HR' AND
NAME = (filename))
LOOP
filetext := b.text;
UTL_FILE.PUTF(fileHandler, filetext);
END LOOP;
UTL_FILE.FCLOSE(fileHandler);
ELSE
DBMS_OUTPUT.PUT_LINE('OBJECT TYPE DOES NOT MATCH');
END IF;
END LOOP;
EXCEPTION
WHEN utl_file.invalid_path THEN
raise_application_error(-20000, 'ERROR: Invalid PATH FOR file.');
END;
/

UTL_FILE writes to the database server. To write to your local machine, you would need to mount your directories on the db server. This is generally a bad idea!
Use spool to write to your machine just do:
spool c:\path\to\your\folder\file.name
select ....

You can use dbms_output.put_line in your PLSQL together with SPOOL to get the result. For example like the below.This prints ename, sal in the file_name.txt file.
set serveroutput on
Spool e:\file_name.txt
Begin
for c in (Select ename, sal from emp)
loop
dbms_output.put_line(c.ename || ',' || c.sal);
end loop;
End;
/
spool off
for your example, you can use the below
set serveroutput on
Spool C:\Workspace\BE\DB\Funktionen\Function1.sql
BEGIN
FOR a IN (SELECT distinct name,type
FROM all_source
WHERE type IN
('FUNCTION')
AND OWNER='HR')
LOOP
FOR b IN (SELECT text FROM all_source WHERE TYPE IN('FUNCTION')AND OWNER = 'HR' AND
NAME = (a.name))
LOOP
dbms_output.enable;
dbms_output.put_line(b.text);
END LOOP;
END LOOP;
EXCEPTION
WHEN others THEN
dbms_output.put_line( 'ERROR: Invalid PATH FOR file.'||sqlerrm);
END;
/
spool off
You can generate one master file which has plsql for all the functions individually which you can run for all the functions
set serveroutput on
spool C:\Workspace\BE\DB\Funktionen\function12.sql
begin
FOR a IN (SELECT distinct name,type
FROM all_source
WHERE type IN
('FUNCTION')
AND OWNER='HR')
loop
dbms_output.enable ;
dbms_output.put_line('set serveroutput on
Spool C:\Workspace\BE\DB\Funktionen\'||a.name||'.sql
BEGIN
FOR a1 IN (SELECT distinct name,type
FROM all_source
WHERE type IN
(''FUNCTION'')
AND OWNER=''HR'' and name='''||a.name||''')
LOOP
FOR b IN (SELECT text FROM all_source WHERE TYPE IN(''FUNCTION'')AND OWNER = ''HR'' AND
NAME = '''||a.name||'''))
LOOP
dbms_output.enable;
dbms_output.put_line(b.text);
END LOOP;
END LOOP;
EXCEPTION
WHEN others THEN
dbms_output.put_line( ''ERROR: Invalid PATH FOR file.''||sqlerrm);
END;'
);
END LOOP;
END;
/
spool off

Related

For loop fetching data from a cursor is getting skipped

This is the code I'm using. I'm a newbie to PL/SQL making some modifications to existing pl/sql code.
There is a cursor C_GET_REFERENCED_USER_GROUPS which is storing data from sec_user_group table based on user input which is stored inside variable r_username.
So I'm giving some input which will be taken as the value for variable used inside cursor C_GET_REFERENCED_USER_GROUPS and it has output with few rows. During the execution of the cursor inside a for loop, the for loop is getting completely skipped despite the fact that output is there and I haven't given any lines to exit out of the code.
This is how for loop has been created which loops through the cursor and adds to a table.
FOR R_GROUP_NAME IN C_GET_REFERENCED_USER_GROUPS
LOOP
BEGIN
add_user_to_group_cmd :='insert into PROD.SEC_USER_GROUP VALUES('||R_GROUP_NAME.group_id||','''||l_user_id||''',sys_context(''userenv'', ''current_user''),sysdate)';
dbms_output.put_line(add_user_to_group_cmd||';');
execute immediate (add_user_to_group_cmd);
exception
when others then
dbms_output.put_line('>>>>> ERROR : Unable to add user to group : '||SQLERRM);
END;
END LOOP;
COMMIT;
I don't get any errors while I'm executing this code, it's just the the execution finishes after the looping through the execution of for loop which loops through cursor C_GET_ROLE_DETAIL and just skips the above mentioned cursor execution which is executed last.
I had also printed the cursor during the beginning of the execution of PL/SQL block just to verify that the output exists by using simple for loop:
FOR rec IN C_GET_REFERENCED_USER_GROUPS
LOOP
DBMS_OUTPUT.put_line (rec.group_id);
END LOOP;
The above does print couple of rows yet the same rows are not being inserted during the last part of pl/sql insertion.
Please see below for the Full code:
SET lines 200
SET trimspool ON
SET echo OFF
SET verify OFF
--SET serveroutput ON size 1000000
SET serveroutput ON size unlimited
DECLARE
l_cmd VARCHAR2(4000);
l_rmsschema VARCHAR2(5000) := trim('&&rmsschema');
l_username VARCHAR2(5000);
l_password VARCHAR2(5000);
l_name VARCHAR2(5000);
l_email VARCHAR2(5000);
l_user_id VARCHAR2(5000) :=trim('&&userid');
l_pwd VARCHAR2(5000) :=trim('&&password');
l_new_username VARCHAR2(5000) :=trim('&&new_user_name');
l_user_email VARCHAR2(5000) :=trim('&&emailid');
r_username VARCHAR2(5000) :=trim('&&referenced_schema_name');
insert_new_user_cmd VARCHAR2(5000);
add_user_to_group_cmd VARCHAR2(5000);
l_granted_roles VARCHAR2(5000);
l_granted_groups VARCHAR2(5000);
RMS_SCHEMA_ERROR EXCEPTION;
CURSOR C_GET_NEW_USER_DETAIL
IS
select distinct nuc.user_id,nuc.pwd,nuc.user_name,nuc.user_email from PROD.NEW_USER_CREATION nuc
where not exists ( select 1 from dba_users du where du.username=nuc.user_id );
CURSOR C_GET_ROLE_DETAIL
IS
select distinct nuc.user_id,nuc.granted_role from PROD.NEW_USER_CREATION nuc order by 1;
CURSOR C_GET_REFERENCED_USER_ROLES
IS
select GRANTED_ROLE from dba_role_privs where grantee=r_username;
CURSOR C_GET_REFERENCED_USER_GROUPS
IS
select group_id from prod.sec_user_group where user_id=r_username;
BEGIN
----Testing the cursor values by printing it-----
FOR rec IN C_GET_REFERENCED_USER_GROUPS
LOOP
DBMS_OUTPUT.put_line (rec.group_id);
END LOOP;
------Insert into NEW_USER_CREATION_TABLE----------
OPEN C_GET_REFERENCED_USER_ROLES;
dbms_output.put_line('TRUNCATE TABLE PROD.NEW_USER_CREATION');
EXECUTE immediate 'TRUNCATE TABLE PROD.NEW_USER_CREATION';
LOOP
FETCH C_GET_REFERENCED_USER_ROLES into l_granted_roles;
EXIT when C_GET_REFERENCED_USER_ROLES%NOTFOUND;
insert_new_user_cmd := 'insert into PROD.NEW_USER_CREATION(USER_ID,PWD,USER_NAME,USER_EMAIL,GRANTED_ROLE) VALUES('''|| l_user_id ||''','''||l_pwd||''','''||l_new_username||''','''||l_user_email||''','''||l_granted_roles||''')';
dbms_output.put_line(insert_new_user_cmd||';');
execute immediate (insert_new_user_cmd);
commit;
END LOOP;
CLOSE C_GET_REFERENCED_USER_ROLES;
-- User Creation-------------------------------------------------------------------------
FOR A_REC IN C_GET_NEW_USER_DETAIL
LOOP
BEGIN
l_username := A_REC.USER_ID;
l_password := A_REC.PWD;
l_name := A_REC.USER_NAME;
l_email := A_REC.USER_EMAIL;
BEGIN
dbms_output.put(CHR(10));
dbms_output.put_line('Creating RMS');
BEGIN
l_cmd := 'CREATE USER "'||l_username||'" identified by "'||l_password||'" DEFAULT TABLESPACE USERS TEMPORARY TABLESPACE TEMP01';
dbms_output.put_line(l_cmd||';');
EXECUTE immediate (l_cmd);
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('>>>>> ERROR : CREATE USER : '||SQLERRM);
END;
BEGIN
--l_cmd := 'INSERT INTO '||l_rmsschema||'.USER_ATTRIB(USER_ID, USER_NAME, LANG, USER_EMAIL) VALUES('''||l_username||''','''||l_name||''',''1'','''||l_email||''')';
l_cmd := 'MERGE INTO '||l_rmsschema||'.USER_ATTRIB TGT';
l_cmd := l_cmd || ' USING (SELECT DISTINCT USER_ID,USER_NAME, USER_EMAIL FROM '||l_rmsschema||'.NEW_USER_CREATION WHERE user_id=''' || A_REC.USER_ID || ''') SRC';
l_cmd := l_cmd || ' ON (TGT.USER_ID = SRC.USER_ID )';
l_cmd := l_cmd || ' WHEN NOT MATCHED THEN';
l_cmd := l_cmd || ' INSERT (USER_ID, USER_NAME, LANG, USER_EMAIL)';
l_cmd := l_cmd || ' VALUES ('''||l_username||''','''||l_name||''',''1'','''||l_email||''')';
dbms_output.put_line(l_cmd||';');
EXECUTE immediate(l_cmd);
COMMIT;
--CR_SYNONYMS
BEGIN
declare
missing_object varchar2(128);
prefix1 varchar2(128);
prefix2 varchar2(128);
cursor c_get_missing_object is
select object_name
from dba_objects
where owner = upper(l_rmsschema)
and object_type in ('TABLE', 'VIEW', 'CLUSTER', 'FUNCTION', 'PACKAGE', 'PROCEDURE', 'SEQUENCE', 'TYPE')
and object_name not like 'DBC_%'
and object_name not like 'BIN$%'
MINUS
select object_name
from dba_objects
where owner = upper(l_username)
order by 1;
begin
if l_username <> '&_USER' then
prefix1:='"' || l_username || '".';
else
prefix1:='';
end if;
if l_rmsschema <> '&_USER' then
prefix2:='"' || l_rmsschema || '".' ;
else
prefix2:='';
end if;
open c_get_missing_object;
LOOP
fetch c_get_missing_object into missing_object;
--When at end of objects, exit
if c_get_missing_object%NOTFOUND then
exit;
end if;
BEGIN
execute immediate 'CREATE SYNONYM '||prefix1||'"'||missing_object||'" FOR '||prefix2||'"'||missing_object||'"';
dbms_output.put_line('Created synonym '||prefix1||missing_object||' pointing to '||prefix2||missing_object);
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('Create synonym FAILED '||missing_object||' '||SQLCODE||' - '||SQLERRM);
END;
END LOOP;
close c_get_missing_object;
end;
END;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('>>>>> ERROR RMS: INSERT USER_ATTRIB: '||SQLERRM);
END;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('>>>>> ERROR : '||SQLERRM);
END;
EXCEPTION
WHEN NO_DATA_FOUND THEN
EXIT ;
END;
END LOOP;
-- RMS Role Assignment-------------------------------------------------------------------------
FOR A_REC IN C_GET_ROLE_DETAIL
LOOP
-- RMS Role Assignment-------------------------------------------------------------------------
begin
l_cmd := 'grant '|| A_REC.GRANTED_ROLE ||' to "'||A_REC.USER_ID||'"';
dbms_output.put_line(l_cmd||';');
execute immediate (l_cmd);
exception
when others then
dbms_output.put_line('>>>>> ERROR : GRANT PRIVILEGES : '||SQLERRM);
end;
end loop;
commit;
EXCEPTION
WHEN utl_file.invalid_path THEN
raise_application_error(-20000, 'Invalid path. Create directory or set UTL_FILE_DIR.');
WHEN OTHERS THEN
dbms_output.put_line('>>>>> ERROR : '||SQLERRM);
-----Adding user to groups-----------------------------------------------------------------------
FOR R_GROUP_NAME IN C_GET_REFERENCED_USER_GROUPS
LOOP
BEGIN
add_user_to_group_cmd :='insert into PROD.SEC_USER_GROUP VALUES('||R_GROUP_NAME.group_id||','''||l_user_id||''',sys_context(''userenv'', ''current_user''),sysdate)';
dbms_output.put_line(add_user_to_group_cmd||';');
execute immediate (add_user_to_group_cmd);
exception
when others then
dbms_output.put_line('>>>>> ERROR : Unable to add user to group : '||SQLERRM);
END;
END LOOP;
COMMIT;
END;
/
I had spooled the output into a log file:Here is part of the log file:
Enter value for rmsschema: prod
Enter value for userid: SCOTT
Enter value for password: scott
Enter value for new_user_name: scott
Enter value for emailid: scott#test
Enter value for referenced_schema_name: 23093
1404
8322//These are the two values that are returned by the cursor and after that should be inserted into the table SEC_USER_GROUP but it's somehow getting skipped.////
TRUNCATE TABLE prod.NEW_USER_CREATION
insert into prod.NEW_USER_CREATION(USER_ID,PWD,USER_NAME,USER_EMAIL,GRANTED_ROLE) VALUES('SCOTT','scott','scott','scott#test','TEST_USER_ROLE');
insert into prod.NEW_USER_CREATION(USER_ID,PWD,USER_NAME,USER_EMAIL,GRANTED_ROLE) VALUES('SCOTT','scott','scott','scott#test','CUSTOMER_ROLE');
Creating RMS
CREATE USER "SCOTT" identified by "scott" DEFAULT TABLESPACE USERS TEMPORARY TABLESPACE TEMP01;
MERGE INTO prod.USER_ATTRIB TGT USING (SELECT DISTINCT USER_ID,USER_NAME, USER_EMAIL FROM prod.NEW_USER_CREATION WHERE user_id='SCOTT') SRC ON (TGT.USER_ID = SRC.USER_ID ) WHEN NOT
MATCHED THEN INSERT (USER_ID, USER_NAME, LANG, USER_EMAIL) VALUES ('SCOTT','scott','1','scott#test');
//Synonyms for the user created
Created synonym "SCOTT".AA_XX_ITEM pointing to "prod".AA_XX_ITEM
Created synonym "SCOTT".ACC_VALIDATE_API pointing to "prod".ACC_VALIDATE_API
Created synonym "SCOTT".ADDR pointing to "prod".ADDR
Created synonym "SCOTT".ADDRESS_SQL pointing to "prod".ADDRESS_SQL
.................................................................
grant TEST_USER_ROLE to "SCOTT";
grant CUSTOMER_ROLE to "SCOTT";
PL/SQL procedure successfully completed.
As seen above the last part of the code doesn't get executed even though the cursor returns rows.

How to listed all the tables of a User in a database? n

Hi so i have the following plan :
i want to Write a script, which calls another script. A parameter V_USERNAME should be passed from the 1st script to the 2nd script.( Using the keyword DEFINE)
My code look like :
##C:\Users\pe.k\Documents\script2.sql &p_v_username
set serveroutput on
define p_v_username = "user";
In the 2nd script all tables of the user should be output. (Using the key word EXECUTE IMMEDIATE and a cursor).
The output control is to be done via a parameter in the script or when calling the script.
Example call:
SQL> #start_script1 MML
declare
&p_v_username varchar2(100);
v_result varchar2(100);
cursor cp_username (&p_v_username varchar2)
is
select owner, table_name
from all_tables
where owner = &p_v_username
order by owner, table_name;
begin
dbms_output.put_line('Alle Tabellen der User'); --l_username);
open cp_username(&p_v_username);
--loop
--fetch cp_username into v_result;
-- dbms_output.put_line(v_result);
--end loop;
close cp_username;
end;
/
And i have the errors and i am lost. I dont know how to do it
Your second procedure should be something like this:
BEGIN
DBMS_OUTPUT.PUT_LINE('Alle Tabellen der User'); --l_username);
FOR TABS IN (
SELECT OWNER, TABLE_NAME
FROM ALL_TABLES
WHERE OWNER = '&P_V_USERNAME'
ORDER BY OWNER, TABLE_NAME
) LOOP
DBMS_OUTPUT.PUT_LINE(TABS.TABLE_NAME);
END LOOP;
END;
/
In order to print the output generated by the DBMS_OUTPUT package from PL/SQL, make sure to set serveroutput on

Command not properly ended PL SQL

I'm trying to implement a pl sql program that export the content of all tables of a particular user in a file but i'm getting 'command not properly ended' problem whenever i run it.
here is my code:
create or replace procedure userTable(name dba_tables.owner%type)
is
cursor cur1 is select table_name from dba_tables where owner = upper(name);
cursor cur(tabName in varchar2) is select column_name from dba_tab_columns where owner = upper(name) and table_name = upper(tabName);
V$FILEP UTL_FILE.FILE_TYPE;
type dyncursor is ref cursor;
dyn dyncursor;
req varchar2(32767):='select to_char(';
lig Varchar2(32767);
i integer:=1;
begin
if existUser(name) = true then
V$FILEP := UTL_FILE.FOPEN('DIRT001','TEST09.UTL','W');
for vc1 in cur1 loop
for vc in cur(to_char(vc1.table_name)) loop
if (i=1) then
req:=req||vc.column_name||')';
i:=0;
else
req:=req||'||'||''','''||'||'||'to_char('||vc.column_name||')';
end if;
end loop;
req:=req||' from '||name||'.'||'to_char('||vc1.table_name||')';
open dyn for req;
loop
fetch dyn into lig;
exit when dyn%notfound;
dbms_output.put_line(lig);
UTL_FILE.PUT_LINE(V$FILEP,lig );
end loop;
close dyn;
end loop;
UTL_FILE.FCLOSE(V$FILEP);
else
dbms_output.put_line('user invalid');
end if;
end;
/
create or replace function existUser(name dba_users.username%type)
return boolean is
nb number :=0;
begin
select count(*) into nb from dba_users where username = upper(name);
if nb = 0 then
return false;
else
return true;
end if;
end;
/
Expanding on what has been mentioned in the comments, adding a DBMS_OUTPUT is going to show you that you have 'from schema.to_char(table_name)'.....
vc1.table_name & vc.column_name are already character (varchar2) so there is no need to do a to_char on them in the first place so just removing to_char from around all these is a good first step.
Then if it still does not work add the DBMS_OUTPUT as suggested by Arkadiusz Łukasiewicz in the comments to see what other issues you may have.

ORACLE BLOB to FILE

I am writing some pl/sql to generate pdf reports that are stored as blobs in an oracle table. I need to loop through this table which has a column for filename and blob and write the blob to the OS as a file with the corresponding filename in the table. I pretty much have completed this code but am running into a snag:
ORA-06550: line 13, column 59:
PL/SQL: ORA-00904: "SIMS_PROD"."PUBLISH_RPT_NEW"."RPT_FILE_NAME": invalid identifier
ORA-06550: line 13, column 12:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
Cause: Usually a PL/SQL compilation error.
Action:
I did read the post on the site: How can I extract files from an Oracle BLOB field? - however - this is only for one file - my table contains hundreds of rows each that has a blob and associated filename - its the looping through this table thats giving me grief.
I need to prefix the schema name, table and column explicitly since I am logged in as a DBA user and not as the owner of the schema itself. Here is my code - what am I missing here or doing wrong. Thanks in advance for any help from the community - its much appreciated.
DECLARE
t_blob BLOB;
t_len NUMBER;
t_file_name VARCHAR2(100);
t_output utl_file.file_type;
t_totalsize NUMBER;
t_position NUMBER := 1;
t_chucklen NUMBER := 4096;
t_chuck RAW(4096);
t_remain NUMBER;
BEGIN
FOR X IN (SELECT SIMS_PROD.publish_rpt_new.RPT_FILE_NAME, SIMS_PROD.publish_rpt_new.RPT_CONTENTS FROM SIMS_PROD.PUBLISH_RPT)
LOOP
-- Get length of blob
SELECT dbms_lob.Getlength (SIMS_PROD.publish_rpt_new.RPT_CONTENTS), SIMS_PROD.publish_rpt_new.RPT_FILE_NAME INTO t_totalsize, t_file_name FROM SIMS_PROD.publish_rpt_new;
t_remain := t_totalsize;
-- The directory TEMPDIR should exist before executing
t_output := utl_file.Fopen ('PDF_REP', t_file_name, 'wb', 32760);
-- Get BLOB
SELECT SIMS_PROD.publish_rpt_new.RPT_CONTENTS INTO t_blob FROM SIMS_PROD.publish_rpt_new;
-- Retrieving BLOB
WHILE t_position < t_totalsize
LOOP
dbms_lob.READ (t_blob, t_chucklen, t_position, t_chuck);
utl_file.Put_raw (t_output, t_chuck);
utl_file.Fflush (t_output);
t_position := t_position + t_chucklen;
t_remain := t_remain - t_chucklen;
IF t_remain < 4096 THEN t_chucklen := t_remain;
END IF;
END LOOP;
END LOOP;
END;
Try replacing the line 13 with this:
FOR X IN (SELECT RPT_FILE_NAME, RPT_CONTENTS FROM SIMS_PROD.PUBLISH_RPT)
It is going to be a too late answer but at least you will know where have you done mistake. The problem is if you use:
FOR X IN (SELECT a, b from table) LOOP
You have to use X.a in next statements of this loop to properly refer to values of selected rows.
So in your code you had to change SIMS_PROD.publish_rpt_new.RPT_CONTENTS to X.SIMS_PROD.publish_rpt_new.RPT_CONTENTS.
I haven't read the rest of your code, so maybe there could be some more mistakes too.
have done a similar thing recently,
ping me for exact additional details
but the gist is this
create/frame excel or pdf as blob and store in to a blob column
use a base 64 converter function to store the same data into clob ( as text )
use sqlplus from windows/linux to spool the text from the clob column
convert the clob to blob with desired filename using os tools (probably ssl/certificate has utility to convert b64 t0 binary back )
Maybe you could consider writing a procedure separetly to save a BLOB as a file (any BLOB from any table) and then just loop through your table passing a BLOB, directory and file name. This way it could be used independently.
Here is the function (it is a function for some other reasons - you can change it to procedure) that does it like described:
Function BLOB2FILE (mBLOB BLOB, mDir VARCHAR2, mFile VARCHAR2) RETURN VarChar2
IS
BEGIN
Declare
utlFile UTL_FILE.FILE_TYPE;
utlBuffer RAW(32767);
utlAmount BINARY_INTEGER := 32767;
utlPos INTEGER := 1;
utlBlobLen INTEGER;
mRet VarChar2(100);
Begin
utlBlobLen := DBMS_LOB.GetLength(mBLOB);
utlFile := UTL_FILE.FOPEN(mDir, mFile,'wb', 32767);
--
WHILE utlPos <= utlBlobLen LOOP
DBMS_LOB.READ(mBLOB, utlAmount, utlPos, utlBuffer);
UTL_FILE.PUT_RAW(utlFile, utlBuffer, TRUE);
utlPos := utlPos + utlAmount;
END LOOP;
--
UTL_FILE.FCLOSE(utlFile);
mRet := 'OK - file created' || mFile;
RETURN mRet;
Exception
WHEN OTHERS THEN
IF UTL_FILE.IS_OPEN(utlFile) THEN
UTL_FILE.FCLOSE(utlFile);
END IF;
mRet := 'ERR - CLOB_ETL.BLOB2FILE error message ' || Chr(10) || SQLERRM;
RETURN mRet;
End;
END BLOB2FILE;
If you can select your BLOBS from any table just loop and pass it to the function/procedure with the directory and file name...

Read text file to insert data into Oracle SQL table

I am studying Oracle SQL developer.
What I am doing is reading text file line by line from the folder.
Then Inserting data to the SQL table.
I am able to compile my PROCEDURE, however, it doesn't seem to be inserting the data to file.
Create or Replace PROCEDURE Rfile is
f UTL_FILE.FILE_TYPE;
s VARCHAR2(200);
BEGIN
f := UTL_FILE.FOPEN('C:\Projects\','testdatabinary.txt','R');
IF UTL_FILE.IS_OPEN(f) THEN
LOOP
BEGIN
UTL_FILE.GET_LINE(f,s);
IF s IS NULL THEN
EXIT;
END IF;
INSERT INTO DATAINSERT
(COLUMN1, COLUMN2)
VALUES
(s, 'testdatabinary');
END;
END LOOP;
COMMIT;
END IF;
END;
And I have a table DATAINSERT with two varchar(200) type cols
I am not really sure the reasons that PROCEDURE is not inserting data to table
I just checked error message
Error starting at line 1 in command:
EXEC Rfile
ORA-29280: invalid directory path
ORA-06512: at "SYS.UTL_FILE", line 41
ORA-06512: at "SYS.UTL_FILE", line 478
ORA-06512: at "SYSTEM.RFILE", line 5
Not sure what causing problems. For me its working fine here is my example code
--Reference Site
--https://community.oracle.com/thread/3633577?start=0&tstart=0
set serveroutput on;
CREATE or replace DIRECTORY USER_DIR AS '/home/oracle';
GRANT READ ON DIRECTORY USER_DIR TO PUBLIC;
DECLARE
V1 VARCHAR2(200); --32767
F1 UTL_FILE.FILE_TYPE;
BEGIN
F1 := UTL_FILE.FOPEN('USER_DIR','temp.txt','R');
Loop
BEGIN
UTL_FILE.GET_LINE(F1,V1);
dbms_output.put_line(V1);
EXCEPTION WHEN No_Data_Found THEN EXIT; END;
end loop;
IF UTL_FILE.IS_OPEN(F1) THEN
dbms_output.put_line('File is Open');
end if;
UTL_FILE.FCLOSE(F1);
END;
/
set serveroutput off;
You can't able to enter the path directly to the file open command like this
f := UTL_FILE.FOPEN('C:\Projects\','testdatabinary.txt','R');
Instead of entering path directly, you have to create directory using the below sql query
CREATE or replace DIRECTORY USER_DIR AS 'C:\PROJECTS\';
Then enter the directory name to the file open command. It will be like this
f := UTL_FILE.FOPEN('USER_DIR ','testdatabinary.txt','R');
First procedure trying to load the file from PC into the server whereas in second procedure file is from server to server. UTL_FILE.FOPEN works for server-side PL/SQL. So first procedure wont execute properly... If you want to load a file from PC to server, then you need to user any front end like D#K or VB.
The mistake your making here is using the workstation path, you actually need to be using the directory path.
The quickest way to resolve this, is just to use the WINSCP command.
Use WINSCP to tell you what the directory path is, then simply substitute this new information for the old path you have in your code, and everything should work ok.
This is very conceptual and tricky. which you can find more concepts and details below:
https://ora-data.blogspot.in/2016/11/read-and-writ-text-file-using-UTLFILE.html
Sure will be helpful:
create or replace procedure read_file is
f_line varchar2(2000);
f utl_file.file_type;
f_dir varchar2(250);
fname varchar2(50);
Comma1 varchar(10);
Comma2 varchar(10);
Comma3 varchar(10);
Comma4 varchar(10);
Comma5 varchar(10);
f_empno emp.empno%type;
f_ename emp.ename%type;
f_job emp.job%type;
f_mgr emp.mgr%type;
f_hiredate emp.hiredate%type;
f_sal emp.sal%type;
begin
f_dir := ‘E:\PLSQL’;
fname := ‘input.txt’;
f := utl_file.fopen(‘UTL_FILE_DIR’,fname,’r’); –opening the file using fopen function
loop
begin
utl_file.get_line(f,f_line);
–using a loop continuously get the file’s content using get_line function exception when no_data_found then
exit;
end;
Comma1 := INSTR(f_line, ‘,’ ,1 , 1);
Comma2 := INSTR(f_line, ‘,’ ,1 , 2);
Comma3 := INSTR(f_line, ‘,’ ,1 , 3);
Comma4 := INSTR(f_line, ‘,’ ,1 , 4);
Comma5 := INSTR(f_line, ‘,’ ,1 , 5);
–Each field in the input record is delimited by commas.
–We need to find the location of two commas in the line.
–and use the locations to get the field from the line.
f_empno := to_number(SUBSTR(f_line, 1, Comma1-1));
f_ename := SUBSTR(f_line, Comma1+1, Comma2-Comma1-1);
f_job := SUBSTR(f_line, comma2+1, Comma3-Comma2-1);
f_mgr := to_number(SUBSTR(f_line, comma3+1, Comma4-Comma3-1));
f_hiredate := to_date(SUBSTR(f_line, comma4+1, Comma5-Comma4-1),’dd-mon-yyyy’);
f_sal := to_number(SUBSTR(f_line, comma5+1),’99999′); dbms_output.put_line(f_empno ||’ ‘|| f_ename || ‘ ‘ || f_job || ‘ ‘ || f_mgr ||’ ‘ || f_hiredate||’ ‘|| f_sal);
insert into emp12 VALUES (f_empno,f_ename,f_job,f_mgr,f_hiredate,f_sal);
end loop;
utl_file.fclose(f);
commit;
end;
/
first login with
username:sys as sysdba
password should be the same as used for user 'system'
now enter
SQL> grant execute on UTL_FILE to PUBLIC;
Now login with any user with which you want to create procedure