web-dev-qa-db-ja.com

UTL_FILE.FOPEN()プロシージャがディレクトリのパスを受け入れませんか?

Vin1.txtという名前のc:\ドライブに保存されているファイルに書き込みをしようとしていますが、このエラーが表示されます。

> ERROR at line 1: ORA-29280: invalid
> directory path ORA-06512: at
> "SYS.UTL_FILE", line 18 ORA-06512: at
> "SYS.UTL_FILE", line 424 ORA-06512: at
> "SCOTT.SAL_STATUS", line 12 ORA-06512:
> at line 1

ここにコードがあります

  create or replace procedure sal_status
   (
    p_file_dir IN varchar2,
    p_filename IN varchar2)
     IS  
    v_filehandle utl_file.file_type;
    cursor emp Is
        select * from employees
        order by department_id;
    v_dep_no departments.department_id%TYPE;
     begin
         v_filehandle :=utl_file.fopen(p_file_dir,p_filename,'w');--Opening a file
         utl_file.putf(v_filehandle,'SALARY REPORT :GENERATED ON %s\n',SYSDATE);
         utl_file.new_line(v_filehandle);
         for v_emp_rec IN emp LOOP
            v_dep_no :=v_emp_rec.department_id;
            utl_file.putf(v_filehandle,'employee %s earns:s\n',v_emp_rec.last_name,v_emp_rec.salary);                    
         end loop;
        utl_file.put_line(v_filehandle,'***END OF REPORT***');
        UTL_FILE.fclose(v_filehandle);
     end sal_status;

execute sal_status('C:\','vin1.txt');--Executing
24
Vineet

Oracle 9i以降、UTL_FILEで使用するディレクトリを宣言する2つの方法があります。

古い方法は、INIT.ORAパラメータUTL_FILE_DIRを設定することです。変更を有効にするには、データベースを再起動する必要があります。この値は、他のPATH変数と同様にすることができます。ワイルドカードを受け入れます。このアプローチを使用すると、ディレクトリパスを渡すことを意味します...

UTL_FILE.FOPEN('c:\temp', 'vineet.txt', 'W');

別の方法は、ディレクトリオブジェクトを宣言することです。

create or replace directory temp_dir as 'C:\temp'
/

grant read, write on directory temp_dir to vineet
/

ディレクトリオブジェクトには正確なファイルパスが必要であり、ワイルドカードは使用できません。このアプローチでは、ディレクトリオブジェクト名を渡します...

UTL_FILE.FOPEN('TEMP_DIR', 'vineet.txt', 'W');

UTL_FILE_DIRは本質的に安全ではないため非推奨です。すべてのユーザーはパスで指定されたすべてのOSディレクトリにアクセスできますが、読み取りおよび書き込み権限は個々のユーザーに個別に付与できます。また、ディレクトリオブジェクトを使用すると、データベースをバウンスさせずにディレクトリを追加、削除、または変更できます。

どちらの場合でも、Oracle OSユーザーは読み取りおよび/または書き込み権限を持っている必要がありますOSディレクトリ上。明らかでない場合、これはデータベースサーバーからディレクトリが見える必要があるを意味します。したがって、ローカルPC上のディレクトリをリモートデータベースサーバーで実行されているプロセスに公開するために、どちらのアプローチも使用できません。ファイルは、データベースサーバーまたは共有ネットワークドライブにアップロードする必要があります。


Oracle OSユーザーがOSディレクトリに対する適切な特権を持っていない場合、またはデータベースで指定されたパスが実際のパスと一致しない場合、プログラムはこの例外を投げます。

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

このエラーのOERRテキストは非常に明確です。

29283 -  "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.
36
APC

また、ファイルのパスが実際のOracleサーバーマシン上にあり、ストアドプロシージャを呼び出す可能性のあるローカル開発マシン上にないことも忘れないでください。これはおそらく非常に明白ですが、覚えておくべきことです。

9
Josh P

ディレクトリを登録する をOracleに登録する必要があります。 fopenは、パスではなくディレクトリオブジェクトの名前を取ります。例えば:

(これらを実行するにはSYSとしてログインする必要がある場合があります)

CREATE DIRECTORY MY_DIR AS 'C:\';

GRANT READ ON DIRECTORY MY_DIR TO SCOTT;

次に、fopenの呼び出しでそれを参照できます。

execute sal_status('MY_DIR','vin1.txt');
4
Jeffrey Kemp

Utl_file.open(location、filename、mode)の場合、場所ではなくパスではなくディレクトリ名を指定する必要があります。 Example:DATA_FILE_DIRの場合、これはディレクトリ名であり、その特定のディレクトリ名のディレクトリパスをチェックアウトします。

1
sujini

ディレクトリ名では大文字と小文字が区別されるようです。私は同じ問題に直面しましたが、大文字でディレクトリ名を提供したとき、それは機能しました。

1
Shafqat Ali

DBAにinit.oraファイルを変更して、アクセスしたいディレクトリを「utl_file_dir」パラメータに追加する必要があります。 init.oraはデータベースの起動時にのみ読み込まれるため、データベースインスタンスを停止して再起動する必要があります。

次のクエリを実行すると、このパラメーターを表示できます(変更はできません)。

SELECT *
  FROM V$PARAMETER
  WHERE NAME = 'utl_file_dir'

共有してお楽しみください。

0
Bob Jarvis