テーブルスペースreportに属するパーティションテーブルがあります。代わりに、テーブルスペースに移動したいrecord。
1つの可能性は、テーブルを削除して新しいテーブルスペースに再作成することですが、移動後も存続する必要のあるデータがテーブルにあるため、これは私にとってオプションではありません。
まず、パーティションが実際にテーブルスペースレポートに属していることを確認します。
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を完全に機能させることができませんでした。
既存のパーティションをすべて新しいテーブルスペースに移動しても、新しいパーティションを作成するときに問題が発生します。新しいパーティションは引き続き古いテーブルスペースに作成されますレポート。新しい表領域に新しいパーティションが作成されるように変更するにはどうすればよいですかrecord?
無効になる可能性のあるインデックスも考慮する必要があります。これに加えてデフォルトのテーブルスペースをリセットすることについての質問をカバーするために、これが実装する必要のある完全なプロセスだと思います。
1)パーティションの移動(zürigschnäzletsの回答によるPL/SQLループ)
これらは、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;
)インデックスのデフォルトパーティションテーブルスペースを設定して、必要に応じて新しいインデックスパーティション(存在する場合)を作成します:
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を使用してステートメントを生成できます。単純なSQLを使用してaltertableステートメントを生成することにしました。
--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;
<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>
これがオプションの場合、最も簡単な方法はテーブルの名前を変更することです(ALTER TABLE requestLog RENAME TO requestLogTmp;
)、すべてのインデックスを含む同じテーブルを正しいテーブルスペースに作成し、古いテーブルからデータをコピーします。
INSERT INTO requestLog ( SELECT * FROM requestLogTmp )
すべてが稼働しているときは、古いテーブルを削除できます。