PL/SQL - UTL_FILE physical location of the file - oracle

I want to use UTL_FILE pkg to read data from a csv file, I already have the code for it, but where exactly I should place the file?
I know that I need to give the path with the UTL_FILE.FOPEN, and I can also create a directory, but I can't find it after creating, so I can't put the file into that directory.
Could you please help me?
Thank you!

Usually:
SYSuser creates directory (Oracle object which points to a filesystem directory which resides on the database server
SYS also grants read and/or read privileges on that directory (Oracle object) to user(s) who will be using it, i.e. storing files in there
in order to be able to manipulate files on the operating system level, DBA grants you appropriate privileges on that filesystem directory. Otherwise, you won't be able to put files in there (such as your CSV file) nor get files you created using UTL_FILE
When everything of above is done, then you'll be able to fully use the directory.
Therefore: if you're not a DBA, you're probably in vain "creating directory" (as you said) because - if you were, you'd already know how it works. I suggest you talk to your DBA.

Related

Open dbf file from oracle database

My instructor gave me a username and password and .dbf file and tell me to open it and try to retrieve with sqlplus and oracle database
I tried to open the dbf file from excel mysql and ms server but it i gave me an error
Speaking as a DBA: As Littlefoot stated, you can't just read a data file from an Oracle DB. At best they are proprietary binary file formats, assuming it isn't encrypted on top of that. Nor can you take a data file from one database instance and just plug it in to another database instance. You also can't import it to mySQL or any other database engine: as a stand-alone data file it can only be properly read by its original database installation (i.e. the specific database instance that created it).
Oracle has specific tools available to copy data and/or files from one database to another, but those would generally use the RMAN backup manager (used to make physical backups) or (more likely in your case) the Datapump "Transportable Tablespace" feature.
To restore it from an RMAN backup you would need a complete full backup of the entire source database instance: RMAN backup sets including all data files, redo logs (and perhaps archived logs), control files, parameter files, encryption keys,, and possibly more.
To restore a transportable tablespace dump you would need your own running Oracle database instance, the correct parameters to run the impdp import utility, and the assistance/cooperation of the DBA.
You need to confirm if the file you were given is such an export dump (though the .dbf file extension would suggest not), and how you are expected to access the data. You won't be able to just "open the file".
.DBF extension probably represents datafile; I don't think you can read it with any tool (at least, I don't know of any).
You should find an Oracle DBA who might try to help; in order to restore a database (which is contained in that file), they might need control file(s), redo log files and ... can't name what other files (I'm not a DBA).
Then, if everything goes OK, database might be started up so that you'd be able to connect to it using credentials you were given.

How to generate files on the client file system using oracle UTL_FILE package

I'd like to know, if is it possible to generate and retrieve the file using UTL_FILE package in oracle on the client side?
As far as I can tell, UTL_FILE operates with files on a server, stored in a directory accessible to Oracle. Therefore, you should CREATE DIRECTORY (oracle object) which points to a local directory (possibly, using UNC), grant required privileges (READ, WRITE most probably) and use that directory while working with UTL_FILE.

Oracle pl/sql Read the contents of a file from Physical Directory

