批量move table(分區/非分區)的plsql

一、因前期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自行查詢。設計

相關文章
相關標籤/搜索