Avatar of dplinnane
dplinnane
Flag for United States of America asked on

UTl_FILE invalid directory path error

/* Formatted on 2005/01/25 19:45 (Formatter Plus v4.8.5) */
Not sure what is wrong with this?
Thx in advance using oracle 9i

ORA-29280: invalid directory path
ORA-06512: at "SYS.UTL_FILE", line 18
ORA-06512: at "SYS.UTL_FILE", line 424
ORA-06512: at "ADMIN_QA.WRITE_FILE", line 5
ORA-06512: at line 3

CREATE OR REPLACE PROCEDURE write_file
IS
   l_file   UTL_FILE.file_type;
BEGIN
   l_file := UTL_FILE.fopen ('/tmp/outputfile/', 'testqa2_ora_14032_test1_binds_single_process.trc', 'w');
   UTL_FILE.put_line (l_file, 'this is a test');

   IF UTL_FILE.is_open (l_file)
   THEN
      UTL_FILE.fclose (l_file);
   END IF;
END;


Oracle Database

Avatar of undefined
Last Comment
manish14

8/22/2022 - Mon
jaramill

You need to have your DBA specify the directory you want to write to in the UTL_FILE_DIR variable that is set by the DBA.
alexnuijten

Or you can use this query to see the directories (if you have rights to the v$parameter view)

select value
from v$parameter
where name = 'utl_file_dir'
/


BTW: Especially with UTL_FILE, it's important to have an exception block. At least to close the File. If you omit this, the file will remain open (and locked) for the duration of your session.
Another point is the exception UTL_FILE can raise. These are in the "user-reserved" ranges (-20000 thru -20999) If you simply reraise you get a user-defined exception. (except for the one you encountered, it was added as a regular exception in 9i)
SOLUTION
bochgoch

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.
Mark Geerlings

For utl_file to work, the directory has to be "approved" first.  With Oracle9i, you (or your DBA) can do this either with:
1. a directory object that is created via SQL*Plus
2. a UTL_FILE_DIR entry in your spfile (or init*.ora file).

Older versions of Oracle only supported the UTL_FILE_DIR approach, but this is less flexible, since it can only be changed by shutting down and restarting the instance.  With Oracle9i, it is much better to create directories via SQL*Plus.

Here is an example of a "create directory..." command from our system (on Linux):
CREATE OR REPLACE DIRECTORY LOG AS '/var/ora_logs';
grant read, write on log to public;

Note that when you use these directory names (like: LOG) with utl_file, they must be specified in upper case.
Experts Exchange is like having an extremely knowledgeable team sitting and waiting for your call. Couldn't do my job half as well as I do without it!
James Murphy
dplinnane

ASKER
With oracle 9i no need to set  UTL_FILE_DIR.

The following executes successfully but no directory created.

SQL> exec admin_qa.test_dir('outputfile');
v_dyn_sql_grant grant create any directory to ADMIN_QA v_dyn_sql_dir create or
replace directory outputfile_admin_qa as '/tmp/outputfile_admin_qa' dir path  as
'/tmp/outputfile_admin_qa'

PL/SQL procedure successfully completed.

CREATE OR REPLACE PROCEDURE test_dir (p_user_dir_nm IN VARCHAR2 := NULL)
IS
   v_dyn_sql_dir      VARCHAR2 (200);
   v_dyn_sql_grant    VARCHAR2 (200);
   v_dyn_sql_revoke   VARCHAR2 (200);
   v_user_dir         VARCHAR2 (200);
   v_user             VARCHAR2 (50);
   v_default_dir      VARCHAR2 (100)  := 'tmp';
   v_path             VARCHAR2 (200);
