#ALTER TABLE

# 通用描述

ALTER TABLE用于修改数据库里的表的结构和定义,以及对表进行相关管理操作,包括:

其中,依据LSC表的存储特性,只能对其分区相关属性(但不包括分区索引)进行修改操作(包括增加分区和删除分区等)。

不支持对AC执行ALTER TABLE操作,且不支持对建立了AC的表执行ALTER TABLE操作。

# 语句定义

alter table::=

syntax
ALTER TABLE schema . table_name alter_table_properties alter_column_clause alter_table_partition alter_table_constraint

alter_table_properties::=

syntax
RENAME TO new_table_name row_movement_clause supplemental_table_logging shrink_space_clause lsc_properties_clause logging_clause readonly_clause

row_movement_clause::=

syntax
ENABLE DISABLE ROW MOVEMENT

supplemental_table_logging::=

syntax
add_supplemental_logging_clause drop_supplemental_logging_clause

add_supplemental_logging_clause::=

syntax
ADD SUPPLEMENTAL LOG DATA ( PRIMARY KEY UNIQUE ALL ) COLUMNS

drop_supplemental_logging_clause::=

syntax
DROP SUPPLEMENTAL LOG DATA

shrink_space_clause::=

syntax
SHRINK SPACE COMPACT CASCADE

lsc_properties_clause::=

syntax
enable_xfmr_clause mcol_ttl_clause

enable_xfmr_clause::=

syntax
ENABLE DISABLE TRANSFORM

mcol_ttl_clause::=

syntax
ALTER MCOL TTL timestamp

logging_clause::=

syntax
LOGGING ASYNC NOLOGGING

readonly_clause::=

syntax
READONLY READWRITE

alter_column_clause::=

syntax
add_column_clause drop_column_clause rename_column_clause modify_column_clause

add_column_clause::=

syntax
ADD COLUMN ( column_definition , ) lob_clauses

column_definition::=

syntax
column dataType DEFAULT default_expr inline_constraint

inline_constraint定义

lob_clauses::=

syntax
lob_clause

lob_clause::=

syntax
LOB ( column , ) STORE AS BASICFILE SECUREFILE ( TABLESPACE space_name ENABLE DISABLE STORAGE IN ROW )

drop_column_clause::=

syntax
DROP drop_column

drop_column::=

syntax
COLUMN ( column_name , )

rename_column_clause::=

syntax
RENAME COLUMN old_name TO new_name

modify_column_clause::=

syntax
MODIFY column_name dataType DEFAULT default_expr inline_constraint ,

alter_table_partition::=

syntax
add_table_partition drop_table_partition truncate_table_partiton set_partition_clause modify_partition_clause split_table_partition

add_table_partition::=

syntax
ADD PARTITION partname add_range_partition_clause , PARTITION partname add_list_partition_clause , PARTITION partname add_hash_partition_clause

add_range_partition_clause::=

syntax
range_values_clause table_partition_description

range_values_clause::=

syntax
VALUES LESS THAN ( literal MAXVALUE , )

table_partition_description::=

syntax
TABLESPACE tablespace PCTFREE integer PCTUSED integer INITRANS integer MAXTRANS integer

add_list_partition_clause::=

syntax
list_values_clause table_partition_description

list_values_clause::=

syntax
VALUES ( DEFAULT list_values )

list_values::=

syntax
literal NULL , ( literal NULL , ) ,

add_hash_partition_clause::=

syntax
partition_storage_clause

partition_storage_clause::=

syntax
TABLESPACE tablespace

drop_table_partition::=

syntax
DROP PARTITION partname , update_index_clause

update_index_clause::=

syntax
UPDATE INVALIDATE GLOBAL INDEXES

truncate_table_partition::=

syntax
TRUNCATE PARTITION partname , truncate_part_clause

truncate_part_clause::=

syntax
DROP REUSE STORAGE CASCADE PURGE

set_partition_clause::=

syntax
SET INTERVAL ( expr ) STORE IN ( tablespace , )

modify_partition_clause::=

syntax
MODIFY PARTITION partname shrink_space_clause

split_table_partition::=

syntax
SPLIT PARTITION partname AT ( literal ) INTO ( range_partition_desc , range_partition_desc ) VALUES ( list_values ) INTO ( list_partition_desc , list_partition_desc ) INTO ( range_partition_desc , list_partition_desc , , PARTITION partname table_partition_description ) UPDATE GLOBAL INDEXES

alter_table_constraint::=

syntax
add_constraint drop_constraint modify_constraint enable_disable_constraint

add_constraint::=

syntax
ADD ( out_of_line_constraint , )

out_of_line_constraint定义

drop_constarint::=

syntax
DROP PRIMARY KEY UNIQUE ( column_name , ) CONSTRAINT constraint_name CASCADE KEEP DROP INDEX

modify_constraint::=

syntax
MODIFY PRIMARY KEY UNIQUE ( column_name , ) CONSTRAINT constraint_name ENABLE DISABLE VALIDATE NOVALIDATE CASCADE

enable_disable_constraint::=

syntax
ENABLE DISABLE VALIDATE NOVALIDATE PRIMARY KEY UNIQUE ( column_name , ) CONSTRAINT constraint_name using_index_clause CASCADE KEEP DROP INDEX

# alter_table_properties

该语句用于修改表的一系列属性。

# rename to

