utl_file.fopen failing Occasionally - oracle

Everyone,
We have a set of 8 jobs which runs in parallel on Unix server. Those jobs calls Oracle stored procedure. All those procedures does a set of DB operations (on different tables) and at the end creates files in Unix server. (Each job creates a file in different names. But puts in same folder)
Recently, we are seeing random failures with error message "ORA-06512: at "SYS.UTL_FILE", line 536". Each day one or two job fails, while creating the error report. When the job is rerun there is no issues. We couldn't reproduce the issue in lower environment.
The folder has all access granted. This jobs have been running for more than an year with no issues. Any ideas appreciated.
Based on my analysis:-
DB Operations have completed without any issues. There is no file created (not even an empty one). So it failed while encountering fopen.
Sample code
DECLARE
IN_CONT_TYPE varchar2(100) := 'HARDWARE_ATTRIBUTES' ;
in_batch_name ccpm_epslz_control.push_batch_name%TYPE := 'HARDWARE_ATTRIBUTES_20181211062540';
l_file_type utl_file.file_type;
file_record_hold_cur sys_refcursor;
BEGIN
/*DB Operations*/
l_file_type :=utl_file.fopen('ERR_FOLDER',l_file_name,'W');
utl_file.put_line(l_file_type, 'count of input records filtered based on errors:');
utl_file.put_line(l_file_type, '-----------------------------------------------');
utl_file.put_line(l_file_type, l_col_name_print);
OPEN file_record_hold_cur FOR l_select_stmt_bus;
LOOP
FETCH file_record_hold_cur INTO l_putline_stmt_bus;
EXIT
WHEN file_record_hold_cur%notfound;
utl_file.put_line(l_file_type, l_putline_stmt_bus);
END LOOP;
CLOSE file_record_hold_cur;
utl_file.fclose(l_file_type);
EXCEPTION
WHEN OTHERS THEN
Dbms_Output.put_line ( DBMS_UTILITY.FORMAT_ERROR_BACKTRACE() );
END;
ERROR MESSAGE:- ORA-20051: Internal Error in file
generationORA-06512: at "MYPACKAGE", line 84                                                                   
ORA-06512: at "SYS.UTL_FILE", line 536

Related

Extracting output from PLSQL procedure to local drive of my laptop

I have a database connection server "server_dev" in sqldeveloper .
Now i want to create a procedure whose output can be directly saved in a csv file for data comparison later in the local drive of my laptop.
So i tried using UTL_FILE oracle package but when i ran the procedure the UTL_FILE was trying to write in the file of the server "server_dev" whereas i dont have any access to that server hence that command isnt working.
for example: the code is:-
CREATE OR REPLACE PROCEDURE export_to_csv_test
IS
v_file UTL_FILE.file_type;
v_string VARCHAR2 (4000);
CURSOR c_contexts
IS
SELECT workspace_id,context_id from contexts where rownum<5;
BEGIN
v_file :=
UTL_FILE.fopen ('Z:\My_Project_knowledge\CSVDIR', 'empdata.csv','w',1000);
FOR cur IN c_contexts
`enter code here`LOOP
v_string :=
cur.workspace_id
|| ','
|| cur.context_id;
UTL_FILE.put_line (v_file, v_string);
END LOOP;
UTL_FILE.fclose (v_file);
END;
for calling it :-
BEGIN
export_to_csv_test;
END;
Error report:
ORA-29280: invalid directory path
ORA-06512: at "SYS.UTL_FILE", line 41
ORA-06512: at "SYS.UTL_FILE", line 478
ORA-06512: at "RAY_DEV07_OWNER.EXPORT_TO_CSV_TEST", line 20
ORA-06512: at line 3
29280. 00000 - "invalid directory path"
*Cause: A corresponding directory object does not exist.
*Action: Correct the directory object parameter, or create a corresponding
directory object with the CREATE DIRECTORY command.
So,I analysed it and found that my SQL developer is connected to a server to my local machin and since its my office laptop I cant alter it.
Can i have any other way in which I can save the output of my stored procedure to my local drive in a text or Csv file?
To write a file to your local machine you may use dbms_output; for example in SQLPlus:
SQL> set feedback off
SQL> set echo off
SQL> set serveroutput on
SQL> spool d:\spool.txt
SQL> begin
2 for i in (select level from dual connect by level <= 5) loop
3 dbms_output.put_line('Level ' || i.level);
4 end loop;
5 end;
6 /
WIll produce the file d:\spool.txt:
Level 1
Level 2
Level 3
Level 4
Level 5
If you can select directly from a table or table function, then SQL*Plus 12.2's new SET MARKUP CSV option will be useful. Instead of paginating the query output it will produce CSV. The full syntax is
SET MARKUP CSV {ON|OFF} [DELIMI[TER] character] [QUOTE {ON|OFF}]
Output generation will faster if you turn on this mode with the sqlplus -m option.
It's also useful for querying JSON types. See https://blogs.oracle.com/opal/entry/fast_generation_of_csv_and

