ORACLE11g“空表”無法導出的深入分析

    我覺得將空表無法導出描述爲沒有使用過的表無法導出應該更確切一些。oralce11g爲了節省存儲空間,新建表的時候默認是不分配segment的。既然segment都沒有,就不用談exp了。但是oracle還是預留了系統參數DEFERRED_SEGMENT_CREATION(延遲創建segment)。這個參數,默認是true。我們可以將他改成false。這樣的話,再創建表的時候就會立即分配segment了。但是修改參數之前創建的沒使用過的表還是不會立即分配segment的。如果想分配segment,可以在表中插入一條數據,再刪除。也可以使用alter table XXX allocate extent。這樣就會創建segment了。再使用exp就會導出沒使用過的表。

    理解了oracle11g無法導出的不是空表而是沒使用過的表之後,我們就不難看出,網絡上很多人給出的查詢批量修改無法導出的表的語句是錯的。

    比較常見的有:

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

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

    我們來分析一下這兩個select語句。num_rows = 0表示表裏的記錄數爲0,但是這個數值是通過數據庫執行analyze table之後寫入的,而數據庫執行analyze table是有條件的,所以num_rows並不能實時的表示表裏面的記錄數。num_rows = 0, 對應表裏的記錄數可能會大於0。新創建的從未使用過的表在數據庫沒有執行analyze table之前,num_rows是NULL,只有執行了analyze table之後num_rows纔會變成0。而且如果執行analyze table  tablename delete statistics把表的統計信息刪除,該表在user_tables中對應的num_rows會變成NULL。

    也就是說num_rows =0 並不能說明這個表沒有被使用過,也並不能說明這個表裏沒有記錄。num_rows is null也不能說明這個表沒有被使用過。

    理解了表無法導出是因爲沒有分配segment之後,我們就可以寫出真正的查詢批量修改無法導出的表的語句了

select 'alter table '||table_name||' allocate extent;' from user_tables where tablespace_name = 'PORTAL_HIS' and not exists(select 1 from dba_segments where segment_type ='TABLE' and tablespace_name =user_tables.tablespace_name and dba_segments.segment_name = user_tables.table_name);

    錯誤理解了“空表”無法導出,才寫出了錯誤的select語句。只有真正弄明白了問題的原因,才能寫出正確的應對方法。

發佈了43 篇原創文章 · 獲贊 30 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章