
# ALTER TABLE SUBPARTITION
#### 功能描述
修改二级分区表分区，包括增删分区、清空分区、切割/合并分区、移动分区表空间、交换分区、重命名分区，以及修改分区属性等。
#### 注意事项
- 添加分区的表空间不能是PG_GLOBAL。
- 添加分区的名称不能与该分区表已有一级分区和二级分区的名称相同。
- 添加分区的分区键值要和分区表的分区键的类型一致。
- 若添加RANGE分区，添加分区键值要大于分区表中最后一个范围分区的上边界。若需要在有MAXVALUE分区的表上新增分区，建议使用SPLIT语法。
- 若添加LIST分区，添加分区键值不能与现有分区键值重复。若需要在有DEFAULT分区的表上新增分区，建议使用SPLIT语法。
- 不支持添加HASH分区。只有一种情况例外，二级分区表的二级分区方式为HASH且一级分区方式不是HASH，此时支持新增一级分区并创建对应的二级分区。
- 如果目标分区表中已有分区数达到了最大值1048575，则不能继续添加分区。
- 当分区表只有一个一级分区或二级分区时，不能删除该分区。
- 不支持删除HASH分区。
- 选择分区使用PARTITION FOR()或SUBPARTITION FOR()，括号里指定值个数应该与定义分区时使用的列个数相同，并且一一对应。
- 切割分区只能对二级分区（叶子节点）进行切割，被切割分区只能是Range、List分区策略，不支持切割hash分区策略。
- 合并分区只能对二级分区（叶子节点）进行合并，且源分区必须属于同一个一级分区。
- 只有分区表的所有者或者被授予了分区表ALTER权限的用户有权限执行ALTER TABLE PARTITION命令，系统管理员默认拥有此权限。
- 删除、切割、清空、交换分区的操作会使Global索引失效，可以申明UPDATE GLOBAL INDEX子句同步更新索引。
- 如果删除、切割、清空、交换分区操作不申明UPDATE GLOBAL INDEX子句，并发的DML业务有可能因为索引不可用而报错。
- 若设置参数enable_gpi_auto_update为on，即使不申明UPDATE GLOBAL INDEX子句，也会自动更新Global索引。
 