Not getting ORA-29285 - File write error (oracle) even the output file is incomplete

I've a code in oracle to write data from database to a file.
conn := utl_file.fopen('sample_directory','output.csv','W',32000);
for i in (select * from per_data)
loop
utl_file.put_line(conn,i.name||','||i.dept||','||to_char(i.start_date,'dd-mon- yy')||','||to_char(i.expire_date,'dd-mon-yy')||','||i.loc||','||i.currently||','||i.past||','||i.sub1||','||i.sub2||','||i.sub3||','||i.sub4||','||i.sub5||','||i.sub6||','||i.sub7||','||i.sub8||','||i.sub9||','||i.sub10||','||i.sub11||','||i.sub12||','||i.sub13||','||i.total,TRUE);
end loop;
utl_file.fclose(conn);
EXCEPTION
WHEN OTHERS THEN
dbms_output.Put_line('SQL Error' || SQLCODE || SQLERRM);
Oracle is not throwing ORA-29285 - File write error but I can see my output file to be incomplete.
Please Can someone help me out with this issue ?
Edit: The same piece of code worked fine before I add two new columns to the output. I mean to say that I had been notified by Oracle that there was file_write_error whenever I have an incomplete file.

DBMS_SCHEDULER.STOP_JOB not possible inside PL-SQL-Procedure, grants are given

my question is about using DBMS_SCHEDULER inside a package. I have given the SCHEDULER_ADMIN privileges to the user. Now I can set these commands inside my procedure after I have created the jobs via script outside the procedure.
-- set Job-Parameters
DBMS_SCHEDULER.SET_ATTRIBUTE(
name => jobidentifier,
attribute => 'job_action',
value => jobparam);
-- Job run.
DBMS_SCHEDULER.ENABLE(jobidentifier);
So far everything went well.
Now my question: Why don’t these commands work inside the code of my procedure?
-- Stop Job
DBMS_SCHEDULER.STOP_JOB (
job_name => jobidentifier,
force => true);
-- disable Job
DBMS_SCHEDULER.DISABLE(jobidentifier);
As soon as I enter the commands in an own session via script and not embedded in the package-code the commands work. The problem is I want to enter these commands inside my PL-SQL-package, cause inside my package I know when there occurs an error, so I want to enter these commands.
Can you help me? Thank you very much.
I'm getting the following error:
ORA-27486: Nicht ausreichende Berechtigungen ORA-06512: in "SYS.DBMS_ISCHED", Zeile 210 ORA-06512: in "SYS.DBMS_SCHEDULER", Zeile 557 ORA-06512: in "SCHEMANAME.JOB_KILLEN_PCK", Zeile 31 ORA-06512: in Zeile 6
the Grant I made was given by the sys_user:
GRANT SCHEDULER_ADMIN TO SCHEMANAME
in line 31 there is the following code
DBMS_SCHEDULER.STOP_JOB ( job_name => jobname, force => true);
Is this for securtiy reasons that Oracle does not want me to be able to stop_jobs by starting a Procedure. Cause this way I could stop each Job I know the name? If this is correct I will be unable to stop the Jobs in case of failures occurring during the Jobs in my procedure
If you want I can send you my test-Packages
I think stop_job with the force option requires the MANAGE SCHEDULER system privilege granted to the user owning the job.
Hope this helps.
#balakshman
Please don't use Force option and you are good, please find below example it works well with package integration.
DECLARE
V_COUNT NUMBER(3);
BEGIN
DBMS_SCHEDULER.STOP_JOB(job_name=>'ORDER_REPORT_JOB_1');
SELECT COUNT(*) INTO V_COUNT FROM DBA_SCHEDULER_JOBS WHERE JOB_NAME = 'ORDER_REPORT_JOB_1';
--THIS ORDER_REPORT_JOB_1 EXIST THEN ONLY DROP THE JOB
IF (V_COUNT=1) THEN
DBMS_SCHEDULER.DROP_JOB ('ORDER_REPORT_JOB_1');
END IF;
END;
/

