All Products
Search
Document Center

PolarDB:ALTER TABLE ADD SUBPARTITION

Last Updated:Mar 28, 2026

Adds a new subpartition to a specified first-level partition of a composite partitioned table. Before running this statement, confirm that the parent partition has a subpartitioning policy defined and that the new subpartition's boundary or values do not conflict with existing subpartitions.

Synopsis

ALTER TABLE table_name
MODIFY PARTITION partition_name
ADD SUBPARTITION { list_subpartition | range_subpartition };

-- LIST subpartition definition
SUBPARTITION subpartition_name
  VALUES (value[, value]...)
  [TABLESPACE tablespace_name]

-- RANGE subpartition definition
SUBPARTITION subpartition_name
  VALUES LESS THAN (value[, value]...)
  [TABLESPACE tablespace_name]

Parameters

ParameterRequiredDescriptionExample
table_nameYesThe name of the target composite partitioned table.sales_data
partition_nameYesThe name of the first-level partition to which the new subpartition is added.p_2023
subpartition_nameYesThe name of the new subpartition. Must be unique across all partitions and subpartitions in the table.sp_q1_asia
VALUESYesThe boundary values for the new subpartition. For a LIST subpartition, specify one or more literal values. For a RANGE subpartition, use VALUES LESS THAN to set the upper boundary.VALUES ('Asia') or VALUES LESS THAN (TO_DATE(...))
TABLESPACE tablespace_nameNo. Default: the table's default tablespace.The tablespace for the new subpartition.TABLESPACE users_tbs

Usage notes

  • The subpartition type (LIST or RANGE) must match the type of existing subpartitions under the same parent partition.

  • subpartition_name must be unique among all partitions and subpartitions in the table.

  • When you add a RANGE subpartition, the boundary value defined by VALUES LESS THAN (...) must be greater than the upper boundary of all existing subpartitions. RANGE subpartitions can only be appended in ascending order. To insert a subpartition in the middle, use ALTER TABLE ... SPLIT SUBPARTITION to split an existing subpartition.

  • When you add a LIST subpartition, the values in its VALUES (...) list cannot overlap with the values of any existing subpartitions in the same parent partition.

  • Do not use ADD SUBPARTITION on a partition governed by a MAXVALUE or DEFAULT rule. Instead, use ALTER TABLE ... SPLIT SUBPARTITION to split the existing boundary partition.

  • ADD SUBPARTITION acquires a table-level exclusive lock (AccessExclusiveLock), which blocks all data manipulation language (DML) operations and most data definition language (DDL) operations on the table. Run this command during off-peak hours and allow enough time for it to complete.

  • There is no stated limit on the number of subpartitions, but keep the total number of partitions per table under 1,000 for optimal performance and manageability.

  • If the table has an index, the database automatically creates a corresponding index partition for the new subpartition.

  • You must be the table owner or have administrator privileges to run this command.

  • The new subpartition initially has no statistics. To help the query optimizer generate accurate execution plans, gather statistics immediately after adding the subpartition.

Examples

Add a LIST subpartition to a RANGE-LIST composite partitioned table

This example adds a subpartition for the Africa region to the 2023 partition of a table that is composite-partitioned by sales year (RANGE) and sales region (LIST).

Prepare the environment

Create a RANGE-LIST composite partitioned table named sales_data, partitioned by RANGE on sale_date and subpartitioned by LIST on region.

-- Create a RANGE-LIST composite partitioned table
CREATE TABLE sales_data (
    sale_id    INT,
    region     VARCHAR2(20),
    sale_date  DATE
)
PARTITION BY RANGE (sale_date)
SUBPARTITION BY LIST (region)
(
    PARTITION p_2023 VALUES LESS THAN (TO_DATE('2024-01-01', 'YYYY-MM-DD'))
    (
        SUBPARTITION sp_2023_asia   VALUES ('Asia'),
        SUBPARTITION sp_2023_europe VALUES ('Europe')
    )
);

Perform a pre-check

Before adding the subpartition, verify that the target first-level partition exists and check its current subpartitions.

-- Check that the first-level partition p_2023 exists
SELECT PARTITION_NAME FROM USER_TAB_PARTITIONS WHERE TABLE_NAME = 'SALES_DATA';

-- Check the existing subpartitions under p_2023 to confirm that 'Africa' does not already exist
SELECT SUBPARTITION_NAME FROM USER_TAB_SUBPARTITIONS
WHERE TABLE_NAME = 'SALES_DATA' AND PARTITION_NAME = 'P_2023';

Add the subpartition

Add a new subpartition with the value 'Africa' to the p_2023 partition.

