您不能像这样对现有表进行分区。该语句正在修改尚未创建的分区。我不知道执行此操作的自动方法,并且我不确定您是否可以执行此操作。
虽然我已经做过很多次这件事,但都是手动步骤。如果找不到自动化解决方案,请执行以下操作:
- 使用您的子句和所有首选项创建名为 table_name_part 的分区表。
- 将原始表中的所有行插入到此分区表中。注意压缩。如果您对表进行了一些压缩(Basic 或 HCC),则必须使用+ APPEND hint.
- 在分区表上创建原始表的约束和索引。
- 重命名表并删除原始表。在您对它们有所了解之前,请勿丢弃它。
我看到您的表可以选择自动创建分区(如果它不存在)。 (NUMTOYMINTERVAL(1,'MONTH')) 因此,您必须仅使用第一个分区创建表。我假设您这里有很多只读数据,因此与上个月相比,您不会遇到任何一致性问题。可能有一些读写数据,所以当你想在新表中插入数据和切换表时,你必须更加小心。
希望对您有所帮助。据我所知,可能有一个名为 DBMS_REDEFINITION 的包可以帮助您完成我的步骤的自动化版本。如果您需要更多详细信息或需要有关我的方法的帮助,请不要犹豫。
UPDATE:从 Oracle 12c R2 开始,您可以使用您的方法将表从未分区表转换为分区表。找到下面的链接。现在这对我来说是一个挑战,我正在尝试转换,但我认为在 12c R1 中没有办法在线进行这种转换。
在以前的版本中,您可以使用以下命令对未分区表进行分区
以“几乎在线”的方式交换分区或 DBMS_REDEFINITION,
但这两种方法都需要多个步骤。 Oracle 数据库 12c 第 2 版
使将非分区表转换为分区表变得比以往更容易
分区表,只需要一个命令,无需停机。
https://oracle-base.com/articles/12c/online-conversion-of-a-non-partitioned-table-to-a-partitioned-table-12cr2 https://oracle-base.com/articles/12c/online-conversion-of-a-non-partitioned-table-to-a-partitioned-table-12cr2
Solution
我为你找到了解决方案。在这里,您将看到我在线转换表格时运行的所有步骤。 :)
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');
在脚本末尾,您将看到原始表已分区。