该语句用于修改表名,或者开启关闭表的附加日志属性。 修改表名时,指定的新名称不支持为空且必须符合YashanDB的对象命名规范

示例

ALTER TABLE area RENAME TO area_new;
ALTER TABLE area_new RENAME TO area;

# row_movement_clause

该语句用于开启或关闭表的行迁移功能,参考CREATE TABLE中相应功能描述。

分布式暂不支持开启row movement。

示例

--创建一张DISABLE ROW MOVEMENT的分区表
DROP TABLE IF EXISTS orders_info_rowmove;
CREATE TABLE orders_info_rowmove (order_no CHAR(14) NOT NULL,
order_desc VARCHAR2(100),
area CHAR(2),
branch CHAR(4),
order_date DATE DEFAULT SYSDATE NOT NULL,
salesperson CHAR(10),
id NUMBER)
PARTITION BY RANGE (id )
(PARTITION p1 VALUES LESS THAN (800),
PARTITION p2 VALUES LESS THAN (1800),
PARTITION p3 VALUES LESS THAN (2800));
  
--插入数据
INSERT INTO orders_info_rowmove VALUES ('20010102020001','product 001','02','0201',SYSDATE-400,'0001',300);
INSERT INTO orders_info_rowmove VALUES ('20010102020001','product 001','02','0201',SYSDATE-400,'0001',1300);
INSERT INTO orders_info_rowmove VALUES ('20010102020001','product 001','02','0201',SYSDATE-400,'0001',2300);
COMMIT;
  
--查询p1分区的记录
SELECT * FROM orders_info_rowmove PARTITION(p1);
ORDER_NO          ORDER_DESC   AREA  BRANCH ORDER_DATE           SALESPERSON      ID
----------------- ------------ ----- ------ -------------------- ------------- -----
20010102020001    product 001  02    0201   2020-12-06 22:55:32  0001            300
 
--更新分区列值,未开启行迁移时本语句报错
UPDATE orders_info_rowmove SET id=500 WHERE id=1300;
YAS-02209 ROW MOVEMENT is not enabled

--执行开启
ALTER TABLE orders_info_rowmove ENABLE ROW MOVEMENT;
UPDATE orders_info_rowmove SET id=500 WHERE id=1300;
 
--重新查询p1分区的记录,之前在p2分区的数据被移动到了此分区中
SELECT * FROM orders_info_rowmove PARTITION(p1);
ORDER_NO          ORDER_DESC   AREA  BRANCH ORDER_DATE           SALESPERSON      ID
----------------- ------------ ----- ------ -------------------- ------------- -----
20010102020001    product 001  02    0201   2020-12-06 22:55:32  0001            300
20010102020001    product 001  02    0201   2020-12-06 22:55:32  0001            500

--跨分区更新数据结束后,建议关闭行迁移
ALTER TABLE orders_info_rowmove DISABLE ROW MOVEMENT;

# supplemental_table_logging

该语句用于开启或关闭附加日志属性。

分布式部署中用户无法执行此操作。

# add_supplemental_logging_clause

该语句用于为该表开启附加日志属性,开启附加日志后,对该表执行DML,DDL类型语句,将会在redo日志里记录额外的信息,以便逻辑日志解析工具能从redo日志里解析出DML和DDL语句。尤其是UPDATE和DELETE语句,会额外记录目标行的主键,唯一键或整行(除LOB列)数据到redo日志里,因此对数据库性能有影响。

附加日志有三种类型:

  • PRIMARY KEY:在UPDATE,DELETE的redo日志中,记录该行的主键列的值。
  • UNIQUE:在UPDATE,DELETE的redo日志中,记录该行的非空的唯一索引列的值。
  • ALL:在UPDATE,DELETE的redo日志中,记录该行的所有列(LOB类型除外)的值。

附加日志约束项:

  • 不支持对已开启附加日志的表重复执行ADD SUPPLEMENTAL LOG操作。
  • 不支持对附加日志类型为PRIMARY KEY或UNIQUE的表,删除附加日志依赖的索引列。
  • 不支持对没有主键的表,开启PRIMARY KEY类型的附加日志。
  • 不支持对没有非空唯一索引列的表,开启UNIQUE类型的附加日志。
  • 不支持对开启附加日志的表,执行长度超过32K的DDL语句。
  • 不支持对使用了字典编码的TAC表开启附加日志。

通过DBA_LOG_GROUPS/ALL_LOG_GROUPS/USER_LOG_GROUPS视图可以查看当前已开启的附加日志信息。

示例

ALTER TABLE area ADD SUPPLEMENTAL LOG DATA (PRIMARY KEY) COLUMNS;
ALTER TABLE area ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;

# drop_supplemental_logging_clause

该语句用于关闭表上的附加日志属性。

示例

ALTER TABLE area DROP SUPPLEMENTAL LOG DATA;

# shrink_space_clause

该功能用于对表或分区进行收缩,将数据存储得紧凑些,降低segment的高水位线,释放空闲出来的连续的extent。本语句只作用于HEAP表。

需注意的是,由于收缩数据涉及到物理位置变更,执行本操作前必须开启行迁移,参考row_movement_clause

COMPACT

指定此关键字表示只将数据存储紧凑,降低水位线,并不释放空出来的extent。

CASCADE

指定此关键字表示在收缩表的同时,对其上索引也进行收缩,语法兼容,无实际意义。

示例

