Come ci si sposta una tabella partizionata da un tablespace all'altro in Oracle 11g?

StackOverflow https://stackoverflow.com/questions/1998627

  •  22-09-2019
  •  | 
  •  

Domanda

Ho una tabella partizionata che appartiene a spazio tabella . Voglio spostarlo spazio tabella record , invece.

Una possibilità è quella di eliminare la tabella e ricrearla nel nuovo spazio tabelle, ma che non è un'opzione per me, poiché non vi sono dati nella tabella che ha bisogno per sopravvivere in movimento.

Ho iniziato controllando che le partizioni in realtà appartengono al rapporto spazio tabella con:

SELECT * FROM user_tab_partitions WHERE table_name = 'REQUESTLOG';

Poi ho appena provato:

ALTER TABLE requestLog MOVE TABLESPACE record;

Ma che mi dà errore ORA-145.111 “non può eseguire l'operazione su un oggetto partizionato”.

Poi ho scoperto che posso spostare singole partizioni utilizzando:

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

Ma dal momento che ci sono 60 partizioni della tabella (in base alla data), e perché io possa avere a che fare questo per diversi sistemi, vorrei un ciclo su tutti i nomi delle partizioni, spostando ogni al nuovo spazio tabelle. Ho provato, ma non riuscivo a ottenere lo SQL per funzionare.

Anche se mi trasferisco tutte le partizioni esistenti per il nuovo spazio tabelle, c'è ancora un problema durante la creazione di nuove partizioni. Le nuove partizioni sono ancora creati nel vecchio spazio tabella . Come faccio a cambiare in modo che le nuove partizioni sono state create nel nuovo spazio tabella record

È stato utile?

Soluzione

Si deve prendere in considerazione indici che può essere invalidata, come pure - per coprire le tue domande su reimpostare le tabelle predefinite oltre a questo, credo che questo è il processo completo che si desidera implementare:

1) Spostare le partizioni (un ciclo di PL / SQL come per ogni risposta zürigschnäzlets')

Si tratta di procedure che uso all'interno di un involucro di blocco anonimo che definisce a_tname, a_destTS, vTname e vTspName - dovrebbero offrirti l'idea generale:

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) Imposta tabella delle partizioni di default tablespace così nuove partizioni vengono create c'è:

    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) tablespace Impostare indice partizione di default in modo nuove partizioni di indice (se presenti) sono creati dove vuoi:

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) ricostruire gli indici partizionati che hanno bisogno di ricostruzione e non sono nello spazio tabelle desiderata:

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) Ricostruire gli indici globali

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;

Altri suggerimenti

È possibile farlo con PL / SQL o generare le dichiarazioni con SQL. Ho deciso per generare le istruzioni ALTER TABLE con semplice 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'; 

È possibile eseguire l'uscita dalla dichiarazione precedente.

Ogni utente ha uno spazio tabella predefinita. I nuovi oggetti di database vengono creati in quel tabelle predefinito se non altro è specificato sulla creazione / modifica

Il modo più semplice per spostare i dati all'interno di tabelle:

Spostare tutte le tabelle non partizionate

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

Le tabelle partizionate

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$%';

indici non partizionati

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

indici partizionati

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;

Se questa è un'opzione, il modo più semplice potrebbe essere quella di rinominare la tabella (ALTER TABLE requestLog RENAME TO requestLogTmp;), creare la stessa tabella con tutti gli indici nello spazio tabelle corretta e copiare i dati dal vecchio tavolo:

INSERT INTO requestLog ( SELECT * FROM requestLogTmp )

Quando tutto è installato e funzionante, è possibile eliminare la vecchia tabella.

    <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>
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top