All Products
Search
Document Center

PolarDB:ALTER TABLE ADD SUBPARTITION

Last Updated:Oct 23, 2025

Adds a new subpartition to a specified first-level partition of a composite partitioned table. This operation expands the partition structure and affects data distribution. Before running this statement, ensure a subpartitioning policy is defined for the parent partition, 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

Parameter

Required

Parameter description

Example

table_name

Yes

The name of the target composite partitioned table.

sales_data

partition_name

Yes

The name of the target first-level partition where the new subpartition will be added.

p_2023

subpartition_name

Yes

The name of the new subpartition.

sp_q1_asia

VALUES

Yes

Defines the boundary values for the new subpartition.
- For a LIST subpartition, value is one or more literal values.
- For a RANGE subpartition, use the LESS THAN clause to define the upper boundary.

VALUES('Asia') or
VALUES LESS THAN (TO_DATE(...))

TABLESPACE tablespace_name

Optional
Default value: The table's default tablespace.

Specifies the tablespace for the new subpartition. If you omit this parameter, it uses the table's default tablespace.

TABLESPACE users_tbs

Notes

  • The type of the new subpartition (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, you can use the ALTER TABLE ... SPLIT SUBPARTITION statement 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.

  • ADD SUBPARTITION acquires a table-level exclusive lock (AccessExclusiveLock). This lock blocks all DML operations and most DDL operations on the table. Run this command during off-peak hours and allow a sufficient time window for it to complete.

  • ADD SUBPARTITION does not limit the number of subpartitions that you can add. However, system resources impose a practical limit. For optimal performance and manageability, keep the total number of partitions for a single table under 1,000.

  • Do not use ADD SUBPARTITION to add a subpartition to a a partition governed by a MAXVALUE or DEFAULT rule.

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

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

  • A new subpartition initially has no statistics. To ensure the query optimizer generates accurate execution plans, gather statistics for the table immediately after this operation.

Examples

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

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

Prepare the environment

This step creates a RANGE-LIST composite partitioned table named sales_data. The table is 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 you add the subpartition, verify that the target first-level partition exists and check its current list of 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 the new value 'Africa' does not exist
SELECT SUBPARTITION_NAME FROM USER_TAB_SUBPARTITIONS 
WHERE TABLE_NAME = 'SALES_DATA' AND PARTITION_NAME = 'P_2023';

Run the command

Run the ADD SUBPARTITION command to 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

Verify that the new subpartition exists and can accept data that matches its value definition.

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

-- Data verification: Try to insert data into the new subpartition and verify
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 query 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).

Prerequisites

This step creates a RANGE-RANGE composite partitioned table named order_history. The table is partitioned by RANGE on order_date and then subpartitioned by RANGE on order_date.

-- Assume that 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 ensure the new boundary does not cause a conflict.

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

-- Check the 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';

Run the command

Run the ADD SUBPARTITION command to 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

Verify that the new subpartition was created, and that you can insert data into it.

-- Structure verification: Confirm that the new subpartition has been added and check its tablespace
SELECT * FROM USER_TAB_SUBPARTITIONS 
WHERE TABLE_NAME = 'ORDER_HISTORY' AND SUBPARTITION_NAME = 'SP_2023_Q2';
-- The query result should show SP_2023_Q2 and ARCHIVE_TBS

-- Data verification: Try to insert data into the new subpartition and verify
INSERT INTO order_history VALUES (201, TO_DATE('2023-05-20', 'YYYY-MM-DD'));

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

FAQ

Q1: Why do I get the error ORA-14321: subpartition ... already exists?
This error occurs because the VALUES definition for the new subpartition conflicts with an existing one under the same first-level partition. For a LIST subpartition, the value already exists; for a RANGE subpartition, the new boundary is not higher than the last one. Specify a non-overlapping boundary value for the new subpartition.

Q2: Why do I get the error ORA-02269: partition does not exist?
This error occurs because the partition_name specified in the MODIFY PARTITION clause does not exist. Query the USER_TAB_PARTITIONS view to verify the correct name of the first-level partition.

Q3: Why do I get the error ORA-14150: subpartitioning is not specified?
You tried to run ADD SUBPARTITION on a partitioned table that does not have a subpartitioning policy. This command applies only to composite partitioned tables.

Q4: Why do I get the error ORA-01031: insufficient privileges?
The user running the command does not have the ALTER privilege on the target table. Contact a database administrator to grant the required privilege.

Q5: Why do I receive the error ORA-14074: partition bound must collate higher than that of the last partition?

The ADD SUBPARTITION command can only append a RANGE subpartition to the end of the existing range. To insert a subpartition in the middle, use the SPLIT SUBPARTITION command instead.

Related statements