一、因前期TABLE的存儲TABLESPACE設計不合理,或者須要對某個TABLESPACE進行維護管理,須要將該TABLESPACE中的對象轉移, ORACLE提供了ALTER TABLE TABLE_NAME MOVE TABLESPACE NEW_TABLESPACE(須要有該表空間權限)的支持。sql
二、在MOVE TABLESPACE過程當中須要注意含LOB字段的表不能直接MOVE,以及分區表的MOVE,在MOVE TABLESPACE以後,對應表的 INDEX將會失效,須要重建。ide
三、爲此寫了一個PL/SQL程式進行批量MOVE(未通過嚴格的測試,請勿在生產庫上使用,不然後果請自行承擔) 測試
PL/SQL以下: spa
DECLARE v_sqltext1 VARCHAR2 (1000); v_sqltext2 VARCHAR2 (1000); v_sqltext3 VARCHAR2 (1000); v_sqltext4 VARCHAR2 (1000); v_sqltext5 VARCHAR2 (1000); v_sqltext6 VARCHAR2 (1000); v_sqltext7 VARCHAR2 (1000); CURSOR tabletype_cur IS SELECT * FROM dba_tables WHERE owner = 'SCOTT' AND tablespace_name = 'USERS'; v_table_str tabletype_cur%ROWTYPE; CURSOR lob_cur (lobtable VARCHAR2) IS SELECT * FROM dba_lobs WHERE table_name = lobtable; CURSOR index_cur (idx VARCHAR2) IS SELECT index_name FROM dba_indexes WHERE table_name = idx; CURSOR part_index_cur (partidx VARCHAR) IS SELECT index_name FROM dba_indexes WHERE table_name = partidx MINUS SELECT index_name FROM dba_part_indexes; BEGIN OPEN tabletype_cur; LOOP FETCH tabletype_cur INTO v_table_str; IF v_table_str.partitioned = 'NO' --是否爲分區表 THEN FOR movelob IN lob_cur (v_table_str.table_name) --是否含有LOB字段 LOOP v_sqltext1 := 'ALTER TABLE SCOTT.' || movelob.table_name || ' MOVE LOB(' || movelob.column_name || ') STORE AS ' || movelob.segment_name || ' (TABLESPACE TEST)'; EXECUTE IMMEDIATE v_sqltext1; --DBMS_OUTPUT.put_line (v_sqltext1); END LOOP; v_sqltext2 := 'ALTER TABLE SCOTT.' || v_table_str.table_name || ' MOVE TABLESPACE TEST'; --DBMS_OUTPUT.put_line (v_sqltext2); EXECUTE IMMEDIATE v_sqltext2; --移動普通表 FOR moveidx IN index_cur (v_table_str.table_name) --將移動以後表的對應INDEX重建 LOOP v_sqltext3 := 'ALTER INDEX SCOTT.' || moveidx.index_name || ' REBUILD ONLINE TABLESPACE TEST'; EXECUTE IMMEDIATE v_sqltext3; --DBMS_OUTPUT.put_line (v_sqltext3); END LOOP; END IF; IF v_table_str.partitioned = 'YES' THEN --分區表分區的移動,暫不考慮有子分區的狀況,若MOVE子分區將報ORA-14257 FOR part IN (SELECT partition_name FROM dba_tab_partitions WHERE subpartition_count = 0 AND table_name = v_table_str.table_name) LOOP v_sqltext4 := 'ALTER TABLE SCOTT.' || v_table_str.table_name || ' MOVE PARTITION ' || part.partition_name || 'TABLESPACE TEST'; EXECUTE IMMEDIATE v_sqltext4; --DBMS_OUTPUT.put_line (v_sqltext4); FOR movepartidx1 IN (SELECT index_name FROM dba_ind_partitions WHERE subpartition_count = 0 AND partition_name = part.partition_name) LOOP v_sqltext5 := 'ALTER INDEX ' || movepartidx1.index_name || ' REBUILD PARTITION ' || part.partition_name || ' TABLESPACE TEST'; EXECUTE IMMEDIATE v_sqltext5; --將移動以後分區表的分區INDEX重建 END LOOP; END LOOP; v_sqltext6 := 'ALTER TABLE SCOTT.' || v_table_str.table_name || 'MODIFY DEFAULT ATTRIBUTES TABLESPACE TEST'; EXECUTE IMMEDIATE v_sqltext6; --DBMS_OUTPUT.put_line (v_sqltext6); FOR movepartidx2 IN part_index_cur (v_table_str.table_name) --將移動以後分區表的全局INDEX重建 LOOP v_sqltext7 := 'ALTER INDEX SCOTT.' || movepartidx2.index_name || ' REBUILD ONLINE TABLESPACE TEST'; EXECUTE IMMEDIATE v_sqltext7; --DBMS_OUTPUT.put_line (v_sqltext7); END LOOP; END IF; END LOOP; CLOSE tabletype_cur; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.put_line (SQLERRM); END; /
總結:該PL/SQL主要是經過判斷一個用戶下的表是否爲分區表進行move,並根據該表的對象類型來作處理,存在過多的邏輯判斷,比較繁瑣, 且是根據表類型來進行的,有比較大的侷限性,後面考慮從須要move的tablespace方向出發,對tablespace上的對象分類進行move。如: A)先將該tablespace中的含LOB字段的表move,並重建索引。 B)以後將該tablespace中的分區表進行move,包含分區,子分區,並重建索引,包含全局索引,分區索引,含子分區索引。 C)在以後查看該tablespace中是否有LONG字段的表,有就進行處理。 D) 以後對剩下的普通表進行move,並重建索引,就可將整個tablespace中的對象move。 最後,對於move table的做用和影響請結合shrink table自行查詢。設計