天天看點

Oracle Directory目錄的知識

在上一章介紹expdp/impdp時曾使用過directory這個概念,下面再簡單說明下directory的點點滴滴。

mos上對directory的解釋(266875.1):

(1)、基于服務端 vs 基于用戶端

directory變量指出了expdp導出資料泵或impdp導入資料泵将dump檔案、log檔案以及sql檔案(僅适用于impdp)寫到什麼路徑。

因為導出資料泵和導入資料泵都是基于服務端的,不是基于用戶端的,是以輸出檔案的路徑都是相對于服務端目錄的路徑。資料泵要求将目錄路徑作為一個目錄對象。一個目錄對象将檔案系統的一個目錄路徑映射為一個名稱。

(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平台

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将會使用。環境變量是在在運作導出和導入資料泵應用的用戶端系統中使用作業系統指令定義的,配置設定給基于用戶端環境變量的取值必須和基于服務端的目錄對象一緻,且必須首先在伺服器端建立。

目錄my_dir中建立dump檔案和my_dir_log中建立日志檔案的示例:

在使用expdp的用戶端機器上,設定環境變量:

-- 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 

注意環境變量data_dump_dir對應的目錄名稱是大小寫敏感的。設定錯誤的data_pump_dir環境變量會報錯,例如:data_pump_dir=my_dir:

ora-39087: directory name my_dir is invalid

5.4 如果之前三種情況都沒有建立目錄對象,作為一個具有權限的使用者(例如具有exp_full_database或imp_full_database角色),那麼資料泵試圖使用預設的基于伺服器端的目錄對象,data_pump_dir。了解資料泵不會建立data_pump_dir目錄對象是非常重要的。僅當授權使用者未使用任何之前提到的機制建立的目錄對象時,才會嘗試使用data_pump_dir。這個預設的目錄對象必須首先由dba建立。不要将這個和同名的基于用戶端的環境變量相混淆。

首先,清空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-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

或者這種特定場景下,使用者scott也可以有目錄data_pump_dir的讀和寫權限:

c:\> set data_pump_dir=data_pump_dir

實驗:

建立目錄:create directory utl_file_dir as ‘/oracle/backup‘;

向用目錄對象辨別的檔案寫内容:

sql> declare

  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

讀取使用目錄對象directory辨別的檔案内容:

  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  /

sql> /

此時沒有任何輸出,設定serveroutput:

sql>

set serveroutput on

列印檔案内容。

directory的目就在于可以讓我們在oracle中靈活地對檔案系統中的檔案進行操作。