Как переместить секционированную таблицу из одного табличного пространства в другое в Oracle 11g?

у меня есть секционированная таблица, которая принадлежит tablespace отчет. Я хочу переместить его в табличное пространство запись вместо.

одна из возможностей-удалить таблицу и воссоздать ее в новом табличном пространстве, но это не вариант для меня, так как в таблице есть данные, которые должны выжить при перемещении.

Я начал с проверки того, что разделы фактически принадлежат отчету табличного пространства с:

SELECT * FROM user_tab_partitions WHERE table_name = 'REQUESTLOG';

тогда я просто попробовал:

ALTER TABLE requestLog MOVE TABLESPACE record;

но это дает мне ошибку ORA-145111 "не удается выполнить операцию над секционированным объектом".

затем я узнал, что могу перемещать отдельные разделы, используя:

ALTER TABLE requestLog MOVE PARTITION "2009-12-29" TABLESPACE report;

но поскольку есть 60 разделов таблицы (на основе даты), и поскольку мне, возможно, придется сделать это для нескольких систем, я хотел бы перебрать все имена разделов, перемещая каждый в новое табличное пространство. Я попытался это сделать, но не смог заставить SQL работа.

даже если я перемещаю все существующие разделы в новое табличное пространство, все равно возникает проблема при создании новых разделов. Новые разделы по-прежнему создаются в старом табличном пространстве отчет. Как изменить, чтобы новые разделы создавались в новом табличном пространстве запись?

6 ответов


вы должны рассмотреть индексы, которые также могут быть признаны недействительными - чтобы покрыть ваш вопрос о сбросе табличных пространств по умолчанию в дополнение к этому, я думаю, что это полный процесс, который вы хотите реализовать:

1) перемещение разделов (цикл PL/SQL в соответствии с ответом zürigschnäzlets)

Это процедуры, которые я использую в анонимной оболочке блока, которая определяет a_tname, a_destTS, vTname и vTspName - они должны дать вам общее идея:

procedure mvTabPart (a_tname in varchar2, a_destTS in varchar2) is
cursor pCur(vTname varchar2, vTspName varchar2) is
  select table_name, partition_name
  from user_tab_partitions
  where table_name = vTname
      and tablespace_name not like vTspName
  order by partition_position desc;
begin
for pRow in pCur(a_tname, a_destTS) loop
 sqlStmnt := 'alter table '||pRow.table_name||
             ' move partition '||pRow.partition_name||
             ' tablespace '||a_destTS;
execute immediate sqlStmnt;
end loop;
end mvTabPart;

2) Установите табличное пространство раздела таблицы по умолчанию, чтобы там создавались новые разделы:

    procedure setDefTabPart (a_tname in varchar2, a_destTS in varchar2) is
    cursor tCur(vTname varchar2) is
      select table_name
      from user_part_tables
      where table_name = vTname;
    begin
    for tRow in tCur(a_tname) loop
     sqlStmnt := 'alter table '||tRow.table_name||
                 ' modify default attributes '||
                 ' tablespace '||a_destTS;
    execute immediate sqlStmnt;
    end loop;
end setDefNdxPart;

3) Установите табличное пространство раздела индекса по умолчанию, чтобы новые разделы индекса (если они есть) создавались там, где вы хотите:

procedure setDefNdxPart (a_tname in varchar2, a_destTS in varchar2) is
cursor iCur(vTname varchar2) is
  select index_name
  from user_part_indexes
  where index_name in (select index_name
             from user_indexes where table_name = vTname);
begin
for iRow in iCur(a_tname) loop
 sqlStmnt := 'alter index '||iRow.index_name||
             ' modify default attributes '||
             ' tablespace '||a_destTS;
execute immediate sqlStmnt;
end loop;

end setDefNdxPart;

4) перестроить любые секционированные индексы, которые нуждаются в перестроении и не находятся в нужном табличном пространстве:

procedure mvNdxPart (a_tname in varchar2, a_destTS in varchar2) is
cursor ndxCur(vTname varchar2, vTspName varchar2) is
select i.index_name index_name, ip.partition_name partition_name
  from user_ind_partitions ip, user_indexes i
  where i.index_name = ip.index_name
     and i.table_name = vTname
     and i.partitioned = 'YES'
     and (ip.tablespace_name not like vTspName or ip.status not like 'USABLE')
  order by index_name, partition_name ;
begin
for ndxRow in ndxCur(a_tname, a_destTS) loop
 sqlStmnt := 'alter index '||ndxRow.index_name||
             ' rebuild partition '||ndxRow.partition_name||
             ' tablespace '||a_destTS;
execute immediate sqlStmnt ;
end loop;
end mvNdxPart;

5) перестроить любой глобальный индексы

procedure mvNdx (a_tname in varchar2, a_destTS in varchar2) is
cursor ndxCur(vTname varchar2, vTspName varchar2) is
  select index_name
  from user_indexes
  where table_name = vTname
       and partitioned = 'NO'
       and (tablespace_name not like vTspName or status like 'UNUSABLE')
  order by index_name ;
begin
for ndxRow in ndxCur(a_tname, a_destTS) loop
 sqlStmnt := 'alter index '||ndxRow.index_name||
             ' rebuild tablespace '||a_destTS;
execute immediate sqlStmnt ;
end loop;
end mvNdx;

вы можете сделать это с помощью PL / SQL или создать операторы с sql. Я решил сгенерировать операторы alter table с помощью простого SQL:

--set linesize
set lines 100

--This Query generates the alter table statements:
SELECT 'ALTER TABLE '
       ||table_name
       ||' MOVE PARTITION '
       ||partition_name
       ||' TABLESPACE REPORT;'