ALTER TABLE orders_info SHRINK SPACE;
ALTER TABLE orders_info SHRINK SPACE COMPACT;
ALTER TABLE orders_info SHRINK SPACE COMPACT CASCADE;

# lsc_properties_clause

该语句只用于修改LSC表的相关属性,对其他类型表执行这些修改将会报错。

分布式部署中用户无法执行此操作。

# enable_xfmr_clause

该语句用于控制LSC表的可变数据缓冲区转换。默认情况下,LSC的可变数据依据一定机制转换为不可变数据存储,可变数据缓冲区的数据被删除,转移到不可变数据内,这段期间如正对表执行闪回查询,将会返回snapshot too old错误。

当通过DISABLE TRANSFORM打开此开关后,LSC表的可变数据缓冲区将不会转换,而被用于保存事务信息,防止可变数据被转换后事务信息被清除。

需注意的是,DISABLE TRANSFORM后,可变数据缓冲区无法被转换,因此不建议本开关长时间开启,而应在需求完成后尽快执行ENABLE TRANSFORM。

示例

ALTER TABLE orders_info ENABLE TRANSFORM;
ALTER TABLE orders_info DISABLE TRANSFORM;

# mcol_ttl_clause

该语句用于修改LSC表的可变生命周期,其含义请参考CREATE TABLE中对应语句描述。

示例

--将finance_info的可变生命周期由1个月修改为10天
ALTER TABLE finance_info ALTER MCOL TTL '10' DAY;

--area表创建时未设置可变生命周期,将其设为10年
ALTER TABLE area ALTER MCOL TTL '10' YEAR(9);

# logging_clause

本语句用于修改HEAP表的logging属性,logging属性用于指定表记录日志的方式,在TAC/LSC表上执行本语句无实际含义。

分布式部署中用户无法执行此操作。

# logging

该语句用于将表转为logging属性,即对该表的所有操作记录日志。

本语句遵循如下规则:

  • 当表原来就是logging属性时,直接返回成功。
  • 当表原来是nologging属性时,系统将执行一次全量checkpoint,将数据写盘并修改flushback,最后修改表的logging属性。
# logging async

该语句用于异步将表转为logging属性。启动新线程完成表模式转化的操作从而不阻塞主线程工作。

注意当客户端返回成功时并不保证转换一定成功,只代表启动线程成功。后续转换仍有可能失败。转换结果通过运行日志记载。

同时在异步转换表的过程中存在以下约束限制:

  • 不支持对转换中的表做任意DML操作。
  • 不支持对转换中的表做除了DROP以外的任意DDL操作。
# nologging

该语句用于将表转为nologging属性,即对该表的大多数操作将不记录日志。此属性只建议在数据迁移场景打开。

本语句遵循如下规则:

  • 当表原来就是nologging属性时,直接返回成功。
  • 当表原来是logging属性时,会更改表的logging属性为nologging。
  • 在表被置为nologging后,对其进行插入操作只会记录必要的redo和undo(例如segment相关的redo),其他redo会被忽略。

Note

由于nologging表缺少redo,如数据没有写盘数据库就关闭将会导致数据丢失,因此在数据库重启时会检测数据库内是否存在nologging表,若存在则将其标记为corrupted并阻止除drop和truncate外的任何操作。

将表置为nologging存在如下约束限制:

  • 不支持对临时表设置nologging属性。
  • 不支持对存在备机的数据库中的表设置nologging属性。
  • 不支持对nologging表执行并发操作。
  • 仅支持对nologging表执行插入和导入操作。
  • 不支持对nologging表执行回滚操作。
  • 不支持对nologging表执行create index online或者rebuild index online操作。

示例

ALTER TABLE area LOGGING;
ALTER TABLE area NOLOGGING;

# readonly_clause

语法兼容,无实际含义。

# alter_column_clause

该语句用于指定对表的列字段的操作。

# add_column_clause

该语句用于为HEAP/TAC表增加列字段,同时增加多项时在()中以,分隔。COLUMN关键字可省略。

# column_definition

为表增加一个新的列字段,并对增加的列字段进行数据类型(DataType)、缺省值(DEFAULT)、行内约束(inline_constraint)等定义。

对非空表增加定义了NOT NULL约束的列字段时,必须同时为其指定缺省值,否则将提示错误。

# datatype

指定列字段的数据类型。YashanDB的数据类型描述详见数据类型章节。

其中,数据类型指定为LOB/JSON类型时,可通过lob_clauses子句指定其存储属性。

YashanDB不支持将新增的列字段指定为Nested Table UDT类型。

# default

为增加的列字段指定一个符合该列字段数据类型的缺省值,default_expr可以为字面量、运算式、函数等表达式。

当指定了缺省值时,系统将对表中现有行的该列字段填充该缺省值。

分布式部署中用户无法在为增加的列字段指定缺省值。

# inline_constraint

该语句用于在增加列字段时同时定义表的行内约束项。关于约束项的详细描述请参考通用SQL语法constraint

其中,对于单机HEAP表,不支持为临时表建立FOREIGN KEY约束,也不支持为其他表建立到临时表的FOREIGN KEY约束。分布式部署中不支持建立FOREIGN KEY约束。

分布式部署中新增唯一约束(或主键约束)时必须包括分布键,否则返回错误。在不指定的情况下,分布表默认将首个列字段作为分布键,分布键相关资料见CREATE TABLE章节中分布键相关内容描述。

示例