BEGIN
   SELECT USER
     INTO v_user
     FROM DUAL;

   IF (p_user_dir_nm IS NULL)
   THEN
      v_user_dir := 'outputfile_' || v_user;
   ELSE
      v_user_dir := p_user_dir_nm || '_' || v_user;
   END IF;

   v_user_dir := LOWER (v_user_dir);
   v_path := ' as ''/' || v_default_dir || '/' || v_user_dir || '''';
   v_dyn_sql_grant := 'grant create any directory to ' || v_user;
   v_dyn_sql_revoke := 'revoke create any directory from  ' || v_user;
   v_dyn_sql_dir := 'create or replace directory '||v_user_dir ||'' ||v_path;
   
DBMS_OUTPUT.put_line ('v_dyn_sql_grant '|| v_dyn_sql_grant || ' v_dyn_sql_dir ' || v_dyn_sql_dir|| ' dir path ' || v_path);

   EXECUTE IMMEDIATE (v_dyn_sql_grant);
   EXECUTE IMMEDIATE (v_dyn_sql_dir);
   EXECUTE IMMEDIATE (v_dyn_sql_revoke);
 
END;

Mark Geerlings

So, is your problem solved, or do you still have a question?
dplinnane

ASKER
When I do select * from all_directories I see
OWNER  Name                               Path
SYS       OUTPUTFILE_ADMIN_QA    /tmp/outputfile_admin_qa

But I can not see it when I logon to unix and browse to tmp directory, why is that?

How can I test it by creating a file in it and writing to it.
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
alexnuijten

According to the documentation, you can't create a "physical" directory this way.

Docs:
"You must also create a corresponding operating system directory for file storage. Your system or database administrator must ensure that the operating system directory has the correct read and write permissions for Oracle processes."

Alex
dplinnane

ASKER
I have tried this and get error
ORA-29289: directory access denied
ORA-06512: at "SYS.UTL_FILE", line 18
ORA-06512: at "SYS.UTL_FILE", line 424
ORA-06512: at "ADMIN_QA.WRITE_FILE", line 9
ORA-06512: at line 3


CREATE OR REPLACE PROCEDURE write_file (p_user_dir_nm IN VARCHAR2 :=NULL)
IS
   log_handle          UTL_FILE.FILE_TYPE;
   log_file            VARCHAR2 (200);
   log_line            VARCHAR2 (32767);

BEGIN
   log_file := 'test_' || TO_CHAR (SYSDATE, 'YYYYMMDDHH24MISS') || '.txt';
   log_handle := UTL_FILE.FOPEN ('OUTPUTFILE_ADMIN_QA', log_file, 'w');
   --DBMS_OUTPUT.put_line ('user ' || v_user || ' dir path ' || v_path );
   UTL_FILE.put_line (log_handle, 'this is a test');

   IF UTL_FILE.is_open (log_handle)
   THEN
      UTL_FILE.fclose (log_handle);
   END IF;
END;
/
alexnuijten

Did you create this path: /tmp/outputfile_admin_qa  on the database server?

Alex
All of life is about relationships, and EE has made a viirtual community a real community. It lifts everyone's boat
William Peck
Mark Geerlings

You have to use operating system tools to create the physical directory (or folder) first, then you can use the "create directory..." command in Oracle to make this physical directory available to PL\SQL.  Also, remember that the "Oracle" user needs operating system privileges on this folder.  That is the "oracle" user account in unix that runs the database, *not* the logon account in Oracle that will run the procedure.
dplinnane

ASKER
I created directory  outputfile_admin_qa under tmp and did chmod 777 still get same error
Do I need to  login as oracle and then create the directory.
SOLUTION
alexnuijten

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
ASKER CERTIFIED SOLUTION
jrb1

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
dplinnane

ASKER
Problem was missing slash
VERY IMPORTANT make SURE SLASH is before tmp create or replace directory OUTPUTFILE_ADMIN_QA as '/tmp/outputfile_admin_qa'

File is created but 'this is a test' is not written to file?



CREATE OR REPLACE PROCEDURE write_file (p_user_dir_nm IN VARCHAR2 := NULL)
IS
/*
VERY IMPORTANT make SURE SLASH is before tmp create or replace directory OUTPUTFILE_ADMIN_QA as '/tmp/outputfile_admin_qa'
*/
   log_handle   UTL_FILE.file_type;
   log_file     VARCHAR2 (200);
   log_line     VARCHAR2 (32767);
BEGIN
   log_file := 'test_' || TO_CHAR (SYSDATE, 'YYYYMMDDHH24MISS') || '.txt';
   log_handle := UTL_FILE.fopen ('OUTPUTFILE_ADMIN_QA', log_file, 'w');
   UTL_FILE.put_line (log_handle, 'this is a test');

   IF UTL_FILE.is_open (log_handle)
   THEN
      UTL_FILE.fclose (log_handle);
   END IF;
END;
/
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
alexnuijten

I'm stumped.... it looks fine, it should work...

Sometimes, it takes some time for the procedure to comlete it's task. Even when it says procedure sucessfully completed, it may still be "working" on the file.
How long did you wait to check the contents of the file?

Alex
SOLUTION
Mark Geerlings

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
jrb1

can you simplify and run as simple PL/SQL script?

declare
   log_handle   UTL_FILE.file_type;
BEGIN
   log_handle := UTL_FILE.fopen ('OUTPUTFILE_ADMIN_QA', 'test.txt', 'w');
   UTL_FILE.put_line (log_handle, 'this is a test');
   IF UTL_FILE.is_open (log_handle) THEN
      UTL_FILE.fclose (log_handle);
   END IF;
END;
jrb1

Any update?  500 points just sitting around....
I started with Experts Exchange in 2004 and it's been a mainstay of my professional computing life since. It helped me launch a career as a programmer / Oracle data analyst
William Peck
manish14

might be corresponding directory object does not exist. If not then create a corresponding
           directory object with the CREATE DIRECTORY command