Skip to Main Content
  • Questions
  • Usage and limitations on PART_NAME parameter in DBMS_REDEFINITION APIs

Breadcrumb

Question and Answer

Chris Saxon

Thanks for the question, Narendra.

Asked: January 21, 2023 - 1:10 am UTC

Last updated: March 06, 2026 - 2:18 pm UTC

Version: 19.16

Viewed 1000+ times

You Asked

Hello Connor/Chris,

Hope you are doing well.
Recently, I came to know about the PART_NAME parameter for multiple APIs of DBMS_REDEFINITION package from the documentation. However, I could not find much about what kind of changes are permitted (and prevented) at partition level, either in the documentation or in any MOS notes.
The documentation states below
part_name
Name of the partition being redefined. If redefining only a single partition of a table, specify the partition name in this parameter. NULL implies the entire table is being redefined. Can take a comma-delimited list of partition names to be redefined.

This lead me to believe that I might be able to leverage this feature to perform a large update of a partitioned table column but with one partition at a time using DBMS_REDEFINITION. However, this does not appear to work and fails with error during START_REDEF_TABLE API call.
Would you be able to help in shedding more light on what is the purpose of PART_NAME parameter in DBMS_REDEFINITION APIs?

Below is my set up to reproduce the issue

DROP TABLE TBL_DATEPART PURGE;
DROP TABLE TBL_TSPART PURGE;

CREATE TABLE TBL_DATEPART 
(
  OBJECT_ID NUMBER NOT NULL 
, OWNER VARCHAR2(50) NOT NULL 
, OBJECT_TYPE VARCHAR2(50) NOT NULL 
, OBJECT_NAME VARCHAR2(200) NOT NULL 
, CREATED DATE NOT NULL 
, LAST_DDL_TIME DATE NOT NULL 
, CONSTRAINT TBL_DATEPART_PK PRIMARY KEY(OBJECT_ID) ENABLE 
) 
PARTITION BY RANGE (LAST_DDL_TIME) 
(
  PARTITION Y2019 VALUES LESS THAN (TO_DATE('01-JAN-2020','DD-MON-YYYY'))  
, PARTITION Y2020 VALUES LESS THAN (TO_DATE('01-JAN-2021','DD-MON-YYYY'))  
, PARTITION Y2021 VALUES LESS THAN (TO_DATE('01-JAN-2022','DD-MON-YYYY'))  
, PARTITION YMAX VALUES LESS THAN (MAXVALUE)  
);

insert into TBL_DATEPART (object_id, owner, object_type, object_name, created, last_ddl_time)
select object_id, owner, object_type, object_name, created, last_ddl_time
from dba_objects
where last_ddl_time is not null ;

commit; 

ALTER TABLE TBL_DATEPART ADD last_ddl_ts TIMESTAMP ;

CREATE TABLE TBL_TSPART 
(
  OBJECT_ID NUMBER 
, OWNER VARCHAR2(50) 
, OBJECT_TYPE VARCHAR2(50) 
, OBJECT_NAME VARCHAR2(200) 
, CREATED DATE
, LAST_DDL_TIME DATE
, LAST_DDL_TS TIMESTAMP
) 
PARTITION BY RANGE (LAST_DDL_TIME) 
(
  PARTITION Y2019 VALUES LESS THAN (TO_TIMESTAMP('01-JAN-2020','DD-MON-YYYY'))  
, PARTITION Y2020 VALUES LESS THAN (TO_TIMESTAMP('01-JAN-2021','DD-MON-YYYY'))  
, PARTITION Y2021 VALUES LESS THAN (TO_TIMESTAMP('01-JAN-2022','DD-MON-YYYY'))  
, PARTITION YMAX VALUES LESS THAN (MAXVALUE)  
);

BEGIN
DBMS_REDEFINITION.CAN_REDEF_TABLE(uname => 'NP', tname => 'TBL_DATEPART', options_flag => DBMS_REDEFINITION.CONS_USE_ROWID);
END;
/

BEGIN 
-- Below fails. My objective is to be able to update the value of newly added column based on an existing column.  
DBMS_REDEFINITION.START_REDEF_TABLE(uname => 'NP', orig_table => 'TBL_DATEPART', int_table => 'TBL_TSPART', col_mapping => 'OBJECT_ID OBJECT_ID, OWNER OWNER, OBJECT_TYPE OBJECT_TYPE, OBJECT_NAME OBJECT_NAME, CREATED CREATED, LAST_DDL_TIME LAST_DDL_TIME, to_timestamp(LAST_DDL_TIME) LAST_DDL_TS', options_flag => dbms_redefinition.cons_use_rowid, part_name => 'Y2019');
-- Below works where I do not specify PART_NAME parameter.
-- DBMS_REDEFINITION.START_REDEF_TABLE(uname => 'NP', orig_table => 'TBL_DATEPART', int_table => 'TBL_TSPART', col_mapping => 'OBJECT_ID OBJECT_ID, OWNER OWNER, OBJECT_TYPE OBJECT_TYPE, OBJECT_NAME OBJECT_NAME, CREATED CREATED, LAST_DDL_TIME LAST_DDL_TIME, to_timestamp(LAST_DDL_TIME) LAST_DDL_TS', options_flag => dbms_redefinition.cons_use_rowid);
end; 
/