--单机TAC表
--为area表新增address非空字段
ALTER TABLE area ADD (address VARCHAR(30) NOT NULL DEFAULT 'no address');

SELECT area_no,address FROM area;
AREA_NO ADDRESS                           
------- --------------------------------- 
01      no address                       
02      no address                       
03      no address                       
04      no address                       
05      no address

--分布式TAC表
--创建TAC表student
CREATE TABLE student(id INT,name VARCHAR2(60));

--为student表中的name字段(非分布键)新增主键约束
ALTER TABLE student ADD PRIMARY KEY(name);
YAS-02125 distribute key is not a subset of unique constraint keys

--为student表中的id字段(分布键)新增主键约束
ALTER TABLE student ADD PRIMARY KEY(id);

# lob_clause

该语句为增加的LOB/JSON字段指定存储属性,语法同CREATE TABLE中lob_clause子句描述。

# drop_column_clause

该语句用于删除HEAP/TAC表中已有的列字段或约束项。

# drop_column

删除指定的列字段,指定多个列字段用,分隔。COLUMN关键字可省略。

分布式部署中无法删除分布键所在的列字段。

该语句遵循如下规则:

  • 不支持删除表中的所有列字段。
  • 如果删除的列字段已被定义为主键组合中的一项,则不允许删除此列。但可以删除整个主键对应的列组合。
  • 如果删除的列字段已被定义为索引对象中的一项,则删除此列字段后,其对应的索引对象也被删除。

示例

--单机TAC表
--创建area_pri表定义组合主键area_no+DHQ
CREATE TABLE area_pri AS SELECT * FROM area;
ALTER TABLE area_pri ADD PRIMARY KEY(area_no,DHQ);
   
--删除部分主键字段返回错误
ALTER TABLE area_pri DROP COLUMN(area_no);
YAS-02132 can not drop column referenced in a multi-column constraint
   
--可以删除全部主键字段
ALTER TABLE area_pri DROP COLUMN(area_no,DHQ);
   
--删除表中最后的一个字段时返回错误
ALTER TABLE area_pri DROP COLUMN area_name;
YAS-02054 cannot drop all columns in a table

--分布式TAC表
--创建TAC表student
CREATE TABLE student(id INT,name VARCHAR2(60),school VARCHAR2(60));

--可以删除非分布键字段
ALTER TABLE student DROP COLUMN(name);

--删除分布键所在字段返回错误
ALTER TABLE student DROP COLUMN(id);
YAS-02304 cannot drop distribute key column in a table

# rename_column_clause

该语句用于对列字段进行重命名,指定的新名称不支持为空且必须符合YashanDB的对象命名规范

示例

ALTER TABLE branches RENAME branch_no TO branchno;

# modify_column_clause

该语句用于对列字段的数据类型、默认值、约束等属性进行修改,同时修改多个列字段时需在()中以,分隔。

YashanDB支持同时对列字段修改多个属性,但需遵循与CREATE TABLE相同的顺序要求,否则系统提示错误;当同时修改多个约束项时,对这些约束项无顺序要求。

# datatype

修改列字段的数据类型为YashanDB认可的数据类型(查看YashanDB的数据类型描述)。

对此类修改系统将区分如下不同场景进行不同的处理:

  1. 不允许对LOB/JSON/UDT列进行数据类型修改,也不允许将列数据类型修改为LOB/JSON/UDT类型。
  2. 对于被定义了外键约束的列字段,包括子表中的列字段和父表中的列字段,不允许修改其数据类型。
  3. 对于被定义了索引的列字段,如果表中无数据,允许将数据类型修改为除LOB/JSON/UDT外的数据类型;非空表则不允许修改该列字段的数据类型。
  4. 对于使用了字典编码的TAC表列字段,任何情况都不允许数据类型修改为除字符型外的所有类型。字符型的修改请参照5中的说明。
  5. 对于被定义为分区键、分布键、函数索引或访问约束(ACCESS CONSTRAINT)的列字段,不允许修改其数据类型。
  6. 除上述情况外,当表中无数据,或者该列字段上所有数据都为NULL时,允许将数据类型修改为除LOB/JSON/UDT外的数据类型;对于非空列字段的数据类型修改存在如下规则:
    • 不支持跨数据大类修改,例如不支持将数值型修改为字符型。
    • 不支持将CHAR/VARCHAR类型修改成NCHAR/NVARCHAR类型,也不支持将NCHAR/NVARCHAR类型修改成CHAR/VARCHAR类型。
    • 同一数据大类中,按值域、精度、长度等属性可以将数据类型从小向大修改,例如不支持将INT修改为指定了精度的NUMBER,不支持将DATE修改为TIME。除字符型外的其他类型均不允许数据类型从大向小修改。
    • 字符型的数据类型存在长度大小,当从大向小修改时,必须保证该列现有数据长度均未超过修改的值,否则提示错误。
    • 字符型的数据类型根据长度不同,有普通字符串组织方式存储和LOB方式存储的区别(具体区别查看YashanDB的字符类型描述),这两种不同存储组织方式的字符串不允许互相修改。
# default

修改列字段的缺省值,default_expr可以为字面量、运算式、函数等表达式。

示例

ALTER TABLE area MODIFY area_no DEFAULT 3;
# inline_constraint

修改列字段的约束项,遵循通用constraint里的行内约束所定义语法要求。

# modfiy null/not null

