oracle 11g匯出空表

2021-07-04 12:42:24 字數 4154 閱讀 4886

oracle 11g 用exp命令匯出庫檔案備份時,發現只能匯出來一部分表而且不提示錯誤,之前找不到解決方案只能把沒匯出來的表重新建建立。後來發現是所有的空表都沒有匯出來。於是想好好查查,因為在以前的10g版本中沒有這樣的問題。

查資料發現oracle 11g中有個新特性:新增了乙個引數「deferred_segment_creation」含義是段延遲建立,預設是true。

具體是什麼意思呢?

如果這個引數設定為true,你新建了乙個表table1,並且沒有向其中插入資料,那麼這個表不會立即分配extent,也就是不佔資料空間,即表也不分配 segment 以節省空間,所以這些表也沒能匯出來。在系統表user_tables中也可以看到segment_treated的字段裡是「no」或者「yes」說明了某張表是否分配了segment。說白了是為了可以節省少量的空間。

用下面的sql語句查詢,可以發現沒有匯出的表其 segment_created 字段值都是 'no'。

select segment_created,table_name from user_tables where segment_created = 'no';

解決方法:

1、最原始最笨的辦法(不推薦):insert一行,再rollback或者刪除就產生segment了。

該方法是在在空表中插入資料,再刪除,則產生segment。匯出時則可匯出空表。

2、設定deferred_segment_creation 引數:

設定deferred_segment_creation 引數為false來禁用"段推遲建立"(也就是直接建立segment),無論是空表還是非空表,都分配segment。

在sqlplus中,執行如下命令:

sql>alter system set deferred_segment_creation=false;

檢視:sql>show parameter deferred_segment_creation;

注意:該值設定後只對後面新增的表產生作用,對之前建立的空表(已經存在的)不起作用,仍不能匯出。

並且要重新啟動資料庫,讓引數生效。

3、使用allocate extent,可以匯出之前已經存在的空表。

使用allocate extent可以為資料庫物件的每一張表分配extent(注意針對每一張表,就是說一張表需要一條sql**):

其語法如下:

-----------

allocate extent

-----------

可以針對資料表、索引、物化檢視等手工分配extent。

allocate extent使用樣例:

allocate extent

allocate extent(size integer [k | m])

allocate extent(datafile 'filename')

allocate extent(instance integer)  www.2cto.com

allocate extent(size integer [k | m]   datafile 'filename')

allocate extent(size integer [k | m]   instance integer)

針對資料表操作的完整語法如下:

-----------

alter table [schema.] table_name allocate extent [()]

-----------

故,需要構建如下樣子簡單的sql命令:

-----------

alter table tablename allocate extent

-----------

但要是每一張表寫一條語句的話太過麻煩,為了方便我們使用sql命令拼寫出每一張表的alter語句。

構建對空表分配空間的sql命令。

查詢當前使用者下的所有空表(乙個使用者最好對應乙個預設表空間)。命令如下:

sql>select table_name from user_tables where num_rows=0; 

根據上述查詢,可以構建針對空表分配空間的命令語句,如下:

sql>select 'alter table '||table_name||' allocate extent;' from user_tables where num_rows=0 or num_rows is null(注意:很多教程沒有這裡,這裡是有可能位空的)

上述**可產生批量的修改表extent的sql語句(有多少張空表就產生多少條),我們只需要將其生成的所有sql**全部執行,就可以給每一張已經存在的表來分配segment,就ok了。

最後:這時再用exp匯出就沒有問題了。

但是:資料庫本身的deferred_segment_creation屬性還是true,也是就是說如果再建立新錶的話,預設還是不分配segment的。所以還是需要更改deferred_segment_creation的引數,以便以後建立的新錶自動分配segment。

總結:

如果你的資料庫還沒有建立任何資料表,那麼直接修改deferred_segment_creation屬性,以後建立的表無論是不是為空都會自動分配segment,就不會出現導不出空表的情況。然而如果你的資料庫中已經有很多空表,並且需要匯出來,那麼光修改deferred_segment_creation屬性則沒有用的,因為它只對之後建立的表有作用。你需要給已存在的空表分配segment以便可以匯出存在的空表,就用到上面講的allocate extent方法,但此方法只針對已經存在的表的segment屬性,所以最好就是:先給已存在的空表分配segment,方便其可以直接匯出,然後設定deferred_segment_creation引數以便以後每張表無論是否為空都自動分配segment。

附錄

有關第三種方法給已經存在的空表分配segment,下面介紹一種生成指令碼來執行sql的方法。

sql>select 'alter table '||table_name||' allocate extent;' from user_tables where num_rows=0 or num_rows is null;

批量輸出上述生成的sql語句並寫入到乙個.sql的指令碼檔案中。

如: 1. 建立執行指令碼檔案:我建立乙個e:\sql_script.sql檔案。內容如下:

set heading off;

set echo off;

set feedback off;

set termout on;

spool e:\sql_allocate.sql;

select 'alter table '||table_name||' allocate extent;' from user_tables where num_rows=0 or num_rows is null;

spool off;

這個指令碼的作用就是建立乙個e:\sql_allocate.sql指令碼檔案,將select 'alter table '||table_name||' allocate extent;' from user_tables where num_rows=0 or num_rows is null的執行結果(就是給每張表生成segment的sql**)批量輸出,儲存到乙個e:\sql_allocate.sql的指令碼檔案中。

2. 執行e:\sql_script.sql檔案來生成「分配表空間的sql**」的指令碼檔案sql_allocate.sql。

命令如下:

sql>@ e:\sql_script.sql;  (也可寫乙個批處理檔案,命令如下:sqlplus 使用者名稱/密碼@資料庫 @e:\sql_script.sql)

執行完畢後,得到e:\sql_allocate.sql指令碼檔案(裡面是給所有空表分配segment的sql**)。 

開啟該檔案會看到,已經得到對所有空表分配空間的sql語句。

3. 執行e:\sql_allocate.sql檔案來對錶分配空間。

命令如下:sql>@ e:\sql_allocate.sql

執行完畢,表已更改。之前存在的空表已分配segment空間!

大功告成,此時執行exp命令,即可把包括空表在內的所有表,正常匯出。

**:

oracle11g匯出空表

該引數意思是當建立物件 如表 初始時沒有資料,是否立即建立segment。預設是true。這會導致在按使用者匯出時,沒有segment的物件不會匯出。首先執行下面的語句 select alter table table name allocate extent from user tables wh...

oracle11g 空表匯出

oracle11g的新特性,資料條數是0時不分配segment,所以就不能被匯出。解決方法 1插入一條資料 或者再刪除 浪費時間,有時幾百張表會累死的。2建立資料庫之前 使用 sql alter system set deferred segment creation false 調整再建表 這兩種...

oracle11g匯出空表

這意味著,當你建立乙個物件引數 如表 起初沒有資料。是否立即建立segment。預設值是true。這會導致使用者在匯出時,否segment該物件不出口。首先執行以下的語句 select alter table table name allocate extent from user tables w...