Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Erro SQL:ORA-14006:nome de partição inválido


Você não pode particionar uma tabela existente assim. Essa instrução está modificando a partição que ainda não foi criada. Não conheço a maneira automática de fazer essa operação e não tenho certeza de que você possa fazê-lo.

Embora eu tenha feito isso muitas vezes, mas com etapas manuais. Faça o seguinte se não conseguir encontrar uma solução automatizada:
  1. Crie uma tabela particionada chamada table_name_part com suas cláusulas e todas as suas preferências.
  2. Insira nesta tabela particionada todas as linhas da tabela original. Preste atenção à compressão. Se você tem alguma compressão na tabela (Basic ou HCC) você tem que usar + APPEND dica.
  3. Crie na tabela particionada suas restrições e índices da tabela original.
  4. Renomeie as tabelas e elimine a tabela original. Não deixe cair até que você faça algumas contas com eles.

Vi que sua tabela tem a opção de auto-criar partição caso ela não exista. (NUMTOYMINTERVAL(1,'MONTH')) Então você tem que criar sua tabela apenas com a primeira partição. Eu suponho que você tenha aqui muitos dados somente leitura, então você não terá nenhum problema com consistência em vez do mês passado. Provavelmente existem alguns dados de leitura e escrita, então você deve ter mais cuidado com o momento em que deseja inserir dados em uma nova tabela e alternar entre tabelas.

Espero ajudá-lo. Até onde eu sei, pode haver um pacote chamado DBMS_REDEFINITION que pode ajudá-lo com uma versão automatizada dos meus passos. Se você precisar de mais detalhes ou precisar de ajuda no meu método, não hesite.

ATUALIZAÇÃO: No Oracle 12c R2, você pode converter uma tabela não particionada para particionada com seu método. Encontre um link abaixo. Agora isso é um desafio para mim e estou tentando converter, mas acho que não tem como fazer essa conversão online em 12c R1.

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

Solução

Encontrei uma solução para você. Aqui você terá todos os meus passos que executo para converter tabela online. :)
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');

No final do script você verá que a tabela original está particionada.