修改NOT NULL约束项:

  • 不支持对未定义NOT NULL约束项的列字段执行modify NULL。
  • 不支持对已定义NOT NULL约束项的列字段执行modify NOT NULL。
  • 不支持对已存在NULL数据的列字段执行modify NOT NULL。
  • 不支持对已定义ON DELETE SET NULL或ON UPDATE SET NULL外键的列字段执行modify NOT NULL。
# modify unique

修改UNIQUE约束项:

  • 不支持对已定义UNIQUE约束项的列字段执行modify UNIQUE。
  • 不支持对已存在重复数据的列字段执行modify UNIQUE。
  • 不支持对多个列字段同时执行modify UNIQUE。
# modify primary key

修改主键约束项:

  • 不支持对已有主键的表执行任意列字段的modify PRIMARY KEY。
  • 不支持对已定义UNIQUE约束项的列字段执行modify PRIMARY KEY。
  • 不支持对不符合创建主键要求的列字段执行modify PRIMARY KEY,创建主键的要求请参考constraint描述。
# modify check

修改CHECK约束项:

  • 如新的CHECK与表中现有其他的CHECK冲突,无法执行修改。
  • 如表中现有的数据不符合CHECK,无法执行修改。
# modfiy foreign key

修改外键约束项:

  • 不支持对不符合创建外键要求的列字段执行modify FOREIGN KEY,创建外键的要求请参考constraint描述。

示例

--修改branches非空表的branch_no非空列字段数据类型,只能修改为字符型
ALTER TABLE branches MODIFY branch_no VARCHAR(5);

--修改branches表的branch_no和branch_name为UNIQUE,无法同时修改多个列字段为UNIQUE,返回错误
ALTER TABLE branches MODIFY (branch_no,branch_name) UNIQUE;
YAS-04297 invalid ALTER TABLE option

--修改branches表的address列字段的缺省值
ALTER TABLE branches MODIFY address DEFAULT 'no address';

--修改branches表的area_no列字段为非空
ALTER TABLE branches MODIFY area_no NOT NULL;

# alter_table_partition

该语句用于指定对表的分区的操作。

如在表上已建立了分区索引,当执行新增分区和删除分区的操作时,系统也会同时新增索引分区和删除索引分区。

# add_table_partition

该语句用于对表增加一个新的分区(Partition)。

不同类型的表可增加的分区类型不同:

  • HEAP表支持增加范围(Range)、列表(List)和哈希(Hash)类型的分区。
  • TAC表支持增加范围(Range)、列表(List)和哈希(Hash)类型的分区。
  • LSC表支持增加范围(Range)和列表(List)类型的分区。

# add_range_partition_clause

增加范围类型的分区,只能在当前最大分区界值之上建立分区,如表的最大分区界值被设为MAXVALUE,则不允许增加分区。

定义了INTERVAL的范围分区表,其分区由系统自动维护,不可以用本语句为其增加分区。

# table_partition_description

该语句用于为新增的分区指定所属表空间(缺省为表所属表空间),及PCTFREE/PCTUSED/INITRANS/MAXTRANS等属性。

示例

--sales_info_range为一张范围分区表,已有p_sales_info_range_1(VALUES LESS THAN('2011'))、p_sales_info_range_2(VALUES LESS THAN('2021'))和p_sales_info_range_3(VALUES LESS THAN('2031'))三个分区。
ALTER TABLE sales_info_range ADD PARTITION p_sales_info_range_4 VALUES LESS THAN('2038');

# add_list_partition_clause

增加列表类型的分区,如表已在列表值里定义了DEFAULT,则不允许增加分区。

分区列表值可以指定为通用表达式(expr)。

# table_partition_description

该语句用于为新增的分区指定所属表空间(缺省为表所属表空间),及PCTFREE/PCTUSED/INITRANS/MAXTRANS等属性。

示例

--sales_info_list为一张列表分区表,已有p_sales_info_list_1(VALUES('2018','2019'))、p_sales_info_list_2(VALUES('2021'))两个分区。
ALTER TABLE sales_info_list ADD PARTITION p_sales_info_list_3 VALUES ('2022');
ALTER TABLE sales_info_list ADD PARTITION p_sales_info_list_4 VALUES (TO_CHAR(2023));

# add_hash_partition_clause

增加哈希类型的分区。本语句只适用于HEAP/TAC表。

新增分区的PCTFREE/PCTUSED/INITRANS/MAXTRANS等属性从表上继承,不允许指定。

# partition_storage_clause

该语句用于为新增的分区指定所属表空间(缺省为表所属表空间)。

示例

--sales_info_hash为一张哈希分区表,已有p_sales_info_hash_1和p_sales_info_hash_2两个分区,下面将为其增加2个分区,使分区总数为2^2。
ALTER TABLE sales_info_hash ADD PARTITION p_sales_info_hash_3;
ALTER TABLE sales_info_hash ADD PARTITION p_sales_info_hash_4;

# drop_table_partition

该语句用于删除表的分区,同时删除分区里的数据。指定多个分区用,分隔。

该语句存在如下约束限制:

  • 删除分区时,不支持将表上的所有分区都删除。
  • 不支持删除哈希类型分区。
  • 在表的分区被删除时,对应的索引分区也会被删除。
  • 对于范围类型的分区,删除分区后其分区界值将会向相邻大一级分区合并,这样符合此被删除分区界值范围的新增表数据将进入相邻分区中,如不存在相邻大一级分区则数据无法再插入成功。