#### 语法格式
修改二级分区表分区包括修改表分区主语法、修改表分区名称的语法和重置分区ID的语法。
- 修改表分区主语法。
  ```
  ALTER TABLE [ IF EXISTS ] { table_name  [*] | ONLY table_name | ONLY ( table_name  )}
      action [, ... ];
  ```
  其中action统指如下分区维护子语法。当存在多个分区维护子句时，保证了分区的连续性，无论这些子句的排序如何，GaussDB总会先执行DROP PARTITION再执行ADD PARTITION操作，最后顺序执行其它分区维护操作。
  ```
  move_clause  |
      exchange_clause  |
      row_clause  |
      merge_clause  |
      modify_clause  |
      add_clause    |
      drop_clause   |    
      split_clause  |
      truncate_clause
  ```
  - move_clause子语法用于移动分区到新的表空间。
    ```
    MOVE SUBPARTITION { subpartion_name | FOR ( subpartition_value [, ...] ) } TABLESPACE tablespacename
    ```
    
  
  - exchange_clause子语法用于把普通表的数据迁移到指定的分区。
    ```
    EXCHANGE SUBPARTITION { ( subpartition_name ) | FOR ( subpartition_value [, ...] ) } 
        WITH TABLE {[ ONLY ] ordinary_table_name | ordinary_table_name * | ONLY ( ordinary_table_name )} 
        [ { WITH | WITHOUT } VALIDATION ] [ VERBOSE ] [ UPDATE GLOBAL INDEX ]
    ```
    进行交换的普通表和分区必须满足如下条件：
    - 普通表和分区的列数目相同，对应列的信息严格一致，包括：列名、列的数据类型、列约束、列的Collation信息、列的存储参数、列的压缩信息等。
    
    - 普通表和分区的表压缩信息严格一致。
    
    - 普通表索引和分区Local索引个数相同，且对应索引的信息严格一致。
    
    - 普通表和分区的表约束个数相同，且对应表约束的信息严格一致。
    
    - 普通表不可以是临时表，分区表只能是二级分区表。
    
    - 普通表和分区表上不可以有动态数据脱敏，行访问控制约束。
    
    
    ![](https://support.huaweicloud.com/centralized-devg-v3-gaussdb/public_sys-resources/notice_3.0-zh-cn.png)
    - 完成交换后，普通表和分区的数据被置换，同时普通表和分区的表空间信息被置换。此时，普通表和分区的统计信息变得不可靠，需要对普通表和分区重新执行analyze。
    
    - 由于非分区键不能建立本地唯一索引，只能建立全局唯一索引，所以如果普通表含有唯一索引时，可能会导致不能交换数据。 如果需要进行数交换数据操作可以通过创建中间表的方式，先将分区数据插入到中间表，truncate分区，普通表数据插入分区表，drop普通表，重命名中间表的方式完成数据交换操作。
      
    
    - 如果在普通表/分区表上进行了drop column操作，被删除的列依然物理存在，所以需要保证普通表和分区的被删除列也严格对齐才能交换成功。
      
  
  - row_clause子语法用于设置分区表的行迁移开关。
    ```
    { ENABLE | DISABLE } ROW MOVEMENT
    ```
    
  
  - merge_clause子语法用于把多个分区合并成一个分区。一个命令中合并的源分区上限为300。
    ```
    MERGE SUBPARTITIONS { subpartition_name } [, ...] INTO SUBPARTITION partition_name 
        [ TABLESPACE tablespacename ] [ UPDATE GLOBAL INDEX ]
    ```
    ![](https://support.huaweicloud.com/centralized-devg-v3-gaussdb/public_sys-resources/notice_3.0-zh-cn.png)
    对于范围分区，MERGE分区要求源分区的范围连续递增，且MERGE后的分区名可以与最后一个源分区名相同；对于列表分区，则源分区无顺序要求，且MERGE后的分区名可以与任一源分区名相同。如果MERGE后的分区名与源分区名相同，视为同一个分区。
    ![](https://support.huaweicloud.com/centralized-devg-v3-gaussdb/public_sys-resources/notice_3.0-zh-cn.png)
    USTORE存储引擎表不支持在事务块/存储过程中执行ALTER TABLE MERGE SUBPARTITIONS的操作。
    
  
  - modify_clause子语法用于设置分区索引是否可用。语法可以作用在一级分区上。
    ```
    MODIFY PARTITION partition_name { UNUSABLE LOCAL INDEXES | REBUILD UNUSABLE LOCAL INDEXES }
    ```
    也可以作用在二级分区上。
    ```
    MODIFY SUBPARTITION partition_name { UNUSABLE LOCAL INDEXES | REBUILD UNUSABLE LOCAL INDEXES }
    ```
    
  
  - add_clause子语法用于为指定的分区表添加一个或多个分区。语法可以作用在一级分区上。
    ```
    ADD {partition_less_than_item | partition_list_item } [ ( subpartition_definition_list ) ]
    ```
    也可以作用在二级分区上。
    ```
    MODIFY PARTITION partition_name ADD subpartition_definition
    ```
    其中，分区项partition_less_than_item为RANGE分区定义语法，具体语法如下。
    ```
    PARTITION partition_name VALUES LESS THAN ( partition_value | MAXVALUE ) [ TABLESPACE tablespacename ]
    ```
    分区项partition_list_item为LIST分区定义语法，具体语法如下。
    ```
    PARTITION partition_name VALUES ( partition_value [, ...] | DEFAULT ) [ TABLESPACE tablespacename ]
    ```
    subpartition_definition_list为1到多个二级分区subpartition_definition对象，subpartition_definition具体语法如下。
    ```
    SUBPARTITION subpartition_name [ VALUES LESS THAN ( partition_value | MAXVALUE ) | VALUES ( partition_value [, ...] | DEFAULT )]  [ TABLESPACE tablespace ]
    ```
    ![](https://support.huaweicloud.com/centralized-devg-v3-gaussdb/public_sys-resources/notice_3.0-zh-cn.png)
    若一级分区为HASH分区，不支持以ADD形式新增一级分区；若二级分区为HASH分区，不支持以MODIFY形式新增二级分区。
    
  
  - drop_clause子语法用于删除分区表中的指定分区。语法可以作用在一级分区上。
    ```
    DROP PARTITION  { partition_name | FOR (  partition_value )  } [ UPDATE GLOBAL INDEX ]
    ```
    也可以作用在二级分区上。
    ```
    DROP SUBPARTITION  { subpartition_name | FOR (  partition_value, subpartition_value )  } [ UPDATE GLOBAL INDEX ]
    ```
    ![](https://support.huaweicloud.com/centralized-devg-v3-gaussdb/public_sys-resources/notice_3.0-zh-cn.png)
    - 若一级分区为HASH分区，不支持删除一级分区；若二级分区为HASH分区，不支持删除二级分区。
    
    - 不支持删除唯一子分区。
      
  
  - split_clause子语法用于把一个分区切割成多个分区。
    ```
    SPLIT SUBPARTITION { subpartition_name| FOR ( subpartition_value [, ...] ) } { split_point_clause | no_split_point_clause } [ UPDATE GLOBAL INDEX ]
    ```
    ![](https://support.huaweicloud.com/centralized-devg-v3-gaussdb/public_sys-resources/notice_3.0-zh-cn.png)
    - SPLIT后的分区名可以与源分区名相同，但视为不同的分区。
     
    - 范围分区指定切割点split_point_clause的语法为：
      ```
      AT ( subpartition_value ) INTO ( SUBPARTITION subpartition_name [ TABLESPACE tablespacename ] , SUBPARTITION subpartition_name [ TABLESPACE tablespacename ] )
      ```
      ![](https://support.huaweicloud.com/centralized-devg-v3-gaussdb/public_sys-resources/notice_3.0-zh-cn.png)
      切割点的大小要位于正在被切割的分区的分区键范围内，指定切割点的方式只能把一个分区切割成两个新分区。
      
    
    - 范围分区不指定切割点no_split_point_clause 的语法如下，其中最后一个分区不能写分区范围定义，即VALUES LESS THAN (subpartition_value)部分，默认继承源分区范围定义的上界值。
      ```
      INTO ( SUBPARTITION subpartition_name VALUES LESS THAN (subpartition_value) [ TABLESPACE tablespacename ][, ...] )
      ```
      ![](https://support.huaweicloud.com/centralized-devg-v3-gaussdb/public_sys-resources/notice_3.0-zh-cn.png)
      - 第一个新分区的分区范围定义要大于正在被切割的分区的前一个分区（如果存在的话）的分区范围定义。
      
      - 最后一个新分区不能写分区范围定义，默认继承源分区范围定义的上界值。
      
      - 新分区必须满足分区范围定义递增的约束。
        
    
    - 列表范围分区指定切割点split_point_clause的语法如下：
      ```
      VALUES ( subpartition_value ) INTO ( SUBPARTITION subpartition_name [ TABLESPACE tablespacename ] , SUBPARTITION subpartition_name [ TABLESPACE tablespacename ] )
      ```
      ![](https://support.huaweicloud.com/centralized-devg-v3-gaussdb/public_sys-resources/notice_3.0-zh-cn.png)
      切割点必须是源分区的一个非空真子集，指定切割点的方式只能把一个分区切割成两个新分区。
      
    
    - 列表分区表不指定切割点no_split_point_clause的语法如下，其中最后一个分区不能写分区范围定义，即VALUES (subpartition_value_list)部分，其范围等于源分区去掉其他子分区后的剩余集合。
      ```
      INTO ( SUBPARTITION subpartition_name VALUES (subpartition_value_list) [ TABLESPACE tablespacename ][, ...] )
      ```
      ![](https://support.huaweicloud.com/centralized-devg-v3-gaussdb/public_sys-resources/notice_3.0-zh-cn.png)
      - 最后一个新分区不能写分区范围定义，其范围等于源分区去掉其他子分区后的剩余集合。
      
      - 不指定切割点的方式，每一个新分区都必须是源分区的一个非空真子集，且互不交叉。
        
     
  
  - truncate_clause子语法用于清空分区表中的指定分区。语法可以作用在一级分区上。
    ```
    TRUNCATE PARTITION  { partition_name | FOR (  partition_value [, ...] )  } [ UPDATE GLOBAL INDEX ]
    ```
    也可以作用在二级分区上。
    ```
    TRUNCATE SUBPARTITION  { subpartition_name | FOR (  subpartition_value [, ...] )  } [ UPDATE GLOBAL INDEX ]
    ```
    
   
 
- 修改表分区名称的语法。可以修改分区表的一级分区。
  ```
  ALTER TABLE [ IF EXISTS ] { table_name [*] | ONLY table_name | ONLY ( table_name  )}
      RENAME PARTITION { partion_name | FOR ( partition_value [, ...] ) } TO partition_new_name;
  ```
  也可以修改分区表的二级分区。
  ```
  ALTER TABLE [ IF EXISTS ] { table_name [*] | ONLY table_name | ONLY ( table_name  )}
      RENAME SUBPARTITION { subpartion_name | FOR ( subpartition_value [, ...] ) } TO subpartition_new_name;
  ```
  
- 重置分区ID的语法。
  ```
  ALTER TABLE [ IF EXISTS ] { table_name [*] | ONLY table_name | ONLY ( table_name  )} RESET PARTITION;
  ```
  
#### 参数说明
- **table_name**
  分区表名。
  取值范围：已存在的分区表名。
  
- **subpartition_name**
  二级分区名。
  取值范围：已存在的二级分区名。
  
- **tablespacename**
  指定分区要移动到哪个表空间。
  取值范围：已存在的表空间名。
  
- **partition_value**
  一级分区键值。
  通过PARTITION FOR ( partition_value \[, ...\] )子句指定的这一组值，可以唯一确定一个一级分区。
  取值范围：需要进行操作的一级分区的分区键的取值范围。
  
- **subpartition_value**
  一级分区键值和二级分区键值。
  通过SUBPARTITION FOR ( subpartition_value \[, ...\] )子句指定的这一组值，可以唯一确定一个二级分区。
  取值范围：对于需要进行操作的二级分区，需要同时有其一级分区分区键和二级分区分区键的取值范围。
  
- **UNUSABLE LOCAL INDEXES**
  设置该分区上的所有索引不可用。
  
- **REBUILD UNUSABLE LOCAL INDEXES**
  重建该分区上的所有索引。
  
- **{ ENABLE \| DISABLE } ROW MOVEMET**
  行迁移开关。
  如果进行UPDATE操作时，更新了元组在分区键上的值，造成了该元组所在分区发生变化，就会根据该开关给出报错信息，或者进行元组在分区间的转移。
  取值范围：
  - ENABLE：打开行迁移开关。
  
  - DISABLE：关闭行迁移开关。
  
  
  默认是打开状态。
  
- **ordinary_table_name**
  进行迁移的普通表的名称。
  取值范围：已存在的普通表名。
  
- **{ WITH \| WITHOUT } VALIDATION**
  在进行数据迁移时，是否检查普通表中的数据满足指定分区的分区键范围。
  取值范围：
  - WITH：对于普通表中的数据要检查是否满足分区的分区键范围，如果有数据不满足，则报错。
  
  - WITHOUT：对于普通表中的数据不检查是否满足分区的分区键范围。
  
  
  默认是WITH状态。
  由于检查比较耗时，特别是当数据量很大的情况下更甚。所以在保证当前普通表中的数据满足分区的分区键范围时，可以加上WITHOUT来指明不进行检查。
  
- **VERBOSE**
  在VALIDATION是WITH状态时，如果检查出普通表有不满足要交换分区的分区键范围的数据，那么把这些数据插入到正确的分区，如果路由不到任何分区，再报错。
  ![](https://support.huaweicloud.com/centralized-devg-v3-gaussdb/public_sys-resources/notice_3.0-zh-cn.png)
  只有在VALIDATION是WITH状态时，才可以指定VERBOSE。
  
- **partition_new_name**
  分区的新名称。
  取值范围：字符串，要符合[标识符命名规范](https://support.huaweicloud.com/centralized-devg-v3-gaussdb/gaussdb-42-0327.html#ZH-CN_TOPIC_0000002235339153__zh-cn_topic_0000002235101877_section1257443811315)。
  
- **subpartition_new_name**
  二级分区的新名称。
  取值范围：字符串，要符合[标识符命名规范](https://support.huaweicloud.com/centralized-devg-v3-gaussdb/gaussdb-42-0327.html#ZH-CN_TOPIC_0000002235339153__zh-cn_topic_0000002235101877_section1257443811315)。
  
- **UPDATE GLOBAL INDEX**
  如果使用该参数，则会更新分区表上的所有全局索引，以确保使用全局索引可以查询出正确的数据；如果不使用该参数，则分区表上的所有全局索引将会失效。
  
 
#### 示例
请参考CREATE TABLE SUBPARTITION的[示例](https://support.huaweicloud.com/centralized-devg-v3-gaussdb/gaussdb-42-0561.html#ZH-CN_TOPIC_0000002200579098__zh-cn_topic_0000002200141176_section3608124119220)。
#### 相关链接
[CREATE TABLE SUBPARTITION](https://support.huaweicloud.com/centralized-devg-v3-gaussdb/gaussdb-42-0561.html#ZH-CN_TOPIC_0000002200579098)，[DROP TABLE](https://support.huaweicloud.com/centralized-devg-v3-gaussdb/gaussdb-42-0609.html#ZH-CN_TOPIC_0000002200419382)
