Oracle 11g Realease 2(11.2.0.1)中,在匯出空表的時候,會報錯。查了一下原因,原來,該版本中做了一項最佳化,在建表的時候,不會分配儲存空間,只有在第一次insert資料的時候,才會分配儲存空間。這在系統中有很多空表時,能節省大量的儲存空間。但是如果系統只有少量的空間時,就沒什麼必要。這項最佳化還會引起配額錯誤(Quota Errors),可參考這裡。這個問題在11.2.0.2中得到了修複。
為此,oracle提供了一個deferred_segment_creation參數來進行配置,這個參數預設值為true。所以在建立表時如果沒有把這個參數指定為false,那麼建立之後,又沒有添加任何資料,在使用exp匯出時就會出錯。來看官方文檔解釋:
Property |
Description |
Parameter type |
Boolean |
Default value |
true |
Modifiable |
ALTER SESSION, ALTER SYSTEM |
Range of values |
true | false |
Basic |
No |
DEFERRED_SEGMENT_CREATION specifies the semantics of deferredsegment creation. If set to true, then segments for non-partitioned tables and their dependent objects (LOBs, indexes) will not be created untilthe first row is inserted into the table.
Before creating a set of tables, if it is known that asignificant number of them will not be populated, then consider setting thisparameter to true. This saves disk space and minimizes install time.
指定段延遲建立,如果設定成true,那麼非分區表和依賴它的對象(LOB,索引)將不分配儲存空間,直到往表中插入第一條資料時才分配。
在建立表之前,如果知道不會往裡面寫入資料,那可心考慮把這個參數設定成true。這樣可以節省儲存空間並減少表建立時間。
好,知道了原因,就好辦了。來看解決辦法:
1、最傻X的方法就是往表中寫一條資料,然後刪除或rollback掉,再匯出就沒問題了。但是這有個問題,如果有很多的表,那太費時間了。那就用第二種方法。
2、通過修改deferred_segment_creation參數。
查看該參數的值:
SQL> showparameter deferred_segment_creation;
NAME TYPE VALUE
------------------------------------ -----------------------------------------
deferred_segment_creation boolean TRUE
設定該參數:
alter system set deferred_segment_creation = false;
設定該參數的文法如下:
set deferred_segment_creation = [TRUE | FALSE]
也可在建立表的時候指定,文法如下:
segment creation { IMMEDIATE | DEFERRED }
這樣設定之後,以後再建立表時,就會分配segment了。但是之前建立的表還不沒有分配。還需要強制給之前的表分配空間。
alter table <tablename> allocate extent
由於表有可能有很多,所以可使用下面方法來批量修改:
select'altertable' ||table_name || ' allocate extent;'
from user_tables
where num_rows =0;
然後匯出查詢結果,再把執行這個匯出的sql語句。OK了。
相關閱讀:Oracle 11g R2 用exp無法匯出空表解決方案