在上一章介紹expdp/impdp時曾使用過DIRECTORY這個概念,以下再簡單說明下DIRECTORY的點點滴滴。
MOS上對DIRECTORY的解釋(266875.1):
(1)、基於服務端 vs 基於client
DIRECTORY變量指出了expdp導出數據泵或impdp導入數據泵將dump文件、log文件以及SQL文件(僅適用於impdp)寫到什么路徑。
由於導出數據泵和導入數據泵都是基於服務端的,不是基於client的,因此輸出文件的路徑都是相對於服務端文件夾的路徑。數據泵要求將文件夾路徑作為一個文件夾對象。一個文件夾對象將文件系統的一個文件夾路徑映射為一個名稱。
(2)、怎樣創建一個文件夾對象?
為了創建文件夾,必須具有DBA角色或者賦予了CREATE ANY DIRECTORY權限。
演示樣例:
Window平台
CONNECT system/manager
CREATE OR REPLACE DIRECTORY my_dir as 'D:\DataPump';
CREATE OR REPLACE DIRECTORY my_logdir as 'E:\logs';
GRANT read, write ON DIRECTORY my_dir TO scott;
GRANT read, write ON DIRECTORY my_logdir TO scott;
Unix平台
CONNECT system/manager
GRANT CREATE ANY DIRECTORY TO scott;
CONNECT scott/tiger
CREATE OR REPLACE DIRECTORY my_dir as '/usr/DataPump';
CREATE OR REPLACE DIRECTORY my_logdir as '/usr/logs';
假設普通用戶被賦予了CREATE ANY DIRECTORY權限,那么用戶就自己主動具備文件夾的READ和WRITE權限。
注意:CREATE DIRECTORY語句不會創建磁盤的真實文件夾。假設文件夾是無效的,數據泵作業會報錯:
ORA-39002: invalid operation
ORA-39070: Unable to open the log file.
ORA-29283: invalid file operation
ORA-06512: at "SYS.UTL_FILE", line 475
ORA-29283: invalid file operation
(3)、怎樣查詢可用的文件夾?
能夠使用例如以下SQL查詢具有READ和WRITE權限的文件夾:
SET lines 80
COL grantee FORMAT a20
COL privilege FORMAT a10
SELECT directory_name, grantee, privilege
FROM user_tab_privs t, all_directories d
WHERE t.table_name(+)=d.directory_name
ORDER BY 1,2,3;
DIRECTORY_NAME GRANTEE PRIVILEGE
------------------------------ -------------------- ----------
DATA_PUMP_DIR EXP_FULL_DATABASE READ
DATA_PUMP_DIR EXP_FULL_DATABASE WRITE
DATA_PUMP_DIR IMP_FULL_DATABASE READ
DATA_PUMP_DIR IMP_FULL_DATABASE WRITE
MY_DIR SCOTT READ
MY_DIR SCOTT WRITE
MY_DIR SYSTEM READ
MY_DIR SYSTEM WRITE
MY_LOGDIR SCOTT READ
MY_LOGDIR SCOTT WRITE
MY_LOGDIR SYSTEM READ
MY_LOGDIR SYSTEM WRITE
...
(4)、須要的操作系統權限。
對文件夾對象的READ或WRITE權限只表示Oracle將會替你讀或寫這個文件。你並沒有訪問Oracle以外文件的權限,除非你具備合適的操作系統權限。
(5)、數據泵怎樣決定文件的路徑
5.1 假設文件夾對象是文件標示符的一部分,那么文件夾對象指定的路徑就須要使用。在文件夾MY_DIR創建dump文件的演示樣例:
> expdp scott/tiger DUMPFILE=my_dir:expdp_s.dmp NOLOGFILE=Y
5.2 假設文件夾對象不代表一個文件,那么就須要使用DIRECTORY變量命名的文件夾對象。文件夾MY_DIR中創建dump文件。文件夾MY_DIR_LOG中創建日志文件的演示樣例:
> expdp scott/tiger DIRECTORY=my_dir DUMPFILE=expdp_s.dmp \
LOGFILE=my_logdir:expdp_s.log
5.3 假設沒有明白文件夾對象,也沒有以DIRECTORY變量命名的文件夾對象。那么環境變量DATA_PUMP_DIR將會使用。環境變量是在在執行導出和導入數據泵應用的client系統中使用操作系統命令定義的,分配給基於client環境變量的取值必須和基於服務端的文件夾對象一致,且必須首先在server端建立。
文件夾MY_DIR中創建dump文件和MY_DIR_LOG中創建日志文件的演示樣例:
在使用expdp的client機器上,設定環境變量:
-- On windows, place all expdp parameters on one single line:
C:\> set DATA_PUMP_DIR=MY_DIR
C:\> expdp scott/tiger@my_db_alias DUMPFILE=expdp_s.dmp
LOGFILE=my_logdir:expdp_s.log
注意環境變量DATA_DUMP_DIR相應的文件夾名稱是大寫和小寫敏感的。
設定錯誤的DATA_PUMP_DIR環境變量會報錯。比如:DATA_PUMP_DIR=My_Dir:
ORA-39002: invalid operation
ORA-39070: Unable to open the log file.
ORA-39087: directory name My_Dir is invalid
5.4 假設之前三種情況都沒有創建文件夾對象,作為一個具有權限的用戶(比如具有EXP_FULL_DATABASE或IMP_FULL_DATABASE角色),那么數據泵試圖使用默認的基於server端的文件夾對象,DATA_PUMP_DIR。理解數據泵不會創建DATA_PUMP_DIR文件夾對象是很重要的。僅當授權用戶未使用不論什么之前提到的機制創建的文件夾對象時。才會嘗試使用DATA_PUMP_DIR。
這個默認的文件夾對象必須首先由DBA創建。不要將這個和同名的基於client的環境變量相混淆。
首先,清空DATA_PUMP_DIR環境變量:
C:\> set DATA_PUMP_DIR=
創建DATA_PUMP_DIR的文件夾:
CONNECT SYSTEM/MANAGER
CREATE OR REPLACE DIRECTORY data_pump_dir AS 'D:\DataPump';
GRANT read, write ON DIRECTORY data_pump_dir TO scott;
-- On windows, place all expdp parameters on one single line:
C:\> expdp system/manager@my_db_alias DUMPFILE=expdp_s.dmp
LOGFILE=expdp_s.log SCHEMAS=scott
假設SCOTT用戶不是授權用戶,不能使用默認的DATA_PUMP_DIR。
ORA-39002: invalid operation
ORA-39070: Unable to open the log file.
ORA-39145: directory object parameter must be specified and non-null
用戶SCOTT的解決方法:如上面5.3。SCOTT能夠環境變量設置DATA_PUMP_DIR為MY_DIR:
-- On windows, place all expdp parameters on one single line:
C:\> set DATA_PUMP_DIR=MY_DIR
C:\> expdp scott/tiger@my_db_alias DUMPFILE=expdp_s.dmp
LOGFILE=expdp_s.log SCHEMAS=scott
或者這樣的特定場景下。用戶SCOTT也能夠有文件夾DATA_PUMP_DIR的讀和寫權限:
-- On windows, place all expdp parameters on one single line:
C:\> set DATA_PUMP_DIR=DATA_PUMP_DIR
C:\> expdp scott/tiger@my_db_alias DUMPFILE=expdp_s.dmp
LOGFILE=expdp_s.log SCHEMAS=scott
實驗:
創建文件夾:CREATE DIRECTORY UTL_FILE_DIR AS '/oracle/backup';
向用文件夾對象標識的文件寫內容:
2 fhandle utl_file.file_type;
3 begin
4 fhandle := utl_file.fopen('UTL_FILE_DIR', 'example.txt', 'w');
5 utl_file.put_line(fhandle, 'test write one');
6 utl_file.put_line(fhandle, 'test write two');
7 utl_file.fclose(fhandle);
8 end;
9 /
PL/SQL procedure successfully completed.
SQL> !
ora10g@vm-vmw4131-t$ more /oracle/backup/example.txt
test write one
test write two
2 fhandle utl_file.file_type;
3 fp_buffer varchar2(4000);
4 begin
5 fhandle := utl_file.fopen('UTL_FILE_DIR', 'example.txt', 'R');
6 utl_file.get_line(fhandle, fp_buffer);
7 dbms_output.put_line(fp_buffer);
8 utl_file.get_line(fhandle, fp_buffer);
9 dbms_output.put_line(fp_buffer);
10 utl_file.fclose(fhandle);
11 end;
12 /
PL/SQL procedure successfully completed.
SQL> /
PL/SQL procedure successfully completed.
此時沒有不論什么輸出。設置serveroutput:
SQL> /
test write one
test write two
PL/SQL procedure successfully completed.
打印文件內容。