ALTER TABLE sales_data MODIFY PARTITION p_2023 ADD SUBPARTITION sp_2023_africa VALUES('Africa');

Verify the result

Confirm that the new subpartition exists and can accept data matching its value definition.

-- Structure verification: confirm the new subpartition has been added
SELECT SUBPARTITION_NAME FROM USER_TAB_SUBPARTITIONS
WHERE TABLE_NAME = 'SALES_DATA' AND PARTITION_NAME = 'P_2023';
-- The result should include sp_2023_africa

-- Data verification: insert a row and confirm it is routed to the new subpartition
INSERT INTO sales_data VALUES (101, 'Africa', TO_DATE('2023-09-15', 'YYYY-MM-DD'));

SELECT COUNT(*) FROM sales_data SUBPARTITION (sp_2023_africa);
-- The result should be 1

Add a RANGE subpartition to a RANGE-RANGE composite partitioned table

This example adds a subpartition for the second quarter (Q2) to the 2023 partition of a table that is composite-partitioned by order year (RANGE) and order date (RANGE).

Prepare the environment

Create a RANGE-RANGE composite partitioned table named order_history, partitioned by RANGE on order_date and subpartitioned by RANGE on order_date.

-- Assumes a tablespace named archive_tbs already exists
-- CREATE TABLESPACE archive_tbs DATAFILE 'archive_tbs.dbf' SIZE 10M;

-- Create a RANGE-RANGE composite partitioned table
CREATE TABLE order_history (
    order_id   INT,
    order_date DATE
)
PARTITION BY RANGE (order_date)
SUBPARTITION BY RANGE (order_date)
(
    PARTITION p_2023 VALUES LESS THAN (TO_DATE('2024-01-01', 'YYYY-MM-DD'))
    (
        SUBPARTITION sp_2023_q1 VALUES LESS THAN (TO_DATE('2023-04-01', 'YYYY-MM-DD'))
    )
);

Perform a pre-check

Verify that the target first-level partition exists and check the boundaries of its current subpartitions to confirm the new boundary does not conflict.

-- Check that the first-level partition p_2023 exists
SELECT PARTITION_NAME FROM USER_TAB_PARTITIONS WHERE TABLE_NAME = 'ORDER_HISTORY';

-- Check existing subpartitions and their boundaries under p_2023
SELECT SUBPARTITION_NAME, HIGH_VALUE FROM USER_TAB_SUBPARTITIONS
WHERE TABLE_NAME = 'ORDER_HISTORY' AND PARTITION_NAME = 'P_2023';

Add the subpartition

Add a new subpartition with an upper boundary of 2023-07-01 to the p_2023 partition.

ALTER TABLE order_history MODIFY PARTITION p_2023
ADD SUBPARTITION sp_2023_q2 VALUES LESS THAN (TO_DATE('2023-07-01', 'YYYY-MM-DD'));

Verify the result

Confirm that the new subpartition was created and can accept data.

-- Structure verification: confirm the new subpartition exists
SELECT * FROM USER_TAB_SUBPARTITIONS
WHERE TABLE_NAME = 'ORDER_HISTORY' AND SUBPARTITION_NAME = 'SP_2023_Q2';
-- The result should show SP_2023_Q2

-- Data verification: insert a row and confirm it is routed to the new subpartition
INSERT INTO order_history VALUES (201, TO_DATE('2023-05-20', 'YYYY-MM-DD'));

SELECT COUNT(*) FROM order_history SUBPARTITION (sp_2023_q2);
-- The result should be 1

FAQ

Why do I get `ORA-14321: subpartition ... already exists`?

The VALUES definition for the new subpartition conflicts with an existing one under the same parent partition. For a LIST subpartition, the value is already claimed by another subpartition. For a RANGE subpartition, the new boundary is not strictly higher than the last one. Specify a non-overlapping boundary value and retry.

Why do I get `ORA-02269: partition does not exist`?

The partition_name in the MODIFY PARTITION clause does not exist in the table. Query USER_TAB_PARTITIONS to get the correct name of the first-level partition.

Why do I get `ORA-14150: subpartitioning is not specified`?

The target table does not have a subpartitioning policy. ADD SUBPARTITION applies only to composite partitioned tables.

Why do I get `ORA-01031: insufficient privileges`?

The current user lacks the ALTER privilege on the target table. Contact a database administrator to grant the required privilege.

Why do I get `ORA-14074: partition bound must collate higher than that of the last partition`?

ADD SUBPARTITION can only append a RANGE subpartition at the end of the existing range in ascending order. To insert a subpartition in the middle, use ALTER TABLE ... SPLIT SUBPARTITION instead.

Related statements