示例

--sales_info_range为一张范围分区表
SELECT * FROM sales_info_range;
YEAR  MONTH BRANCH PRODUCT      QUANTITY      AMOUNT SALSPERSON  
----- ----- ------ --------- ----------- ----------- -------------
2001  01    0201   11001              30         500 0201010011 
2000  12    0102   11001              20         300            
2015  11    0101   11001              20         300            
2015  03    0102   11001              20         300            
2021  10    0101   11001              20         300            
2021  05    0101   11001              40         600       
   
--分区及数据被删除
ALTER TABLE sales_info_range DROP PARTITION p_sales_info_range_2;
SELECT * FROM sales_info_range;
YEAR  MONTH BRANCH PRODUCT      QUANTITY      AMOUNT SALSPERSON  
----- ----- ------ --------- ----------- ----------- -------------
2001  01    0201   11001              30         500 0201010011 
2000  12    0102   11001              20         300            
2021  10    0101   11001              20         300            
2021  05    0101   11001              40         600 
   
INSERT INTO sales_info_range VALUES ('2015','03','0101','11001',20,300,'');
SELECT * FROM sales_info_range PARTITION(p_sales_info_range_3);
YEAR  MONTH BRANCH PRODUCT      QUANTITY      AMOUNT SALSPERSON  
----- ----- ------ --------- ----------- ----------- -------------
2021  10    0101   11001              20         300            
2021  05    0101   11001              40         600            
2015  03    0101   11001              20         300

# update_index_clause

指定分区被删除后,对表上的全局索引(Global Index)的处理,默认为INVALIDATE。

  • INVALIDATE GLOBAL INDEXES:将全局索引全部失效,不可用。
  • UPDAET GLOBAL INDEXES:将全局索引进行更新,仍然可用。

示例

ALTER TABLE sales_info_list DROP PARTITION p_sales_info_list_4 UPDATE GLOBAL INDEXES;

# truncate_table_partition

该语句用于删除分区里的所有数据,指定删除多个分区数据用,分隔。

该语句同时删除分区对应的本地索引(Local Index)。

# truncate_part_clause

该语句用于指定删除分区数据的方式。

# drop|reuse storage

指定删除分区数据后释放|保留其存储空间。

# cascade

如某张分区表为被子表定义了外键约束的父表,且要删除的分区数据在子表对应列字段值中已经存在,则指定CASCADE将同时删除子表中对应的数据行。本语句只作用于HEAP表。

# purge

当回收站开启时,被删除的数据默认将进入回收站,指定本关键字则表示数据被彻底删除,不进入回收站。本语句只作用于HEAP表。

示例

ALTER TABLE sales_info TRUNCATE PARTITION p_sales_info_1 DROP STORAGE;

# set_partition_clause

该语句只作用于HEAP表,且只针对范围分区表,用于指定INTERVAL和非INTERVAL分区类型之间的相互转换。转换分区类型不会影响表中原有的数据,新增加的数据则按转换后的分区类型特点存储。

分布式部署中用户无法执行此操作。

# transfer range to range-interval

将非INTERVAL的范围分区转换为INTERVAL范围分区,语法如下:

ALTER TABLE table_name SET INTERVAL(expr);

建立INTERVAL分区的要求和规则与CREATE TABLE里的interval_clause中描述一致,不符合时无法成功转换。

示例

--将sales_info_range表的分区类型转换为INTERVAL类型
ALTER TABLE sales_info_range SET INTERVAL(2);

--对于超过现有分区界值的数据,系统将创建新分区且类型为INTERVAL
INSERT INTO sales_info_range VALUES ('2031','05','0101','11001',40,600,'');
COMMIT;
SELECT partition_name,tablespace_name,high_value
FROM USER_TAB_PARTITIONS 
WHERE table_name='SALES_INFO_RANGE'
ORDER BY partition_name;
PARTITION_NAME          TABLESPACE_NAME  HIGH_VALUE  
----------------------- ---------------- ----------- 
P_SALES_INFO_RANGE_1    USERS            '2011'     
P_SALES_INFO_RANGE_2    USERS            '2021'     
P_SALES_INFO_RANGE_3    USERS            '2031'     
SYS_P21                 USERS            2033       
# modify range-interval

修改INTERVAL分区的属性。

# 修改interval值

调整INTERVAL为新的值,之后插入的数据将按新值创建分区。

本功能语法为:

ALTER TABLE table_name SET INTERVAL(expr);

相关要求和规则与上述transfer range to range-interval一致。

# 修改分区表空间

指定INTERVAL分区的表空间,指定多个以,分隔,之后所有新创建的分区将循环使用这些表空间。

本功能语法为:

ALTER TABLE table_name SET STORE IN(tablespace_name, ...);

只能对INTERVAL类型的范围分区表执行此操作,否则系统报错。

示例