My questions is as follows:
I am trying to create a script which will execute in sqlplus and what this script will do is that i will have a file in which you can write inside 1 name on every line. So i wanted to use an Associative Array in which i will read the contents of the file line by line (1 name on every line) and store every name in the array.
My problem is that i cannot use the UTL_FILE package which has a ready GET_LINE procedure to get the name of every line because it has to take as argument a "Logical Directory" of Oracle.
My issue is that i cannot make changes to the database like to create a new directory or use one of the default directories for the in file. I have to come to a solution in which i will read the contents of the file from a physical location.
I am kindly asking for some assistance in 2 fields. If you can please help me if you know any other package which can work on a physical location or if know any other way in which maybe i can call sqlplus (sqlplus username/pass #myscript) and give there as an argument the input file or like initialize the array from there.
Thank you in advance.
Any help would be highly appreciated
George
Clearly the best solution is to use UTL_FILE or external tables. So not being able to change the database is a major problem. If you don't have the permission to create a directory object and you cannot persuade a privileged user to do so on your behalf, then your question basically becomes
"How can I circumvent the security restrictions imposed on the database?"
Well, there are two possibilities.
If the DBAs have been careless enough to enable the UTL_FILE_DIR parameter in the init.ora file you may still be able to use UTL_FILE, by passing an absolute file path to FOPEN().
Alternatively, you can write a Java Stored Procedure to interact with files on the OS. This requires privileges to be granted through the Java security model. Find out more. Again, you will only have this without asking if you have lax DBAs.
Let me make it clear, both these "solutions" are grey hat. You really should try to get the necessary privileges through the proper channels. If the DBA team won't create a directory are you can use you need to escalate it to your boss.
If you cannot make any change to the database and the existing database does not provide you the privileges you need, you're out of luck.
UTL_FILE either requires the presence of an Oracle directory object that points to a physical directory on the database server that you have privileges on or that you are using a physical directory that you have been given access to via the deprecated UTL_FILE_DIR parameter. It appears that you are stating that neither of these is a viable option. If that is the case, you cannot use UTL_FILE.
You could also create an external table that would read data from a file. That would require that you could create the Oracle directory object and the external table. Again, it sounds like you are saying that is not an option so external tables are out.
You could write a Java (or .Net if you're on Windows) stored procedure that would read from the file. That would require that you create the procedure and that you grant the owner the necessary file system privileges. It sounds like you're saying this is also not an option so Java stored procedures are out.
If you move the file to the client machine, you could use SQL*Loader on the client machine to load the data into a table in the database. That would require that you create a physical table in the database, though, which it sounds like you are saying is not possible. So SQL*Loader is out.
If you can move the file to the client, you could obviously write a program in whatever language you would like to read the file and build whatever PL/SQL block you'd like. But that won't work for files stored on the database server barring some sort of very odd permissions grants where your client machine can somehow mount a directory on the server.
So we're back to where we started. Reading a file from the server's operating system requires privileges to be able to read that file. You seem to be saying that you do not have and cannot get those privileges. Therefore, you're saying that you can't do what you want. Whoever in your organization is asking you to implement this change needs to talk with whoever is preventing you from getting the privileges you need to do your job. One of them needs to give ground.

view contents of a directory on Database Server

I have access to the Oracle 10g database, but not the Unix server. I would like to verify that a file exists on the server. Is there a way to use the "ls" command to view the contents of a directory on the Unix server? I don't think this is possible, but I want to be sure.
Note the file is located in a "directory" defined in the dba_directories view and my Oracle user (myusername) has Oracle read / write access to the "directory". This can be verified by looking at the dba_tab_privs view.
You can't do it from pl/sql but you can do it with java. There is an ask tom article that contains the java code at this link.
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:439619916584

Make Directory Part Dynamic In Call To BFILENAME function In Oracle 10g

I am trying to open an existing physical file from file system in a procedure in Oracle 10g. The bfilename function requires a directory and path. I want to pass on the directory such as "c:\abc" directly to the procedure, i.e. I don't want to pass a directory object. The reason is, the directory can change, and I don't know how to create or replace directory inside a procedure (the command always returns error saying that variable is not allowed). I also am not sure about how it works in a multi-user environment, because a new directory is not local to the procedure.
When I run the command:
bfilename('c:\abc', 'myfile.txt');
it returns error that directory do not exists. I have checked by ending directory with "\" i.e. make it "c:\work\". I have also checked by capitalizing the directory name inside the procedure. If I make a directory object say DOCUMENTS and pass it to the bfilename, then its working.
bfilename('DOCUMENTS', 'myfile.txt');
Is there some way to make the directory part dynamic?
Update: I have tried to create directory from inside the procedure because this msdn article says that directory-object is must. The code is as follows:
EXECUTE IMMEDIATE 'CREATE OR REPLACE DIRECTORY WORKDIR AS ''c:\work''';
The procedure compiled successfully but when run gives following error:
Insufficient privileges.
I have only one user in my test database, this user has sysdba role. I have physical access to file through file system. The database-user can create directory through sqlplus.
Mark's answer solves your specific problem (you cannot use privileges gained through the SYSDBA role in procedures) but I want to discuss the underlying issues.
The relevant privilege is CREATE ANY DIRECTORY. All directory objects are owned by SYS, which is why this is a privilege which should be granted with caution.
Bear in mind that the second time you run your stored procedure it will fail. This is because the directory already exists. There is no ALTER DIRECTORY syntax. This means you need to drop and re-create the directory every time you want to change its path. Consequently you will also need to grant DROP ANY DIRECTORY to the user. Also, in a production environment you would need to re-issue the privileges granted on that directory to any other users who need it.
Why do Oracle make it so hard to work dynamically with directory objects? Because we shouldn't need to do it.
The OS directory structure is full of potential dangers for the database. Access to OS files from inside the database should be strictly controlled. That means we should specify particular directories for known purposes (DataPump, writing dumps and logfiles, importing CSV files, etc) and stick to them. Allowing procedures to change the paths of directories on the fly is a red flag for bad business process.
But, sometimes directory objects are a real pain. For instance, I once worked on a system which generated millions of files. In order to spread them across the operating system without blowing the unix inode limit we had a tree structure based on the last two digits of the header ID and the penultimate two digits of the header ID. Some like this:
$OUT_FILES/whatever/00/00
$OUT_FILES/whatever/00/01
...
$OUT_FILES/whatever/99/98
$OUT_FILES/whatever/99/99
That would have been ten thousand directory objects per feed. Which is a lot. So we used the (deprecated) UTL_FILE_DIR parameter. This parameter is deprecated for at least three reasons:
It is set in the INIT.ORA file and changing it requires a database re-start.
There is no granularity. Every database user has privileges on any OS directory in the list
The security is laxer because it allows wildcards.
Also, it means we have to specify the full OS path whenever we need to read or write to a directory, which is fragile and error-prone.
However, if you're working on a toy database this parameter might solve your headache. Find out more.
Just to be clear, I am not recommending that anybody use this parameter in a proper database unless they really understand the limitations. In most situations directory objects are safer and more convenient.
Try granting the 'CREATE DIRECTORY' privilege directly to the user (i.e., not through a role).
Something like:
grant create directory to the_user;
The reason for that is that roles are disabled inside of stored procedures. So, your user needs a direct grant explicitly granted.
Hope that helps.

Resources