У меня есть разделенная таблица, которая принадлежит отчету о табличной области. Я хочу переместиться, это к табличной области записывает вместо этого.
Одна возможность состоит в том, чтобы отбросить таблицу и воссоздать ее в новой табличной области, но это не опция для меня, так как существуют данные в таблице, которая должна пережить перемещение.
Я запустил путем проверки, что разделы на самом деле принадлежат отчету о табличной области с:
SELECT * FROM user_tab_partitions WHERE table_name = 'REQUESTLOG';
Тогда я просто попробовал:
ALTER TABLE requestLog MOVE TABLESPACE record;
Но это дает мне, ошибочные РТЫ 145111 “не могут выполнить операцию на разделенном объекте”.
Тогда я узнал, что могу переместить отдельное использование разделов:
ALTER TABLE requestLog MOVE PARTITION "2009-12-29" TABLESPACE report;
Но с тех пор существует 60 разделов таблицы (на основе даты), и потому что мне, вероятно, придется сделать это для нескольких систем, я хотел бы циклично выполниться по всем именам раздела, перемещая каждого в новую табличную область. Я попробовал это, но не мог вполне заставить SQL работать.
Даже если я перемещаю все существующие разделы в новую табличную область, существует все еще проблема при создании новых разделов. Новые разделы все еще создаются в старом отчете о табличной области. Как я изменяюсь так, чтобы новые разделы были созданы в новой записи табличной области?
Вы должны учитывать индексы, которые могут быть недействительны - чтобы охватить вопрос о сбросе табличных пространств по умолчанию, в дополнение к этому, я думаю, что это полный процесс, который вы захотите реализовать:
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;
Если это опция, то самым простым способом может быть переименование таблицы ( ALTER TABLE requestLog
RENAME TO requestLogTmp;
), создайте одну и ту же таблицу со всеми индексами в правильном табличном пространстве и скопируйте данные из старой таблицы:
INSERT INTO requestLog ( SELECT * FROM requestLogTmp )
Когда все готово и работает, вы можете опустить старую таблицу.
.] Это можно сделать либо с помощью PL/SQL, либо сгенерировать операторы с помощью sql. Я решил сгенерировать операторы таблицы изменений с помощью простого 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';
]
[] Вы можете выполнить вывод из предыдущего утверждения. [
] [] У каждого пользователя есть табличное пространство по умолчанию. Новые объекты БД создаются в этом табличном пространстве по умолчанию, если при создании/изменении ничего больше не указано[
].