Oracle
 sql >> Base de données >  >> RDS >> Oracle

Erreur SQL :ORA-14006 :nom de partition non valide

Vous ne pouvez pas partitionner une table existante comme ça. Cette instruction modifie la partition qui n'a pas encore été créée. Je ne connais pas la manière automatique de faire cette opération et je ne suis pas sûr que vous puissiez le faire.

Bien que j'aie fait cette chose plusieurs fois, mais avec des étapes manuelles. Procédez comme suit si vous ne trouvez pas de solution automatisée :

  1. Créez une table partitionnée nommée table_name_part avec vos clauses et toutes vos préférences.
  2. Insérez dans cette table partitionnée toutes les lignes de la table d'origine. Attention à la compression. Si vous avez une certaine compression sur la table (Basic ou HCC), vous devez utiliser + APPEND indice.
  3. Créez sur une table partitionnée vos contraintes et index à partir de la table d'origine.
  4. Renommer les tables et supprimer la table d'origine. Ne le laissez pas tomber jusqu'à ce que vous ayez fait quelques comptes sur eux.

J'ai vu que votre table a la possibilité de créer automatiquement une partition si elle n'existe pas. (NUMTOYMINTERVAL(1,'MONTH')) Vous devez donc créer votre table avec la première partition uniquement. Je suppose que vous avez ici beaucoup de données en lecture seule, vous n'aurez donc aucun problème de cohérence par rapport au mois dernier. Il y a probablement des données en lecture-écriture, vous devez donc faire plus attention au moment où vous souhaitez insérer des données dans une nouvelle table et changer de table.

J'espère vous aider. Autant que je sache, il pourrait y avoir un package nommé DBMS_REDEFINITION qui peut vous aider avec une version automatisée de mes étapes. Si vous avez besoin de plus de détails ou avez besoin d'aide sur ma méthode, n'hésitez pas.

MISE À JOUR : À partir d'Oracle 12c R2, vous pouvez convertir une table non partitionnée en table partitionnée avec votre méthode. Trouvez un lien ci-dessous. Maintenant, c'est un défi pour moi et j'essaie de convertir, mais je pense qu'il n'y a aucun moyen de faire cette conversion en ligne dans 12c R1.

https://oracle-base.com/articles/12c/online-conversion-of-a-non-partitioned-table-to-a-partitioned-table-12cr2

Solution

Je t'ai trouvé une solution. Ici, vous aurez toutes mes étapes que j'exécute pour convertir le tableau en ligne. :)

1. Create regular table and populate it.

CREATE TABLE SCOTT.tab_unpartitioned
(
    id              NUMBER,
    description     VARCHAR2 ( 50 ),
    created_date    DATE
);
INSERT INTO tab_unpartitioned
        SELECT LEVEL,
               'Description for ' || LEVEL,
               ADD_MONTHS ( TO_DATE ( '01-JAN-2017', 'DD-MON-YYYY' ),
                            -TRUNC ( DBMS_RANDOM.VALUE ( 1, 4 ) - 1 ) * 12 )
          FROM DUAL
    CONNECT BY LEVEL <= 10000;
COMMIT;

2. Create partitioned table with same structure.

--If you are on 11g create table with CREATE TABLE command but with different name. ex: tab_partitioned

CREATE TABLE SCOTT.tab_partitioned
(
    id              NUMBER,
    description     VARCHAR2 ( 50 ),
    created_date    DATE
)
PARTITION BY RANGE (created_date)
INTERVAL( NUMTOYMINTERVAL(1,'YEAR'))
(PARTITION part_2015 VALUES LESS THAN (TO_DATE ( '01-JAN-2016', 'DD-MON-YYYY' )),
 PARTITION part_2016 VALUES LESS THAN (TO_DATE ( '01-JAN-2017', 'DD-MON-YYYY' )),
 PARTITION part_2017 VALUES LESS THAN (TO_DATE ( '01-JAN-2018', 'DD-MON-YYYY' )));

--this is an alter command that works only in 12c.
ALTER TABLE tab_partitioned
    MODIFY
        PARTITION BY RANGE (created_date)
        (PARTITION part_2015 VALUES LESS THAN (TO_DATE ( '01-JAN-2016', 'DD-MON-YYYY' )),
         PARTITION part_2016 VALUES LESS THAN (TO_DATE ( '01-JAN-2017', 'DD-MON-YYYY' )),
         PARTITION part_2017 VALUES LESS THAN (TO_DATE ( '01-JAN-2018', 'DD-MON-YYYY' )));

3. Check if the table can be converted. This procedure should run without any error. 
Prerequisites: table should have an UNIQUE INDEX and a Primary Key constraint.

EXEC DBMS_REDEFINITION.CAN_REDEF_TABLE('SCOTT','TAB_UNPARTITIONED');

4. Run the following steps like I have done.

EXEC DBMS_REDEFINITION.START_REDEF_TABLE('SCOTT','TAB_UNPARTITIONED','TAB_PARTITIONED'); 
var num_errors varchar2(2000);
EXEC DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS('SCOTT','TAB_UNPARTITIONED','TAB_PARTITIONED', 1,TRUE,TRUE,TRUE,FALSE,:NUM_ERRORS,FALSE);
SQL> PRINT NUM_ERRORS -- Should return 0
EXEC DBMS_REDEFINITION.SYNC_INTERIM_TABLE('SCOTT','TAB_UNPARTITIONED','TAB_PARTITIONED');
EXEC DBMS_REDEFINITION.FINISH_REDEF_TABLE('SCOTT','TAB_UNPARTITIONED','TAB_PARTITIONED');

À la fin du script, vous verrez que la table d'origine est partitionnée.