FROM   all_tab_partitions
WHERE  table_name = 'requestLog'; 

вы можете выполнить вывод из предыдущего оператора.

каждый пользователь имеет табличное пространство по умолчанию. Новые объекты базы данных создаются в табличном пространстве по умолчанию, если при создании/изменении не указано ничего другого


самый простой способ перемещения данных в табличных пространствах:

перемещение всех нераздельных таблиц

SELECT 'ALTER TABLE '||OWNER|| '.'||TABLE_NAME||' MOVE TABLESPACE ARCHIVE;'  
FROM ALL_tables 
where owner = 'owner_name' 
and temporary != 'Y'
and partitioned != 'YES';

секционированных таблиц

SELECT 'ALTER TABLE '|| TABLE_OWNER||'.'||TABLE_NAME||' MOVE PARTITION ' ||  PARTITION_NAME||  ' TABLESPACE ARCHIVE;'  FROM ALL_tab_partitions 
WHERE TABLE_OWNER = 'owner_name' 
AND table_NAME NOT LIKE 'BIN$%';

несекционированные индексы

SELECT 'ALTER INDEX '|| OWNER||'.'||OBJECT_NAME ||' REBUILD TABLESPACE ARCHIVE ;' 
FROM ALL_OBJECTS 
WHERE OBJECT_TYPE ='INDEX'
AND OWNER = 'owner_name';

секционированных индексов

SELECT  'ALTER INDEX '||I.INDEX_NAME||'REBUILD PARITION'|| S.PARTITION_NAME || ' TABLESPACE  ARCHIVE ' 
                   FROM  DBA_INDEXES I,    DBA_SEGMENTS S
                  WHERE  I.INDEX_NAME = S.SEGMENT_NAME
                    AND I.INDEX_TYPE IN ('NORMAL', 'BITMAP')
                    AND I.OWNER = 'owner_name'; 

--MOVING ALL TABLES FROM USER  
BEGIN
  FOR i IN (
    SELECT * FROM ALL_tables where owner = :owner 
      and (tablespace_name is null or tablespace_name != :tbs)
      and temporary != 'Y'
      and partitioned != 'YES'
    ) LOOP
    EXECUTE IMMEDIATE 'ALTER TABLE '  || i.table_name || ' MOVE TABLESPACE ' || :tbs;
  END LOOP; 
END;


--MOVING ALL INDEX

 BEGIN
  FOR i IN (
    SELECT * FROM ALL_tab_partitions 
    WHERE table_owner = :owner and tablespace_name != :tbs
  ) LOOP
    EXECUTE IMMEDIATE 'ALTER TABLE ' 
      || i.table_name || ' MOVE PARTITION '
      || i.partition_name ||' TABLESPACE '|| :tbs;
  END LOOP;
END;


--MOVING ALL PARTATION TABLES FROM USER  

BEGIN
  FOR i IN (
    SELECT * FROM ALL_tables where owner = :owner and partitioned = 'YES'
  ) LOOP
    EXECUTE IMMEDIATE 'ALTER TABLE '
      || i.table_name || ' MODIFY DEFAULT ATTRIBUTES TABLESPACE ' || :tbs;
  END LOOP;
END;

Если это опция, самым простым способом может быть переименование таблицы (ALTER TABLE requestLog RENAME TO requestLogTmp;), создайте одну и ту же таблицу со всеми индексами в правильном табличном пространстве и скопируйте данные из старой таблицы:

INSERT INTO requestLog ( SELECT * FROM requestLogTmp )

когда все работает и работает, вы можете удалить старую таблицу.


    <pre><code>PROCEDURE P_ALTER_TABLE_SPACE(
        A_TNAME         IN VARCHAR2,
        A_DESTTS        IN VARCHAR2,
        A_PATITION_TYPE IN VARCHAR2)
    IS
      CURSOR PCUR(VTNAME VARCHAR2, VTSPNAME VARCHAR2)
      IS
        SELECT TABLE_NAME,
          PARTITION_NAME
        FROM USER_TAB_PARTITIONS
        WHERE TABLE_NAME = VTNAME
        AND TABLESPACE_NAME NOT LIKE VTSPNAME
        ORDER BY PARTITION_POSITION DESC;

      CURSOR PCURR(VTNAME VARCHAR2, VTSPNAME VARCHAR2)
      IS
        SELECT TABLE_NAME,
          SUBPARTITION_NAME
        FROM USER_TAB_SUBPARTITIONS
        WHERE TABLE_NAME = VTNAME
        AND TABLESPACE_NAME NOT LIKE VTSPNAME
        ORDER BY SUBPARTITION_POSITION DESC;
    BEGIN
      IF A_PATITION_TYPE = 'PARTITION' THEN
        FOR PROW IN PCUR(A_TNAME, A_DESTTS)
        LOOP
          SQLSTMNT := 'ALTER TABLE '||PROW.TABLE_NAME|| ' MOVE PARTITION '||PROW.PARTITION_NAME|| ' TABLESPACE '||A_DESTTS;
          EXECUTE IMMEDIATE SQLSTMNT;
        END LOOP;
      ELSE
        FOR PROW IN PCURR(A_TNAME, A_DESTTS)
        LOOP
          SQLSTMNT := 'ALTER TABLE '||PROW.TABLE_NAME|| ' MOVE SUBPARTITION '||PROW.SUBPARTITION_NAME|| ' TABLESPACE '||A_DESTTS;
          EXECUTE IMMEDIATE SQLSTMNT;
        END LOOP;
      END IF;
    END P_ALTER_TABLE_SPACE;
    </code></pre>