Cannot open file using dbms_lob.filopen but can open it using utl_file

What could cause the following behaviour:
Database 11gR2
declare
l_amt number := dbms_lob.lobmaxsize;
l_dst_loc clob;
l_dst_offset number := 1;
l_lang_ctx number := dbms_lob.default_lang_ctx;
l_src_loc bfile;
l_src_offset number := 1;
l_warning number;
begin
l_src_loc := bfilename('ODS_SERVER_DIRECTORY', '_CIVKD_ASU.CSV');
dbms_lob.createtemporary(l_dst_loc, true);
dbms_lob.fileopen(l_src_loc, dbms_lob.file_readonly);
dbms_lob.loadclobfromfile(l_dst_loc
,l_src_loc
,l_amt
,l_dst_offset
,l_src_offset
,dbms_lob.default_csid
,l_lang_ctx
,l_warning);
commit;
dbms_lob.fileclose(l_src_loc);
dbms_output.put_line(substr(l_dst_loc, 1, 200));
end;
/
ORA-22288: file or LOB operation FILEOPEN failed
.
ORA-06512: in "SYS.DBMS_LOB", line 805
ORA-06512: in line 31
22288. 00000 - "file or LOB operation %s failed\n%s"
*Cause: The operation attempted on the file or LOB failed.
*Action: See the next error message in the error stack for more detailed
information. Also, verify that the file or LOB exists and that
the necessary privileges are set for the specified operation. If
the error still persists, report the error to the DBA.
However opening and reading the exact same file succeeds when using utl_file.
declare
l_file utl_file.file_type;
l_regel varchar2(4000);
begin
l_file := utl_file.fopen('ODS_SERVER_DIRECTORY', '_CIVKD_ASU.CSV', 'R');
-- Haal de volgende regel op
utl_file.get_line(l_file, l_regel);
dbms_output.put_line(l_regel);
utl_file.fclose_all;
end;
So it seems the file is available and accessable by the database.
It's the first time we run into this particular error and it's one of the first 11gR2 instances so maybe there is something 11g specific we don't know about?
=== Update 8-6-2012 ===
Some progress made. It turns out the directory object points to a shared drive. It's a windows server and Oracle runs as Local System. I always thought that it was impossible to read anything from a shared drive in this situation. Apparently in some situations you can using utl_file but not usign dbms_lob.
Could you confirm that ODS_SERVER_DIRECTORY is an actual DIRECTORY
SELECT
*
FROM
dba_objects
WHERE
object_type = 'DIRECTORY'
AND object_name = 'ODS_SERVER_DIRECTORY'
Possibly you have it set in the UTL_FILE_DIR parameter of init.ora (should not be done anymore..)
But its one possibility as to why utl_file would see the directory and dbms_lob would not.

ORA-29283: invalid file operation ORA-06512: at "SYS.UTL_FILE", line 536

