2010-05-01 200 views
19

我想寫在一個文件存儲在c:\驅動器名爲vin1.txt 並得到這個錯誤。請建議!UTL_FILE.FOPEN()過程不接受目錄的路徑?

> 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 

回答

32

從Oracle 9i有有兩種方法或者聲明一個用於UTL_FILE的目錄。

舊的方法是設置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已被棄用的目錄對象名稱,因爲它本質上是不安全 - 所有用戶都可以訪問的路徑中指定的所有操作系統目錄,而讀取和寫入權限可以去分散授予個人用戶。另外,通過Directory對象,我們可以添加,刪除或更改目錄,而不會彈出數據庫。

在任一情況下,oracle OS用戶必須在OS目錄上具有讀取和/或寫入權限。如果不明顯,這意味着該目錄必須在數據庫服務器中可見。所以我們不能使用這兩種方法將本地PC上的目錄公開到在遠程數據庫服務器上運行的進程。文件必須上傳到數據庫服務器或共享網絡驅動器。


如果oracle 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. 
+0

你可以連接其他目錄嗎?例如:UTL_FILE.FOPEN('TEMP_DIR'||'/ otherFolder','vineet.txt','W');我想知道如果可能。 FTP服務器的路徑/ .../... / – delive 2017-10-25 12:39:34

0

你需要讓你的DBA修改init.ora文件,將要訪問的「UTL_FILE_DIR」參數的目錄。然後您的數據庫實例需要停止並重新啓動,因爲只有在啓動數據庫時纔會讀取init.ora。

您可以通過運行下面的查詢查看(但不能更改)這個參數:

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

分享和享受。

3

您需要使用Oracle的register the directory。 fopen採用目錄對象的名稱,而不是路徑。例如:

(您可能需要登錄爲SYS執行這些)

CREATE DIRECTORY MY_DIR AS 'C:\'; 

GRANT READ ON DIRECTORY MY_DIR TO SCOTT; 

然後,你可以參考它在調用的fopen:

execute sal_status('MY_DIR','vin1.txt'); 
+0

注意:此方法在較早版本的Oracle(我認爲是前9)中不可用,您可能需要設置utl_file_dir。我想 – 2010-05-02 07:57:00

5

也不要忘記,該文件的路徑是實際的Oracle服務器上,而不是任何LOCA l可能調用存儲過程的開發機器。這可能很明顯,但應該記住的東西。

1

對於utl_file.open(位置,文件名,模式),我們需要爲位置提供目錄名稱,但不提供路徑。例如:DATA_FILE_DIR,這是目錄名,並檢出該特定目錄名的目錄路徑。

0

目錄名稱似乎區分大小寫。我遇到了同樣的問題,但是當我提供大寫的目錄名稱時,它就起作用了。