Writing a file to a custom created directory on Oracle Amazon-RDS - oracle

I can connect to the database via sqlplus
sqlplus stepdba/<password>#steprds.<rds-hash-here>.<region>.rds.amazonaws.com:1521/STEP
and I am trying to write to a file.
According to AmazonRDS documentation regarding Oracle, create directory must be done with rdsadmin.rdsadmin_util.create_directory('MY_DIR'); which I have done.
To write to a file, I do the following:
DECLARE
fileHandler UTL_FILE.FILE_TYPE;
BEGIN
fileHandler := UTL_FILE.FOPEN('MY_DIR', 'test.txt', 'W');
UTL_FILE.PUTF(fileHandler, 'Writing TO a file\n');
UTL_FILE.FCLOSE(fileHandler);
END;
/
Which result in an error:
ERROR at line 1:
ORA-29283: invalid file operation
ORA-06512: at "SYS.UTL_FILE", line 536
ORA-29283: invalid file operation
ORA-06512: at line 4
If I try to write to an Oracle provided directory DATA_PUMP_DIR, the above snippet executes correctly and the file is written.
The privileges to the two directories are the same
select grantee, privilege from dba_tab_privs where table_name='DATA_PUMP_DIR' and grantee = 'STEPDBA';
select grantee, privilege from dba_tab_privs where table_name='MY_DIR' and grantee = 'STEPDBA';
In the Amazon-RDS case, we can not manipulate the file/directory permissions on the OS level.
I seem to be missing something, any hint would be appreciated.

Hi I had exactly the same problem. Solved it by using higher version of Oracle software: Oracle SE One 11.2.0.4.v4
One that was causing the problems was Oracle SE One 11.2.0.4.v3

Related

ORA-29283: invalid file operation when calling utl_file.fopen on Windows server 2016

Most of the answers I've seen are for Linux. Windows permissions have an element of black magic about them. This is Windows Server 2016.
I created the d:\data\transfer\sirius\ directory on the Oracle database server.
As SYSDBA I do the following:
create or replace directory SIRIUS_DIR as 'd:\data\transfer\sirius\';
grant read,write on directory SIRIUS_DIR to SIRIUS;
Then on another server, in a SQL*Plus session as the SIRIUS user, I run:
DECLARE myFile utl_file.file_type;
BEGIN
myFile := utl_file.fopen('SIRIUS_DIR ', 'random.txt', 'w', 32000);
END;
/
Which gives:
ERROR at line 1:
ORA-29283: invalid file operation
ORA-06512: at "SYS.UTL_FILE", line 536
ORA-29283: invalid file operation
ORA-06512: at "SYS.UTL_FILE", line 41
ORA-06512: at "SYS.UTL_FILE", line 478
ORA-06512: at line 3
How to proceed?
Figured it out. You need to grant full access to the ORA_INSTALL group to the directory in question on the database. According to the Oracle configuration docs:
The ORA_INSTALL group contains all the Oracle Home Users for all
Oracle homes on the server.
Thanks to this kindly blogger for his solution.

Oracle DATAPUMP import failed

I am currently trying to import a database using DBMS_DATAPUMP in PL/SQL using the following script.
DECLARE
h1 NUMBER;
BEGIN
h1 := DBMS_DATAPUMP.OPEN('IMPORT', 'FULL', NULL, DBMS_SCHEDULER.generate_job_name, 'LATEST');
DBMS_DATAPUMP.ADD_FILE(handle => h1, filename => 'EXAMPLE6.DMP', directory => 'DUMP');
DBMS_DATAPUMP.START_JOB(h1);
dbms_datapump.detach(h1);
END;
/
Everytime I execute this code, I get the following error message.
ERROR in line 1:
ORA-39001: invalid argument value
ORA-06512: in "SYS.DBMS_SYS_ERROR", line 79
ORA-06512: in "SYS.DBMS_DATAPUMP", line 4929
ORA-06512: in "SYS.DBMS_DATAPUMP", line 5180
ORA-06512: in line 5
I already googled the error, but the answer mostly consisted of checking if the directory was already created and if the user had read and write access to the directory.
I also tried the impdp tool just as an experiment, to see if I could execute imports that way.
impdp pdb2 directory="DUMP" dumpfile="EXAMPLE6.DMP"
Based on the user I am executing impdp as, I get different error messages.
As a user with all privileges granted:
ORA-39001: invalid argument value
ORA-39000: bad dump file specification
ORA-39155: error expanding dump file name "C:\Users\...\EXAMPLE6.DMP"
ORA-48128: opening of a symbolic link is disallowed
As the sysdba user:
ORA-39002: invalid operation
ORA-39070: unable to open the log file
ORA-39087: directory name DUMP is invalid
As I already said, the directory does exist on my drive, I created the directory called DUMP in Oracle and granted read and write access to my user.
All help would be appreciated and I would be happy to clarify if I wrote something confusing!
Edit:
Output of select directory_name, directory_path from dba_directories;
DIRECTORY_NAME
--------------------------------------------------------------------------------
DIRECTORY_PATH
--------------------------------------------------------------------------------
DUMP
C:\Users\Nemanja\Desktop\oraclePLS
I forgot to mention, that the Oracle service has complete access to the specified Windows directory.

UTL_FILE.FOPEN() procedure not accepting path for directory in oracle 12c database?

Below code is working perfectly in oracle 10g database
DECLARE
g_file_handle UTL_FILE.FILE_TYPE;
g_dir varchar2(100);
BEGIN
g_dir := Scamp_Utils.getutlfiledir;
DBMS_OUTPUT.PUT_LINE (g_dir);
g_file_handle := UTL_FILE.FOPEN (g_dir, 'qwe.txt', 'W', 32767);
UTL_FILE.PUT_LINE (g_file_handle, 'BEGINDATA');
UTL_FILE.FCLOSE (g_file_handle);
COMMIT;
END;
/
Here Scamp_Utils.getutlfiledir is a function which returns the path defined in utl_file_dir.
But same code doesn't work in oracle 12c database. I'm getting an error:
ORA-29280: invalid directory path
ORA-06512: at "SYS.UTL_FILE", line 41
ORA-06512: at "SYS.UTL_FILE", line 478
ORA-06512: at line 7
I have already provided rwx permission to all at the OS level. I'm still getting this error. I can use the oracle logical directory but I don't want to change code. What should I do here?
Oracle has two option to declare a directory for utl_file.
1. Change `utl_file_dir='/appl/flstadm/utl_files/wlsbb01'` in INIT.ORA file and restart DB. This solution is not recommended and deprecated.
2. Create directory object in DB.
CREATE OR REPLACE DIRECTORY my_dir AS '/appl/flstadm/utl_files/wlsbb01';
GRANT read, write ON DIRECTORY my_dir TO your_user;
g_file_handle := UTL_FILE.FOPEN ('my_dir', 'qwe.txt', 'W', 32767);
Have you added your path to init.ora?

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

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