Below is the code i use to extract data from a table to a flat file.
BEGIN
DECLARE
file_name VARCHAR2(50);
file_handle utl_file.file_type;
BEGIN
file_name := 'table.txt';
file_handle := utl_file.fopen('SEND',file_name,'W');
FOR rec in(
SELECT column 1
||'~'||column 2
||'~'||column 3 out_line
FROM table1)LOOP
UTL_FILE.PUT_LINE(file_handle,rec.out_line);
UTL_FILE.FFLUSH(file_handle);
END LOOP;
UTL_FILE.FCLOSE(file_handle);
END;
end;
This code is working fine in our development database but its throwing the below error if i execute in a new DB.
Error starting at line 1 in command:
BEGIN
DECLARE
file_name VARCHAR2(50);
file_handle utl_file.file_type;
BEGIN
file_name := 'table.txt';
file_handle := utl_file.fopen('SEND',file_name,'W');
FOR rec in(
SELECT column 1
||'~'||column 2
||'~'||column 3 out_line
FROM table1)LOOP
UTL_FILE.PUT_LINE(file_handle,rec.out_line);
UTL_FILE.FFLUSH(file_handle);
END LOOP;
UTL_FILE.FCLOSE(file_handle);
END;
end;
Error report:
ORA-29283: invalid file operation
ORA-06512: at "SYS.UTL_FILE", line 536
ORA-29283: invalid file operation
ORA-06512: at line 7
29283. 00000 - "invalid file operation"
*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.
Oracle directory 'SEND' points to some UNIX directory which has rights as
'rwxrwsr-x' (Octal 2775)
Oracle Version:11g
Please help me to solve this issue.
Guys please do let me know if you require more data from me to solve this question.
So, #Vivek has got the solution to the problem through a dialogue in the Comments rather than through an actual answer.
"The file is being created by user oracle just noticed this in our development database. i'm getting this error because, the directory where i try to create the file doesn't have write access for others and user oracle comes under others category. "
In the absence of an accepted answer to this question I proffer a link to an answer of mine on the topic of UTL_FILE.FOPEN(). Find it here.
P.S. I'm marking this answer Community Wiki, because it's not a proper answer to this question, just a redirect to somewhere else.
Assume file is already created in the predefined directory with name "table.txt"
1) change the ownership for file :
sudo chown username:username table.txt
2) change the mode of the file
sudo chmod 777 table.txt
Now, try it should work!
On Windows also check whether the file is not encrypted using EFS. I had the same problem untill I decrypted the file manualy.
I had been facing this problem for two days and I found that the directory you create in Oracle also needs to created first on your physical disk.
I didn't find this point mentioned anywhere i tried to look up the solution to this.
Example
If you created a directory, let's say, 'DB_DIR'.
CREATE OR REPLACE DIRECTORY DB_DIR AS 'E:\DB_WORKS';
Then you need to ensure that DB_WORKS exists in your E:\ drive and also file system level Read/Write permissions are available to the Oracle process.
My understanding of UTL_FILE from my experiences is given below for this kind of operation.
UTL_FILE is an object under SYS user. GRANT EXECUTE ON SYS.UTL_FILE TO
PUBLIC; needs to given while logged in as SYS. Otherwise, it will
give declaration error in procedure. Anyone can create a directory as
shown:- CREATE OR REPLACE DIRECTORY DB_DIR AS 'E:\DBWORKS'; But CREATE
DIRECTORY permission should be in place. This can be granted as
shown:- GRANT CREATE ALL DIRECTORY TO user; while logged in as SYS
user. However, if this needs to be used by another user, grants need
to be given to that user otherwise it will throw error. GRANT READ,
WRITE, EXECUTE ON DB_DIR TO user; while loggedin as the user who
created the directory. Then, compile your package. Before executing
the procedure, ensure that the Directory exists physically on your
Disk. Otherwise it will throw 'Invalid File Operation' error. (V.
IMPORTANT) Ensure that Filesystem level Read/Write permissions are in
place for the Oracle process. This is separate from the DB level
permissions granted.(V. IMPORTANT) Execute procedure. File should get
populated with the result set of your query.
The ORA-29283: invalid file operation is also raised on utl_file.put if there is an attempt to write line longer than max_linesize in text mode. max_linesize is optional 4th parameter of utl_file.fopen function defaulting to 1024.
(My case was dumping CSV from within Oracle in Docker into file in host directory mapped as Docker volume and I was misleaded by this error for pretty significat time - I seeked cause in filesystem rights or volume mapping between Docker and host, actually it was so stupid cause.)
UPDATE: another occurence of same exception also happened on utl_file.fopen. The database rejected to create file even if the file did not exist before. The directory in which the attempt of file creation happened was mapped on Docker volume. It started to work if the zero-sized file was created on host machine in advance. Attempt to create file from within container (touch /dir/file) failed though. Perhaps some docker issue - it disappeared after restarting Docker Desktop.
You need give permission by creating folder.
create or replace directory DINESH as '/home/oracle/DINESH/';
grant read, write
on directory DINESH
to public;
Simple PLSQL to open a file,
-- write two lines into the file,
-- and close the file
declare
fhandle utl_file.file_type;
begin
fhandle := utl_file.fopen(
'DINESH' -- File location
, 'test_file.txt' -- File name
, 'w' -- Open mode: w = write.
);
utl_file.put(fhandle, 'Hello world!'|| CHR(10));
utl_file.put(fhandle, 'Hello again!');
utl_file.fclose(fhandle);
exception
when others then
dbms_output.put_line('ERROR: ' || SQLCODE || ' - ' || SQLERRM);
raise;
end;
test_file.txt file created in /home/oracle/DINESH.

Resources