--对上例中的INTERVAL分区表修改INTERVAL和表空间
ALTER TABLE sales_info_range SET INTERVAL(3);
ALTER TABLE sales_info_range SET STORE IN(sales_tb1,sales_tb2);
INSERT INTO sales_info_range VALUES ('2033','05','0101','11001',40,600,'');
INSERT INTO sales_info_range VALUES ('2043','05','0101','11001',40,600,'');
COMMIT;
SELECT partition_name,tablespace_name,high_value
FROM USER_TAB_PARTITIONS 
WHERE table_name='SALES_INFO_RANGE'
ORDER BY partition_name;
PARTITION_NAME          TABLESPACE_NAME      HIGH_VALUE  
----------------------- -------------------- ----------- 
P_SALES_INFO_RANGE_1    USERS                '2011'     
P_SALES_INFO_RANGE_2    USERS                '2021'     
P_SALES_INFO_RANGE_3    USERS                '2031'     
SYS_P21                 USERS                2033       
SYS_P22                 SALES_TB1            2036       
SYS_P23                 SALES_TB2            2045  
# transfer range-interval to range

将INTERVAL范围分区转换为非INTERVAL的范围分区,语法如下:

ALTER TABLE table_name SET INTERVAL();

示例

--将上例中的INTERVAL分区表修改为非INTERVAL的范围分区表
ALTER TABLE sales_info_range SET INTERVAL();

# modify_partition_clause

该语句用于对表分区进行空间收缩,其操作与对表的收缩操作一致,请参考shrink_space_clause

示例

ALTER TABLE orders_info MODIFY PARTITION p_orders_info_1 SHRINK SPACE COMPACT CASCADE;

# split_table_partition

该语句能将一个范围或者列表分区重新划分为多个分区。当一个分区过于臃肿影响到了查询、备份等性能时,可以考虑SPLIT PARTITION。

该语句须遵循如下限制:

  • LSC表暂不支持SPLIT PARTITION。
  • 仅支持在单机部署中执行。
  • UPDATE GLOBAL INDEXES为语法兼容,SPLIT PARTITION后会失效全局索引,请SPLIT后重建全局索引。
  • 若指定UPDATE INDEXES,则SPLIT PARTITION后不会失效LOCAL索引,会失效全局索引。
  • 未指定分区名的表分区、索引分区、LOB分区会按照SYS_Pn的格式自动生成分区名。
# split at (literal) into

该语句根据指定的字面量将一个范围分区划分为两个范围分区,仅适用于范围分区。

# literal

划分值,该值须位于被划分的分区范围内,否则返回错误。

# range_partition_desc

该语句用于指定划分后两个范围分区的名称,其中一个分区名可保留原分区名称,另一分区名不可与已有的分区名称重复。

新范围分区上下限分别为[原范围分区下限,literal][literal,原范围分区上限]

-- split range分区
DROP TABLE IF EXISTS split_range_part;
CREATE TABLE split_range_part(c1 INT)
PARTITION BY RANGE(c1)
(PARTITION p1 VALUES LESS than(100),
PARTITION p2 VALUES LESS than(200),
PARTITION p3 VALUES LESS than(300),
PARTITION p4 VALUES LESS than(MAXVALUE));
-- 将p4 split出p4和p5两个分区,新p4的分区边界值为350,p5的分区边界值为maxvalue
ALTER TABLE split_range_part split PARTITION p4 at(350) INTO (PARTITION p4, PARTITION p5);
# split values (list_values) into

该语句根据指定的列表内容将一个列表分区划分为两个列表分区,仅适用于列表分区。

# list_values

划分的列表内容,其中的值须包含在被划分的列表分区内,否则返回错误。

# list_partition_desc

该语句用于指定划分后两个列表分区的名称,其中一个分区名可保留原分区名称,另一分区名不可与已有的分区名称重复。

划分后的首个列表分区包含list_values中所有值,其余值保存在第二个列表分区中。

示例

-- split list分区
DROP TABLE IF EXISTS split_list_part;
CREATE TABLE split_list_part(c1 INT)
PARTITION BY LIST(c1)
(PARTITION p1 VALUES (100, 150, 170),
PARTITION p2 VALUES (200, 250, 280),
PARTITION p3 VALUES (300, 400),
PARTITION p4 VALUES (DEFAULT));
-- 将p4 split出p4和p5两个分区,新p4分区仅包含值350,p5分区包含default中除350之外所有值
ALTER TABLE split_list_part split PARTITION p4 VALUES(350) INTO (PARTITION p4, PARTITION p5);
# split into (range/list_partition_desc)

该语句可将范围分区或列表分区根据指定内容划分为多个分区,适用于范围分区和列表分区。

# range_partition_desc|list_partition_desc

该语句用于指定划分后的分区具体信息,包括分区名称、类型和分区值,新分区类型须与原分区类型保持一致,多个分区间使用,进行分隔。

划分后的其中一个分区名可保留原分区名称,其余分区名不可与已有的分区名称重复。

# partition partname table_partition_description

该语句用于指定包含所有剩余值的分区名称及信息,名称不可与已有分区的名称重复。

示例

-- split list分区
DROP TABLE IF EXISTS split_list_part;
CREATE TABLE split_list_part(c1 INT)
PARTITION BY LIST(c1)
(PARTITION p1 VALUES (100, 150, 170),
PARTITION p2 VALUES (200, 250, 280),
PARTITION p3 VALUES (300, 400),
PARTITION p4 VALUES (DEFAULT));
-- 使用split into语法
ALTER TABLE split_list_part split PARTITION p4 INTO (PARTITION p4 VALUES(350), PARTITION p5);

-- split range分区
DROP TABLE IF EXISTS split_range_part;
CREATE TABLE split_range_part(c1 INT)
PARTITION BY RANGE(c1)
(PARTITION p1 VALUES LESS than(100),
PARTITION p2 VALUES LESS than(200),
PARTITION p3 VALUES LESS than(300),
PARTITION p4 VALUES LESS than(MAXVALUE));
-- 使用split into语法
ALTER TABLE split_range_part split PARTITION p4 INTO (PARTITION p4 VALUES LESS than(350), PARTITION p5);

