Oracle
 sql >> Datenbank >  >> RDS >> Oracle

SQL-Fehler:ORA-14006:Ungültiger Partitionsname

Sie können eine vorhandene Tabelle nicht so partitionieren. Diese Anweisung ändert die Partition, die noch nicht erstellt wurde. Ich weiß nicht, wie diese Operation automatisch durchgeführt wird, und ich bin nicht sicher, ob Sie dies tun können.

Obwohl ich diese Sache viele Male gemacht habe, aber mit manuellen Schritten. Gehen Sie wie folgt vor, wenn Sie keine automatisierte Lösung finden:

  1. Erstellen Sie eine partitionierte Tabelle namens Tabellenname_Teil mit Ihren Klauseln und all Ihren Einstellungen.
  2. In diese partitionierte Tabelle alle Zeilen aus der Originaltabelle einfügen. Auf Kompression achten. Wenn Sie eine gewisse Komprimierung auf der Tabelle haben (Basic oder HCC), müssen Sie + APPEND verwenden Hinweis.
  3. Erstellen Sie auf einer partitionierten Tabelle Ihre Beschränkungen und Indizes aus der Originaltabelle.
  4. Benennen Sie die Tabellen um und löschen Sie die ursprüngliche Tabelle. Lassen Sie es nicht fallen, bis Sie einige Zählungen gemacht haben.

Ich habe gesehen, dass Ihre Tabelle die Option hat, eine Partition automatisch zu erstellen, wenn sie nicht existiert. (NUMTOYMINTERVAL(1,'MONTH')) Sie müssen also Ihre Tabelle nur mit der ersten Partition erstellen. Ich gehe davon aus, dass Sie hier viele schreibgeschützte Daten haben, sodass Sie keine Probleme mit der Konsistenz anstelle des letzten Monats haben werden. Wahrscheinlich gibt es einige Read-Write-Daten, also müssen Sie vorsichtiger sein, wenn Sie Daten in eine neue Tabelle einfügen und Tabellen wechseln möchten.

Ich hoffe, Ihnen zu helfen. Soweit ich weiß, gibt es möglicherweise ein Paket namens DBMS_REDEFINITION, das Ihnen bei einer automatisierten Version meiner Schritte helfen kann. Wenn Sie weitere Details benötigen oder Hilfe zu meiner Methode benötigen, zögern Sie bitte nicht.

AKTUALISIERUNG: Ab Oracle 12c R2 können Sie mit Ihrer Methode eine Tabelle von einer unpartitionierten in eine partitionierte konvertieren. Finden Sie unten einen Link. Das ist jetzt eine Herausforderung für mich und ich versuche zu konvertieren, aber ich denke, dass es keine Möglichkeit gibt, diese Konvertierung online in 12c R1 durchzuführen.

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

Lösung

Ich habe eine Lösung für dich gefunden. Hier finden Sie alle meine Schritte, die ich ausführe, um die Tabelle online zu konvertieren. :)

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

Am Ende des Skripts sehen Sie, dass die ursprüngliche Tabelle partitioniert ist.