web-dev-qa-db-fra.com

Comment déplacer une table partitionnée d'un espace de table vers un autre dans Oracle 11g?

J'ai une table partitionnée qui appartient à tablespace report . Je veux le déplacer vers le tablespace record à la place.

Une possibilité consiste à supprimer la table et à la recréer dans le nouvel espace de table, mais ce n'est pas une option pour moi, car il y a des données dans la table qui doivent survivre au déplacement.

J'ai commencé par vérifier que les partitions appartiennent bien au rapport de tablespace avec:

SELECT * FROM user_tab_partitions WHERE table_name = 'REQUESTLOG';

Alors j'ai juste essayé:

ALTER TABLE requestLog MOVE TABLESPACE record;

Mais cela me donne l'erreur ORA-145111 "impossible d'effectuer l'opération sur un objet partitionné".

Ensuite, j'ai découvert que je pouvais déplacer des partitions individuelles en utilisant:

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

Mais comme il y a 60 partitions de la table (basées sur la date) et que je devrais le faire pour plusieurs systèmes, je voudrais parcourir tous les noms de partitions, en les déplaçant chacune vers le nouvel espace de table. J’ai essayé, mais je n’ai pas pu faire fonctionner le code SQL.

Même si je déplace toutes les partitions existantes vers le nouvel espace de table, il reste un problème lors de la création de nouvelles partitions. Les nouvelles partitions sont toujours créées dans l'ancien espace de table report . Comment puis-je changer pour que de nouvelles partitions soient créées dans le nouvel espace de table record ?

9
Henrik Warne

Vous devez également prendre en compte les index susceptibles d'être invalidés. Pour répondre à votre question sur la réinitialisation des espaces de table par défaut, je pense qu'il s'agit du processus complet que vous souhaitez implémenter:

1) Déplacer des partitions (une boucle PL/SQL selon la réponse de zürigschnäzlets)

Ce sont des procédures que j'utilise dans un wrapper de bloc anonyme qui définit a_tname, a_destTS, vTname et vTspName - elles devraient vous donner une idée générale:

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) Définissez le tablespace de partition par défaut de table afin que les nouvelles partitions y soient créées:

    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) Définissez l'espace de table de partition par défaut d'index afin que les nouvelles partitions d'index (le cas échéant) soient créées à l'emplacement souhaité:

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) reconstruisez tous les index partitionnés nécessitant une reconstruction et qui ne sont pas dans le tablespace souhaité:

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) Reconstruisez tous les index globaux

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;
22
dpbradley

Vous pouvez le faire avec PL/SQL ou générer les instructions avec SQL. J'ai décidé de générer les instructions alter table avec du SQL simple:

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

Vous pouvez exécuter la sortie de l'instruction précédente.

Chaque utilisateur a un espace de table par défaut. Les nouveaux objets de base de données sont créés dans cet espace de table par défaut si rien d'autre n'est spécifié lors de la création/modification

9
Thomas Aregger

Le moyen le plus simple de déplacer les données dans les espaces de table:

Déplacement de toutes les tables non partitionnées

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

Tables partitionnées

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

Index non partitionnés

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

Index partitionnés

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'; 
3
Imran
--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;
1
Imran
    <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>
0
Vinay

S'il s'agit d'une option, le moyen le plus simple consiste à renommer la table (ALTER TABLE requestLog RENAME TO requestLogTmp;), à créer la même table avec tous les index dans l'espace de table approprié et à copier les données de l'ancienne table:

INSERT INTO requestLog ( SELECT * FROM requestLogTmp )

Lorsque tout est opérationnel, vous pouvez supprimer l'ancienne table.

0
Peter Lang