# alter_table_constraint

该语句用于指定对表上的约束的操作包括对添加约束、删除约束、修改约束和停用或启用约束。

# add_constraint

该语句用于对HEAP/TAC表添加约束,同时增加多项在()中以,分隔。

# out_of_line_constraint

约束项,关于约束项的详细描述请参考通用SQL语法constraint

# drop_constraint

该语句用于删除约束项。

如某个约束项在其创建时未指定名称,可以从系统提供视图(如USER_CONSTRAINTS)中查询到其默认名称后再执行删除操作。

删除UNIQUE/PRIMARY KEY约束项会自动删除对应的索引。

示例

--以单机HEAP表为例
ALTER TABLE branches DROP CONSTRAINT c_branches_1;
ALTER TABLE branches DROP PRIMARY KEY;

# modify_constraint

该语句用于修改约束项的属性。

分布式部署中用户无法执行此操作。

# 约束项名称

指定用于修改属性的约束项,可按如下三种方式指定(指定的约束项不存在时报错):

  • 对于主键约束项,以PRIMARY KEY表示即可。
  • 对于唯一约束项,以UNIQUE表示即可,但需同时指定该约束项对应的列。
  • 以CONSTRAINT 约束项名称表示,从系统视图(例如USER_CONSTRAINTS)可获得表上所有的约束项名称。
# enable|disable

启用或停用指定的约束项(含义见constraint中的ENABLE|DISABLE描述)。

对于存在子表外键关联的约束项,指定DISABLE将无法成功停用,除非同时指定CASCADE。

在指定ENABLE启用约束项时,如表中现有数据无法满足约束规则,则启用失败,除非同时指定NOVALIDATE(但对于主键/唯一/NOT NULL约束项无效)。

# validate|novalidate

启用或停用约束检查(含义见constraint中的VALIDATE|NOVALIDATE描述)。

本关键字可省略,则对ENABLE操作默认为VALIDATE,对DISABLE操作默认为NOVALIDATE。

# cascade

指定CASCADE表示在DISABLE一个存在子表外键关联的约束项时,同时对子表的外键约束项执行DISABLE。

需注意的是,在重新ENABLE父表的该约束项时,即使指定CASCADE也不会对子表的外键约束项执行ENABLE,用户需手工操作。

本关键字可省略,则在DISABLE一个存在子表外键关联的约束项时默认不会对子表的外键约束项执行DISABLE,而是进行错误提示。

--停用area表的主键约束,同时停用子表上的外键约束
ALTER TABLE area MODIFY PRIMARY KEY DISABLE CASCADE;

--在branches表上创建不启用的唯一约束,之后启用
ALTER TABLE branches ADD UNIQUE(branch_no, area_no) DISABLE;
ALTER TABLE branches MODIFY UNIQUE(branch_no, area_no) ENABLE;

--以下例句所涉及表为单机HEAP表
--停用branches表的area_no外键约束
ALTER TABLE branches MODIFY CONSTRAINT c_branches_1 DISABLE;
--修改area_no为在area表中不存在的值
UPDATE branches SET area_no='99' WHERE area_no='01';
COMMIT;
--启用branches表的area_no外键约束,但不启用约束检查,则可以启用成功
ALTER TABLE branches MODIFY CONSTRAINT c_branches_1 ENABLE NOVALIDATE;

# enable_disable_constraint

该语句用于启用或者停用表上的某个约束项,拥有与modify_constraint子句除MODIFY外相同的关键字和含义,但顺序不相同,例如:

--modify_constraint中的如下例句:
ALTER TABLE area MODIFY PRIMARY KEY DISABLE CASCADE;
ALTER TABLE branches MODIFY UNIQUE(branch_no, area_no) ENABLE;
ALTER TABLE branches MODIFY CONSTRAINT SYS_C_17 ENABLE NOVALIDATE;

--在enable_disable_constraint中可以如下表示:
ALTER TABLE area DISABLE PRIMARY KEY CASCADE;
ALTER TABLE branches ENABLE UNIQUE(branch_no, area_no);
ALTER TABLE branches ENABLE NOVALIDATE CONSTRAINT c_branches_1;

同时,本语句还提供如下与索引相关的语法选项(针对主键/唯一约束项):

  • using_index_clause

  • (KEEP|DROP) INDEX

默认情况下,停用主键/唯一约束项会自动删除对应的索引,启用主键/唯一约束项会自动复用或者创建索引,上述两个选项用于对此情况进行人工干预。

# using_index_clause

在启用主键/唯一约束项时,使用本语句可对系统自动复用或创建的索引进行人工指定,详细语法定义和描述见constraint中的using_index_clause。

# (keep|drop) index

在停用主键/唯一约束项时,使用KEEP INDEX可指定不删除对应的索引,使用DROP INDEX则同默认情况,即删除对应的索引。

示例

--停用主键但保留对应索引
ALTER TABLE area DISABLE PRIMARY KEY CASCADE KEEP INDEX;

--停用主键同时删除对应索引
ALTER TABLE area DISABLE PRIMARY KEY CASCADE DROP INDEX;
pdf-btn 下载文档
copy-btn 复制链接