ORA-42000: invalid online redefinition column mapping for table "NP"."TBL_DATEPART"
ORA-06512: at "SYS.DBMS_REDEFINITION", line 113
ORA-06512: at "SYS.DBMS_REDEFINITION", line 4363
ORA-06512: at "SYS.DBMS_REDEFINITION", line 5753
ORA-06512: at line 3
42000. 0000 -  "invalid online redefinition column mapping for table \"%s\".\"%s\""
*Document: YES
*Cause:    An attempt was made to change the logical structure of a
           materialized view log, queue table, or a partition
           by specifying a non-NULL column mapping during online
           redefinition.
*Action:   Pass a NULL column mapping parameter.

and Connor said...

PART_NAME is going to be mutually exclusive with *structural changes* because you can't have a table with some partitions with structure "A" and some with structure "B".

PART_NAME pre-dates some of the things that you can now do online from 12.2 onwards, so it was used for things like compressing / moving - re-sorting on a partition by partition basis without service interruption

I expect you're referring to the post by Tim about migrating billions of rows to a new partition key. I also had a look at PART_NAME as a means to do this incrementally, but I think we're out of luck

Hope that helps.

Rating

  (5 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Thanks

Narendra, January 24, 2023 - 11:26 pm UTC

Hello Connor,

Thank you for taking time to answer my question.
You are right that DBMS_REDEFINITION can/should not support structural changes to individual partitions. Also, I agree that with 19c, we have so many options to modify table structure online that there is probably not a strong enough case to ask for DBMS_REDEFINITION to be able to update a column on per partition basis but it would be a really cool feature to have if it was indeed possible to use DBMS_REDEFINITION incrementally for implementing data manipulation online. If, for example, in my example above, the original table had been HASH PARTITIONED on OBJECT_ID instead of being RANGE PARTITIONED on LAST_DDL_TIME, it would mean that I do not have any historical/read-only partitions. With a really large table, if want to add a column and update its value in ONLINE manner, I am not sure it is possible, right?
Connor McDonald
January 25, 2023 - 2:50 am UTC

I am not sure it is possible, right?

That's what I'm currently researching

Does DBMS_REDEFINITION use EXCHANGE PARTITION when used with PART_NAME?

Narendra, February 23, 2026 - 12:16 pm UTC

Hello Connor/Chris,

So I was (once again) hoping to use DBMS_REDEFINITION to be able to amend number of subpartitions in a range/hash partitioned tables but on a per partition basis but looks like DBMS_REDEFINITION with PART_NAME appears to not be able to help with this. Would you know if this is intended behaviour or a suboptimal algorithm?

Below is my test script with comments

drop table if exists NP.NP_TEST_COPY purge ;

create table NP.NP_TEST_COPY
storage (initial 128k)
partition by range (CREATED) INTERVAL (NUMTOYMINTERVAL(1,'MONTH'))
subpartition by hash (object_id) subpartitions 32
(partition P1 values less than (TO_DATE('01-JAN-2024','DD-MON-YYYY')) storage (initial 128k))
as
select owner, object_id, object_name, created, xmlelement("ObjectDetails", xmlforest(object_type, status, last_ddl_time)) as xml_details
from dba_objects ;

-- Below fails with ORA-14427: table does not support modification to a partitioned state DDL due to XMLTYPE column
ALTER TABLE NP.NP_TEST_COPY
MODIFY
partition by range (CREATED) INTERVAL (NUMTOYMINTERVAL(1,'MONTH'))
subpartition by hash (object_id) subpartitions 2
(partition P1 values less than (TO_DATE('01-JAN-2024','DD-MON-YYYY')) storage (initial 256k)) ;

-- DBMS_REDEFINITION approach
create table NP.NP_TEST_COPY_INT
(OWNER VARCHAR2(128), OBJECT_ID NUMBER, OBJECT_NAME VARCHAR2(128), CREATED DATE, xml_details XMLTYPE)
storage (initial 512k)
partition by hash (object_id) partitions 2 ;


-- START_REDEF_TABLE reports success
begin
    dbms_redefinition.start_redef_table(uname        => 'NP', 
                                        orig_table   => 'NP_TEST_COPY',
                                        int_table    => 'NP_TEST_COPY_INT',
                                        part_name    => 'P1',
                                        options_flag => dbms_redefinition.cons_use_rowid);
end;
/

-- FINISH_REDEF_TABLE complains about (sub)partition structure not matching
-- ORA-42012: error occurred while completing the redefinition
-- ORA-14294: Number of partitions does not match number of subpartitions
-- ORA-06512: at "SYS.DBMS_REDEFINITION", line 188
-- ORA-06512: at "SYS.DBMS_REDEFINITION", line 4533
-- ORA-06512: at "SYS.DBMS_REDEFINITION", line 5859
-- ORA-06512: at line 2
begin
    dbms_redefinition.finish_redef_table(uname       => 'NP', 
                                        orig_table   => 'NP_TEST_COPY',
                                        int_table    => 'NP_TEST_COPY_INT',
                                        part_name    => 'P1');
end;
/

Connor McDonald
February 24, 2026 - 5:06 am UTC

Database version?

Does DBMS_REDEFINITION use EXCHANGE PARTITION when used with PART_NAME?

Narendra, February 23, 2026 - 12:16 pm UTC

Hello Connor/Chris,

So I was (once again) hoping to use DBMS_REDEFINITION to be able to amend number of subpartitions in a range/hash partitioned tables but on a per partition basis but looks like DBMS_REDEFINITION with PART_NAME appears to not be able to help with this. Would you know if this is intended behaviour or a suboptimal algorithm?

Below is my test script with comments

drop table if exists NP.NP_TEST_COPY purge ;

create table NP.NP_TEST_COPY
storage (initial 128k)
partition by range (CREATED) INTERVAL (NUMTOYMINTERVAL(1,'MONTH'))
subpartition by hash (object_id) subpartitions 32
(partition P1 values less than (TO_DATE('01-JAN-2024','DD-MON-YYYY')) storage (initial 128k))
as
select owner, object_id, object_name, created, xmlelement("ObjectDetails", xmlforest(object_type, status, last_ddl_time)) as xml_details
from dba_objects ;

-- Below fails with ORA-14427: table does not support modification to a partitioned state DDL due to XMLTYPE column
ALTER TABLE NP.NP_TEST_COPY
MODIFY
partition by range (CREATED) INTERVAL (NUMTOYMINTERVAL(1,'MONTH'))
subpartition by hash (object_id) subpartitions 2
(partition P1 values less than (TO_DATE('01-JAN-2024','DD-MON-YYYY')) storage (initial 256k)) ;

-- DBMS_REDEFINITION approach
create table NP.NP_TEST_COPY_INT
(OWNER VARCHAR2(128), OBJECT_ID NUMBER, OBJECT_NAME VARCHAR2(128), CREATED DATE, xml_details XMLTYPE)
storage (initial 512k)
partition by hash (object_id) partitions 2 ;


-- START_REDEF_TABLE reports success
begin
    dbms_redefinition.start_redef_table(uname        => 'NP', 
                                        orig_table   => 'NP_TEST_COPY',
                                        int_table    => 'NP_TEST_COPY_INT',
                                        part_name    => 'P1',
                                        options_flag => dbms_redefinition.cons_use_rowid);
end;
/

-- FINISH_REDEF_TABLE complains about (sub)partition structure not matching
-- ORA-42012: error occurred while completing the redefinition
-- ORA-14294: Number of partitions does not match number of subpartitions
-- ORA-06512: at "SYS.DBMS_REDEFINITION", line 188
-- ORA-06512: at "SYS.DBMS_REDEFINITION", line 4533
-- ORA-06512: at "SYS.DBMS_REDEFINITION", line 5859
-- ORA-06512: at line 2
begin
    dbms_redefinition.finish_redef_table(uname       => 'NP', 
                                        orig_table   => 'NP_TEST_COPY',
                                        int_table    => 'NP_TEST_COPY_INT',
                                        part_name    => 'P1');
end;
/

Connor McDonald
February 24, 2026 - 5:06 am UTC

Duplicate

Re: Does DBMS_REDEFINITION use EXCHANGE PARTITION when used with PART_NAME?

Narendra, February 24, 2026 - 9:29 am UTC

Hello Connor/Chris,

Thank you for responding and apologies for not doing my "homework" before asking this question.
My database version is 19.28 but I found the reference in the documentation https://docs.oracle.com/en/database/oracle/oracle-database/18/admin/managing-tables.html#GUID-F183AA70-A1CF-44F9-A139-DE67EEA5025E which confirms that DBMS_REDEFINITION uses EXCHANGE PARTITION under the covers to redefine individual partitions.
If I am brutally honest, I am not sure what is the use of DBMS_REDEFINITION having option to cater for individual partitions, especially when it uses the same EXCHANGE PARTITION that is already available and is limited by the same rules of EXCHANGE PARTITION.

On a related note, I tried to use DBMS_REDEFINITION to successfully reduce the number of HASH sub partitions in a Range/Hash Composite Partitioned table. While the table data and its dependents were copied over, the local index was not carried over to the new table. Would you know if this is an expected behaviour (and I did check documentation this time but could not find)?

Thanks in advance
Connor McDonald
February 25, 2026 - 3:52 am UTC

The reason I was asking about what version was - if you want to alter the number of partitions, I would not use DBMS_REDEFINITION. I would simply use 'alter table'

eg

SQL> create table t
  2  partition by hash ( owner )
  3  partitions 16
  4  as select * from dba_objects;

Table created.

SQL> alter table T modify
  2  partition by list (owner) automatic
  3  (
  4    partition p1 values ('SYS')
  5  ) online
  6  update indexes;

Table altered.



Re: Does DBMS_REDEFINITION use EXCHANGE PARTITION when used with PART_NAME?

Narendra, February 25, 2026 - 8:41 am UTC

Hello Connor,

My apologies for not answering your question.
My database version is 19.28

Also, I had mentioned it before but probably not clearly but ALTER TABLE...MODIFY was the first thing that I tried.
drop table if exists NP.NP_TEST_COPY purge ;

create table NP.NP_TEST_COPY
storage (initial 128k)
partition by range (CREATED) INTERVAL (NUMTOYMINTERVAL(1,'MONTH'))
subpartition by hash (object_id) subpartitions 32
(partition P1 values less than (TO_DATE('01-JAN-2024','DD-MON-YYYY')) storage (initial 128k))
as
select owner, object_id, object_name, created, xmlelement("ObjectDetails", xmlforest(object_type, status, last_ddl_time)) as xml_details
from dba_objects ;

-- Below fails with ORA-14427: table does not support modification to a partitioned state DDL due to XMLTYPE column
ALTER TABLE NP.NP_TEST_COPY
MODIFY
partition by range (CREATED) INTERVAL (NUMTOYMINTERVAL(1,'MONTH'))
subpartition by hash (object_id) subpartitions 2
(partition P1 values less than (TO_DATE('01-JAN-2024','DD-MON-YYYY')) storage (initial 256k)) ;


Unfortunately, the presence of XMLTYPE column in the table is preventing me from using ALTER TABLE...MODIFY approach.
That is why I had to fall back on having to use DBMS_REDEFINITION.

If it helps, I am not precious about making this change ONLINE. We can secure "reasonable downtime" for this table structure change. However, it seems there is no easy way to achieve that but I am happy to be proved wrong.
The only OFFLINE option I can think of is to script the conversion to do it manually by one or few partitions at a time using EXCHANGE PARTITION with INSERT INTO...SELECT. While I will have more control over it due to having to write scripts myself, there is an element of "feeling reassured" with DBMS_REDEFINITION, especially when it comes to convincing "the management".

Thanks in advance
Chris Saxon
March 06, 2026 - 2:18 pm UTC

You can coalesce subpartitions when the table has an XMLtype column. This only removes the last subpartition, so going down from 32 to 2 subpartitions means shuffling the data around a lot.

For example:

create table t ( c1 int, c2 int, c3 xmltype )
partition by range ( c1 ) 
subpartition by hash ( c2 ) subpartitions 8 (
  partition p1 values less than ( 100 ),
  partition p2 values less than ( 200 )
);

select partition_name, count(*) 
from   user_tab_subpartitions
where  table_name = 'T'
group  by partition_name;

PARTITION_   COUNT(*)
---------- ----------
P1                  8
P2                  8

begin
  for i in 1 .. 4 loop
    execute immediate 'alter table t modify partition p1 coalesce subpartition';
  end loop;
end;
/

select partition_name, count(*) 
from   user_tab_subpartitions
where  table_name = 'T'
group  by partition_name;

PARTITION_   COUNT(*)
---------- ----------
P1                  4
P2                  8


Another approach - you can change the number of subpartitions when merging partitions. So you could:

- Merge partitions to get the desired number of subpartitions
- Split the partitions back out to the original

alter table t merge partitions p1, p2 
   into partition p2
   subpartitions 2;

select partition_name, count(*) 
from   user_tab_subpartitions
where  table_name = 'T'
group  by partition_name;

PARTITION_   COUNT(*)
---------- ----------
P2                  2

alter table t split partition p2 at ( 100 )
   into ( partition p1, partition p2 );

select partition_name, count(*) 
from   user_tab_subpartitions
where  table_name = 'T'
group  by partition_name;

PARTITION_   COUNT(*)
---------- ----------
P1                  2
P2                  2

More to Explore

Administration

Need more information on Administration? Check out the Administrators guide for the Oracle Database