#ALTER TABLE
# 通用描述
ALTER TABLE用于修改数据库里的表的结构和定义,以及对表进行相关管理操作,包括:
- 表更名
- 修改列
- 修改分区
- 修改约束
- 开启和关闭行迁移(row movment)
- 开启和关闭附加日志(supplemental logging)
- 开启和关闭redo日志(nologging)
- 空间收缩(shrink space)
- LSC表的后台数据转换选项开关(data transformer)
- LSC表的可变数据生命周期(MCOL time to live)
- LSC表开启或关闭MCOL排序 (MCOL order by)
- LSC表的强制转换(force xfmr)
其中,依据LSC表的存储特性,只能对其分区相关属性(但不包括分区索引)进行修改操作(包括增加分区和删除分区等)。
不能对AC对象以及AC对象的源表执行ALTER TABLE操作。
# 语句定义
alter table::=
add_supplemental_logging_clause::=
drop_supplemental_logging_clause::=
lob_clauses::=
lob_clause::=
drop_column::=
table_partition_description::=
list_values::=
truncate_table_subpartition::=
syntax::= RECLAIM SEGMENT [PRIMARY_SPACE tablespace_name PARTITION partition_name] TABLESPACE tablespace_name [OBJNO_REUSE object_id SEG_FILE file_id SEG_BLOCK block_id] [COLSEGS "(" DATAOBJ data_objectid TYPE type ID id ENTRY entry FLAG flag ")"]
[XFMRS "(" DATAOBJ data_objectid TYPE type PRIORITY priority SRCID srcid CTX_SIZE size CTX ctx ")"]
[SLICE_ID_MAP "(" LOGIC_ID logic_id DATAOID data_objectid SLICE_ID slice_id ")"]
[LOBS "(" lob_col [OBJNO_REUSE object_id SEG_FILE file_id SEG_BLOCK block_id ] INDEX [OBJNO_REUSE object_id SEG_FILE file_id SEG_BLOCK block_id ] ")"] [AUXSEGS "(" AUXENTRY entry)]
# 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中相应功能描述。
示例(单机HEAP表、单机TAC表)
-- 创建一张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 order_no,order_desc,area,branch,order_date,salesperson,id 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 order_no,order_desc,area,branch,order_date,salesperson,id 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;
示例(分布式TAC表)
-- 创建一张DISABLE ROW MOVEMENT的TAC表
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 HASH (area)
SUBPARTITION BY RANGE (id)
SUBPARTITION TEMPLATE(
SUBPARTITION sp1 VALUES LESS THAN (800),
SUBPARTITION sp2 VALUES LESS THAN (1800),
SUBPARTITION sp3 VALUES LESS THAN (2800))
(PARTITION p1,
PARTITION p2,
PARTITION p3,
PARTITION p4,
PARTITION p5,
PARTITION p6,
PARTITION p7,
PARTITION p8,
PARTITION p9,
PARTITION p10,
PARTITION p11,
PARTITION p12,
PARTITION p13,
PARTITION p14,
PARTITION p15,
PARTITION p16,
PARTITION p17,
PARTITION p18,
PARTITION p19,
PARTITION p20,
PARTITION p21);
-- 插入数据
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中sp1子分区的记录(由于分布式一级分区为HASH分区,实际结果可能与本例中结果不同)
SELECT order_no,order_desc,area,branch,order_date,salesperson,id FROM orders_info_rowmove SUBPARTITION(p1_sp1);
ORDER_NO ORDER_DESC AREA BRANCH ORDER_DATE SALESPERSON ID
----------------- ---------------------------------------------------------------- ----- ------ -------------------------------- ------------- -----------
20010102020001 product 001 02 0201 2022-08-21 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中sp1子分区的记录,之前在sp2子分区的数据被移动到了此分区中
SELECT order_no,order_desc,area,branch,order_date,salesperson,id FROM orders_info_rowmove SUBPARTITION(p1_sp1);
ORDER_NO ORDER_DESC AREA BRANCH ORDER_DATE SALESPERSON ID
----------------- ---------------------------------------------------------------- ----- ------ -------------------------------- ------------- -----------
20010102020001 product 001 02 0201 2022-08-21 0001 300
20010102020001 product 001 02 0201 2022-08-21 0001 500
-- 跨分区更新数据结束后,建议关闭行迁移
ALTER TABLE orders_info_rowmove DISABLE ROW MOVEMENT;
# supplemental_table_logging
该语句用于开启或关闭表级附加日志属性。表级附加日志只对当前的表生效,数据库级附加日志请参考ALTER DATABASE章节。
分布式部署中用户无法执行此操作。
# 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型,32K以上varchar和char等除外)的值。
附加日志约束项:
- 不能对已开启附加日志的表重复执行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 branches 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
指定此关键字表示在收缩表的同时,对其上索引也进行收缩,语法兼容,无实际意义。
示例(单机HEAP表)
ALTER TABLE orders_info ENABLE ROW MOVEMENT;
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表的后台数据转换能力。
目前的YashanDB后台提供给LSC表如下数据转换能力:
- TRANSFORM:LSC的可变数据依据此开关转换为稳态数据存储,可变数据缓冲区的数据被转换,转移到稳态数据内。关闭此开关即不再允许自动转换。需要注意,如果一直不转换,数据将一直存放在可变数据区,无法对数据存储格式进行优化,不建议长时间关闭。
- COMPACT:LSC的稳态数据依据此开关将数据格式进行自动优化(包括排序和合并)。关闭此开关即不再允许自动优化。需要注意,稳态数据的优化有利于查询性能提升,但是优化期间会产生额外的资源消耗,可以根据业务要求适当关闭。
- BUILD AC:LSC的稳态数据依据此开关进行AC的数据文件生成。关闭此开关即不再允许自动生成AC的数据文件,AC的能力可根据业务自行关闭开启。
此子句允许同时开启或关闭多种能力,用户也可通过配置DATA_TRANSFORMER_ENABLED参数整体开启或关闭后台数据转换能力。
Note:
1.TRANSFORM和COMPACT涉及物理空间变动, 转换任务执行后将在一段时间内保留转换前的数据,用于满足长查询的需要;当达到保留的最大时间时对这些数据进行清理 。用户在确保业务不受影响的情况下,可参照force_xfmr_clause执行立即清理。
2.系统中不存在AC对象时,打开BUILD AC开关不会创建AC数据文件。
示例(LSC表)
ALTER SYSTEM SET DATA_TRANSFORMER_ENABLED = TRUE SCOPE=SPFILE;
ALTER TABLE orders_info ENABLE TRANSFORM;
ALTER TABLE orders_info ENABLE TRANSFORM BUILD AC COMPACT;
ALTER TABLE orders_info DISABLE TRANSFORM;
ALTER TABLE orders_info DISABLE COMPACT;
# mcol_ttl_clause
该语句用于修改LSC表的可变生命周期,其含义请参考CREATE TABLE中对应语句描述。
该语句不适用于分布式部署。
示例(单机LSC表)
--将finance_info的可变生命周期由1个月修改为10天
ALTER TABLE finance_info ALTER MCOL TTL '10' DAY;
--area表创建时未设置可变生命周期,将其设为10年
ALTER TABLE area ALTER MCOL TTL '10' YEAR(9);
# mcol_order_by_clause
该语句用于开启或关闭可变数据(MCOL)排序,其含义请参考CREATE TABLE中table_sort_clause语句描述。
示例(LSC表)
ALTER TABLE orders_info ENABLE MCOL ORDER BY;
ALTER TABLE orders_info DISABLE MCOL ORDER BY;
# force_xfmr_clause
该语句用于LSC表强制转换,其中ASYNC标记表示异步转换,省略情况下默认进行同步转换。
强制转换有如下三种模式:
- STABLE:将LSC表的可变数据强制转换成稳态数据并生成此表下所有AC数据。
- COMPACT:将LSC表的稳态数据强制进行合并。
- CLEAN:将LSC的所有可删除数据( 转换任务执行完成后达到延期清理条件的数据 )强制进行删除。
示例(LSC表)
ALTER TABLE sales_info ALTER SLICE ALL STABLE;
ALTER TABLE sales_info ALTER SLICE ALL COMPACT;
ALTER TABLE sales_info ALTER SLICE ALL CLEAN;
# logging_clause
该语句用于修改表的logging属性,logging属性用于指定表记录日志的方式。
该语句不适用于分布式部署。
# logging
该语句用于将表转为logging属性,即对该表的所有操作记录日志。
- 若对已是logging属性的表执行该语句,直接返回成功。
- 若对nologging属性的表执行该语句,系统将执行一次全量checkpoint,将数据写盘并修改flushback,最后修改表的logging属性。
# logging async
该语句用于异步将表转为logging属性。启动新线程完成表模式转化的操作从而不阻塞主线程工作。
注意当客户端返回成功时并不保证转换一定成功,只代表启动线程成功。后续转换仍有可能失败。转换结果通过运行日志记载。
在异步转换表的过程中存在如下约束限制:
- 不能对转换中的表做任意DML操作。
- 不能对转换中的表做除了DROP以外的任意DDL操作。
# nologging
该语句用于将表转为nologging属性。若对已是nologging属性的表执行该语句,直接返回成功。若对logging属性的表执行该语句,会将其转为nologging属性。建议只在数据迁移场景打开此属性。
该语句不适用于共享集群部署。
执行该语句存在如下约束限制:
- 不能将临时表设置为nologging属性。
- 主备环境中,不能将表设置为nologging属性。
nologging属性的表存在如下特征:
- nologging表对DML操作仅支持插入数据和导入数据,且插入数据时只会记录必要的redo和undo(例如segment相关的redo),其他redo会被忽略。
- nologging表不能执行并发操作。
- nologging表不能执行回滚操作。
- nologging表不能在线创建索引(CREATE INDEX ONLINE)和在线重建索引(ALTER INDEX REBUILD ONLINE)。
- 数据库重启时会将nologging表标记为corrupted,阻止对其进行除drop和truncate外的任何操作。
- 如果一个事务失败,该事务内所有执行过插入数据操作的nologging表都会被标记为corrupted。
- nologging属性的LSC表使用bulkload模式导入数据时,不受nologging属性影响(性能无变化,失败也不会被标记为corrupted)。
- nologging属性的TAC表不允许修改列和删除主键约束。
示例(单机部署)
-- 执行如下语句开启logging
ALTER TABLE area LOGGING;
-- 执行如下语法关闭nologging,但主备环境中无法关闭
ALTER TABLE area NOLOGGING;
YAS-02328 table nologging is not allowed when standby exists
# readonly_clause
无实际含义。
# alter_column_clause
该语句用于指定对表的列字段的操作。
# add_column_clause
该语句用于为表增加列字段,同时增加多项时在()
中以,
分隔。COLUMN关键字可省略。
# column_definition
为表增加一个新的列字段,并对增加的列字段进行数据类型(DataType)、缺省值(DEFAULT)、行内约束(inline_constraint)等定义。
对非空表增加定义了NOT NULL约束的列字段时,必须同时为其指定缺省值,否则将提示错误。
# datatype
指定列字段的数据类型。查看YashanDB的数据类型描述。
其中,数据类型指定为LOB/JSON类型时,可通过lob_clauses子句指定其存储属性。
YashanDB不允许将新增的列字段指定为Nested Table UDT类型。
# default
为增加的列字段指定一个符合该列字段数据类型的缺省值,default_expr可以为字面量、运算式、函数等表达式。
当指定了缺省值时,系统将对表中现有行的该列字段填充该缺省值。
对于LSC表的新增列字段,该列为LOB型时不能指定缺省值;为其他类型时,缺省值不能定义为Sequence伪列。
示例(单机LSC表)
--创建LSC表lsc_forb_def
CREATE TABLE lsc_forb_def(c1 INT,c2 INT);
--LSC表中新增指定了默认值的lob列会报错
ALTER TABLE lsc_forb_def ADD(c3 CLOB DEFAULT 'default');
YAS-00004 feature "add lob column with default expr on LSC table" has not been implemented yet
--创建序列seq1
CREATE SEQUENCE seq1;
--LSC表中新增列的默认值为Sequence伪列时会报错
ALTER TABLE lsc_forb_def ADD(c3 INT DEFAULT seq1.NEXTVAL);
YAS-00004 feature "add column with default sequence on LSC table" has not been implemented yet
ALTER TABLE lsc_forb_def ADD(c3 INT DEFAULT seq1.currval);
YAS-00004 feature "add column with default sequence on LSC table" has not been implemented yet
# inline_constraint
该语句用于在增加列字段时同时定义表的行内约束项。关于约束项的详细描述请参考通用SQL语法constraint。
示例
-- 为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
# lob_clause
该语句为增加的LOB/JSON字段指定存储属性,语法同CREATE TABLE中lob_clause子句描述。
# drop_column_clause
该语句用于删除表中已有的列字段或约束项。
# drop_column
删除指定的列字段,指定多个列字段时用,
分隔。COLUMN关键字可省略。
该语句遵循如下规则:
- 不允许删除表中的所有列字段。
- 如果删除的列字段已被定义为主键组合中的一项,则不允许删除此列,但可以删除整个主键对应的列组合。
- 如果删除的列字段已被定义为索引对象中的一项,则删除此列字段后,其对应的索引对象也被删除。
- 分布式部署中,不允许删除分区键所在的列字段。
- LSC表中,不允许删除被定义为排序键的列字段。
- 如果数据库后台正在执行回滚,则不允许删除TAC表/含有热数据的LSC表中使用变长存储的列。
示例(单机、共享集群部署)
-- 创建product_pri表
CREATE TABLE product_pri AS SELECT * FROM product;
-- 定义组合主键product_no+product_name
ALTER TABLE product_pri ADD PRIMARY KEY(product_no,product_name);
-- 创建索引
CREATE UNIQUE INDEX idx_product_pri_1 ON product_pri(cost,price);
-- 删除部分主键字段,返回错误
ALTER TABLE product_pri DROP COLUMN product_no;
YAS-02132 cannot drop column referenced in a multi-column constraint
-- 删除全部主键字段,成功
ALTER TABLE product_pri DROP COLUMN(product_no,product_name);
-- 删除部分索引字段,成功
ALTER TABLE product_pri DROP COLUMN cost;
-- 删除表中最后的一个字段,返回错误
ALTER TABLE product_pri DROP COLUMN price;
YAS-02054 cannot drop all columns in a table
示例(分布式TAC表)
-- 创建area_part表
CREATE TABLE area_part AS SELECT * FROM area;
-- 删除分区键字段,返回错误
ALTER TABLE area_part DROP COLUMN area_no;
YAS-02142 cannot drop partitioning column
-- 删除非分区键字段,成功
ALTER TABLE area_part DROP COLUMN area_name;
示例(LSC表)
--创建area_orderkey表,并指定排序键为area_no
CREATE TABLE area_orderkey AS SELECT * FROM area ORDER BY area_no;
--删除排序键所在字段,返回错误
ALTER TABLE area_orderkey DROP COLUMN area_no;
YAS-03726 cannot drop order key column
# rename_column_clause
该语句用于对列字段进行重命名,指定的新名称不允许为空且必须符合YashanDB的对象命名规范。
示例(HEAP表、TAC表)
ALTER TABLE branches RENAME branch_no TO branchno;
ALTER TABLE branches RENAME branchno TO branch_no;
# modify_column_clause
该语句用于对列字段的数据类型、默认值、约束等属性进行修改,同时修改多个列字段时需在()
中以,
分隔。
YashanDB支持同时对列字段修改多个属性,但需遵循与CREATE TABLE相同的顺序要求,否则系统提示错误;当同时修改多个约束项时,对这些约束项无顺序要求。
# datatype
修改列字段的数据类型为YashanDB认可的数据类型。
LSC表不允许修改列字段的数据类型,HEAP表和TAC表列字段数据类型修改规则如下:
外键约束所在列:不允许修改子表和父表中相应列的数据类型。
索引所在列:
若为空表(即无数据),允许将其修改为除LOB/JSON/UDT/XMLTYPE外的数据类型。
若为非空表,则不允许修改其数据类型。
使用字典编码的列(仅适用于TAC表):仅允许将其修改为字符型,但仍遵循字符型列的修改规则。
变长存储的字符型列(仅适用于TAC表):不允许在数据库进行回滚时,修改其数据类型。
分区键、函数索引或AC所在列:不允许修改其数据类型。
原数据类型为LOB/JSON/UDT/XMLTYPE的其他列:不允许修改其数据类型。
原数据类型为字符型的其他空列:允许将其修改为除LOB/JSON/UDT/XMLTYPE外的其他数据类型。
原数据类型为字符型的其他非空列:允许修改为不同字符型,但仍需遵顼以下规则:
不允许CHAR/VARCHAR与NCHAR/NVARCHAR交叉修改。
当按长度属性从大向小修改时,必须保证该列现有数据的长度均未超过目标数据类型的上限,否则无法修改成功并提示相应错误。
HEAP表不允许跨存储方式修改数据类型,例如HEAP表不允许将列数据类型从VARCHAR(3200)(采用普通字符串存储)修改为VARCHAR(8004)(会自动转换为LOB型存储),而TAC表允许此操作。存储方式介绍请查阅字符型。
原数据类型为其他数据类型的其他空列:允许将其修改为除LOB/JSON/UDT/XMLTYPE外的其他数据类型。
原数据类型为其他数据类型的其他非空列:
不允许跨大类修改数据类型,例如不允许将数值型修改为字符型。
同一数据大类中,除字符型外其他类型只允许按值域、精度、长度等属性从小向大修改数据类型,例如不允许将INT修改为指定了精度的NUMBER,不允许将DATE修改为TIME。
# default
修改列字段的缺省值,default_expr可以为字面量、运算式、函数等表达式。
示例(HEAP表、TAC表)
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描述。
示例(HEAP表、TAC表)
--修改branches非空表的branch_name非空列字段数据类型,只能修改为字符型
ALTER TABLE branches MODIFY branch_name CHAR(400);
--修改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';
--修改area表的area_name列字段为非空
ALTER TABLE area MODIFY area_name 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等属性。
可以为新增的分区指定range、list或者hash子分区,子分区的类型需要和表的定义一致。
如建表时未指定该表为组合分区表,不允许通过本语句为新增分区指定子分区。
示例(单机、共享集群部署)
ALTER TABLE sales_info_range ADD PARTITION p_sales_info_range_4 VALUES LESS THAN('2038');
--创建一张range-list组合分区表range_list_table
CREATE TABLE range_list_table(a INT, b INT)
PARTITION BY RANGE(a)
SUBPARTITION BY LIST(b)
(PARTITION p1 VALUES LESS than(1) (SUBPARTITION sp1 VALUES(10), SUBPARTITION sp2 VALUES(20)),
PARTITION p2 VALUES LESS than(2) (SUBPARTITION sp3 VALUES(10), SUBPARTITION sp4 VALUES(20)));
--为其添加一个range分区并指定其list子分区
ALTER TABLE range_list_table ADD PARTITION p3 VALUES LESS THAN(3)(SUBPARTITION sp5 VALUES(10),SUBPARTITION sp6 VALUES(20));
# add_list_partition_clause
增加列表类型的分区,如表已在列表值里定义了DEFAULT,则不允许增加分区。
分区列表值可以指定为通用表达式(expr)。
# table_partition_description
可以为新增的分区指定所属表空间(缺省为表所属表空间),及PCTFREE/PCTUSED/INITRANS/MAXTRANS等属性。
可以为新增的分区指定range、list或者hash子分区,子分区的类型需要和表的定义一致。
如建表时未指定该表为组合分区表,不允许通过本语句为新增分区指定子分区。
当分区列数量为一并且新增分区包含多个值时,每个值需要用括号包起来,否则报错。
示例(单机、共享集群部署)
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));
--创建一张list-list组合表list_list_table
CREATE TABLE list_list_table(a INT, b INT)
PARTITION BY LIST(a)
SUBPARTITION BY LIST(b)
(PARTITION p1 VALUES(1) (SUBPARTITION sp1 VALUES(1), SUBPARTITION sp2 VALUES(2)),
PARTITION p2 VALUES(2) (SUBPARTITION sp3 VALUES(1), SUBPARTITION sp4 VALUES(2)));
--为其添加一个list分区并指定其list子分区
ALTER TABLE list_list_table ADD PARTITION p3 VALUES (3)(SUBPARTITION sp5 VALUES(1), SUBPARTITION sp6 VALUES(2));
# add_hash_partition_clause
增加哈希类型的分区。本语句只适用于HEAP/TAC表。
新增分区的PCTFREE/PCTUSED/INITRANS/MAXTRANS等属性从表上继承,不允许指定。
可以为新增的分区指定range、list或者hash子分区,子分区的类型需要和表的定义一致。
如建表时未指定该表为组合分区表,不允许通过本语句为新增分区指定子分区。
# partition_storage_clause
可以为新增的分区指定所属表空间(缺省为表所属表空间)。
示例(HEAP表、单机TAC表)
ALTER TABLE sales_info_hash ADD PARTITION p_sales_info_hash_3;
ALTER TABLE sales_info_hash ADD PARTITION p_sales_info_hash_4;
--创建一张hash-list组合分区表hash_list_table
CREATE TABLE hash_list_table(c1 INT, c2 VARCHAR(10))
PARTITION BY HASH(c1)
SUBPARTITION BY LIST(c2)
(
PARTITION p1(SUBPARTITION sp1 VALUES('a')),
PARTITION p2 (SUBPARTITION sp3 VALUES('d'), SUBPARTITION sp4 VALUES(DEFAULT))
);
--为其添加一个hash分区并指定其list子分区
ALTER TABLE hash_list_table ADD PARTITION p3(SUBPARTITION sp5 VALUES ('f'));
# drop_table_partition
该语句用于删除表的分区,同时删除分区里的数据。指定多个分区用,
分隔。
该语句指定的分区中存有数据时,会同步失效表上的全局索引。分布式部署模式下,不管指定的分区是否存有数据,都会失效表上的全局索引。
该语句存在如下约束限制:
- 删除分区时,不允许将表上的所有分区都删除。
- 不允许删除哈希类型分区。
- 在表的分区被删除时,对应的索引分区也会被删除。
- 对于范围类型分区,删除分区后其分区界值将会向相邻大一级分区合并,这样符合此被删除分区界值范围的新增表数据将进入相邻分区中,如不存在相邻大一级分区则数据无法再插入成功。
示例(单机、共享集群部署)
--sales_info_range为一张范围分区表
SELECT year,month,branch,product,quantity,amount,salsperson 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 year,month,branch,product,quantity,amount,salsperson 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 year,month,branch,product,quantity,amount,salsperson 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;
# drop_table_subpartition
该语句用于删除表的子分区,同时删除子分区里的数据。指定多个子分区用,
分隔。
本语句存在如下约束限制:
- 删除子分区时,不允许将分区下的所有子分区都删除,也不允许跨分区删除子分区。
- 不允许删除哈希类型子分区。
- 在表的子分区被删除时,对应的索引子分区也会被删除。
示例
--获得sales_info表的子分区名称
SELECT partition_name,subpartition_name
FROM DBA_TAB_SUBPARTITIONS
WHERE table_name='SALES_INFO';
--以下输出以单机为例
PARTITION_NAME SUBPARTITION_NAME
---------------------------- ---------------------------------------
P_SALES_INFO_1 P_SALES_INFO_1_SP_SALES_INFO_1
P_SALES_INFO_1 P_SALES_INFO_1_SP_SALES_INFO_2
P_SALES_INFO_1 P_SALES_INFO_1_SP_SALES_INFO_3
P_SALES_INFO_2 P_SALES_INFO_2_SP_SALES_INFO_1
P_SALES_INFO_2 P_SALES_INFO_2_SP_SALES_INFO_2
P_SALES_INFO_2 P_SALES_INFO_2_SP_SALES_INFO_3
P_SALES_INFO_3 P_SALES_INFO_3_SP_SALES_INFO_1
P_SALES_INFO_3 P_SALES_INFO_3_SP_SALES_INFO_2
P_SALES_INFO_3 P_SALES_INFO_3_SP_SALES_INFO_3
--选择其中一个子分区删除
ALTER TABLE sales_info DROP SUBPARTITION P_SALES_INFO_1_SP_SALES_INFO_1;
# update_index_clause
同drop_table_partition语句中描述一致。
# truncate_table_partition
该语句用于删除分区里的所有数据,指定删除多个分区数据用,
分隔。
该语句同时删除分区对应的本地索引数据(Local Index)。
该语句指定的分区中存有数据时,会同步失效表上的全局索引。分布式部署模式下,不管指定的分区是否存有数据,都会失效表上的全局索引。
# truncate_part_clause
该语句用于指定删除分区数据的方式。
# drop|reuse storage
指定删除分区数据后释放|保留其存储空间。
# cascade
如某张分区表为被子表定义了外键约束的父表,且要删除的分区数据在子表对应列字段值中已经存在,则指定CASCADE将同时删除子表中对应的数据行。本语句只作用于HEAP表。
# purge
当回收站开启时,被删除的数据默认将进入回收站,指定本关键字则表示数据被彻底删除,不进入回收站。本语句只作用于HEAP表。
示例(单机、共享集群部署)
--获得sales_info表的分区名称
SELECT partition_name
FROM DBA_TAB_PARTITIONS
WHERE table_name='SALES_INFO';
--以下输出以单机为例
PARTITION_NAME
----------------------------------------------------------------
P_SALES_INFO_1
P_SALES_INFO_2
P_SALES_INFO_3
ALTER TABLE sales_info TRUNCATE PARTITION P_SALES_INFO_1 DROP STORAGE;
# truncate_table_subpartition
该语句用于删除子分区里的所有数据,指定删除多个子分区数据用,
分隔。
该语句同时删除子分区对应的本地索引数据(Local Index)。
# truncate_part_clause
同truncate_table_partition语句中描述一致。
示例(单机、共享集群部署)
ALTER TABLE sales_info TRUNCATE SUBPARTITION P_SALES_INFO_3_SP_SALES_INFO_1 DROP STORAGE;
# set_partition_clause
该语句只作用于HEAP表,且只针对范围分区表,用于指定INTERVAL和非INTERVAL分区类型之间的相互转换。转换分区类型不会影响表中原有的数据,新增加的数据则按转换后的分区类型特点存储。
分布式部署中用户无法执行此操作。
# transfer range to range-interval
将RANGE分区表转换为INTERVAL分区时,要求分区键的数据类型为number或date,语法如下:
ALTER TABLE table_name SET INTERVAL(expr);
建立INTERVAL分区的要求和规则与CREATE TABLE里的interval_clause中描述一致,不符合时无法成功转换。
示例(HEAP表)
--创建示例表sales_info_range1,与样例表中sales_info_range区别仅在于分区键year的数据类型为int
CREATE TABLE sales_info_range1
(year INT NOT NULL,
month CHAR(2) NOT NULL,
branch CHAR(4),
product CHAR(5),
quantity NUMBER DEFAULT 0 NOT NULL,
amount NUMBER(10,2) DEFAULT 0 NOT NULL,
salsperson CHAR(10))
PARTITION BY RANGE(year)
(PARTITION p_sales_info_range_1 VALUES LESS THAN(2011),
PARTITION p_sales_info_range_2 VALUES LESS THAN(2021),
PARTITION p_sales_info_range_3 VALUES LESS THAN(2031));
--将sales_info_range1表的分区类型转换为INTERVAL类型
ALTER TABLE sales_info_range1 SET INTERVAL(2);
--对于超过现有分区界值的数据,系统将创建新分区且类型为INTERVAL
INSERT INTO sales_info_range1 VALUES ('2031','05','0101','11001',40,600,'');
COMMIT;
SELECT partition_name,tablespace_name,high_value
FROM USER_TAB_PARTITIONS
WHERE table_name='SALES_INFO_RANGE1'
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类型的范围分区表执行此操作,否则系统报错。
示例(HEAP表)
--为sales_info_range1表新建两个表空间
CREATE TABLESPACE sales_tb1;
CREATE TABLESPACE sales_tb2;
--对上例中的INTERVAL分区表修改INTERVAL和表空间
ALTER TABLE sales_info_range1 SET INTERVAL(3);
ALTER TABLE sales_info_range1 SET STORE IN(sales_tb1,sales_tb2);
INSERT INTO sales_info_range1 VALUES ('2033','05','0101','11001',40,600,'');
INSERT INTO sales_info_range1 VALUES ('2043','05','0101','11001',40,600,'');
COMMIT;
SELECT partition_name,tablespace_name,high_value
FROM USER_TAB_PARTITIONS
WHERE table_name='SALES_INFO_RANGE1'
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();
示例(HEAP表)
--将上例中的INTERVAL分区表修改为非INTERVAL的范围分区表
ALTER TABLE sales_info_range1 SET INTERVAL();
# modify_partition_clause
该语句用于对表分区进行操作,对于一级分区其中包含收缩操作和添加二级分区的操作,对于二级分区只有收缩操作。
# shrink_space_clause
收缩操作与表的收缩一致,请参考shrink_space_clause。
示例(单机HEAP表)
ALTER TABLE orders_info ENABLE ROW MOVEMENT;
ALTER TABLE sales_info ENABLE ROW MOVEMENT;
ALTER TABLE orders_info MODIFY PARTITION p_orders_info_1 SHRINK SPACE COMPACT CASCADE;
ALTER TABLE sales_info MODIFY SUBPARTITION P_SALES_INFO_3_SP_SALES_INFO_1 SHRINK SPACE COMPACT CASCADE;
# split_table_partition
该语句能将一个范围或者列表分区重新划分为多个分区。当一个分区过于臃肿影响到了查询、备份等性能时,可以考虑SPLIT PARTITION。
只能对HEAP表和单机TAC表执行本语句。
该语句须遵循如下限制:
- 不可对组合分区表执行SPLIT PARTITION。
- UPDATE GLOBAL INDEXES为语法兼容,SPLIT PARTITION后会失效全局索引,请SPLIT后重建(rebuild_clause)全局索引。
- 若指定UPDATE INDEXES,则SPLIT PARTITION后不会失效LOCAL索引,会失效全局索引。
- 未指定分区名的表分区、索引分区、LOB分区会按照SYS_Pn的格式自动生成分区名。
# split at (literal) into
该语句根据指定的字面量将一个范围分区划分为两个范围分区,仅适用于范围分区。
# literal
划分值,该值须位于被划分的分区范围内,否则返回错误。
# range_partition_desc
该语句用于指定划分后两个范围分区的名称,其中一个分区名可保留原分区名称,另一分区名不可与已有的分区名称重复。
新范围分区上下限分别为[原范围分区下限,literal]
和[literal,原范围分区上限]
。
示例(HEAP表,单机TAC表)
-- 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分区。
# list_values
划分的列表内容,其中的值须包含在被划分的列表分区内,否则返回错误。
# list_partition_desc
该语句用于指定划分后两个列表分区的名称,其中一个分区名可保留原分区名称,另一分区名不可与已有的分区名称重复。
划分后的首个列表分区包含list_values中所有值,其余值保存在第二个列表分区中。
示例(HEAP表,单机TAC表)
-- 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
该语句用于指定包含所有剩余值的分区名称及信息,名称不可与已有分区的名称重复。
示例(HEAP表,单机TAC表)
-- 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);
# add_subpartition_clause
该语句用于在组合分区表中给指定的一级分区添加二级分区。
该语句中range_subpartition_desc、list_subpartition_desc、individual_hash_subparts的描述请参考CREATE TABLE。
示例(HEAP表,单机TAC表)
CREATE TABLE composite_table(c1 INT, c2 INT)
PARTITION BY RANGE(c1)
SUBPARTITION BY HASH(c2)
(
PARTITION p1 VALUES LESS than(1) (SUBPARTITION sp1, SUBPARTITION sp2),
PARTITION p2 VALUES LESS than(2) (SUBPARTITION sp3, SUBPARTITION sp4)
);
ALTER TABLE composite_table MODIFY PARTITION p1 ADD SUBPARTITION p1_subp1;
-- 表创建时未指定为组合分区表,执行本语句会返回错误
CREATE TABLE partition_table(c1 INT,c2 INT)
PARTITION BY RANGE(c1)
INTERVAL (10)
(PARTITION par1 VALUES LESS THAN(100));
ALTER TABLE partition_table MODIFY PARTITION par1 ADD SUBPARTITION par1_subp1;
YAS-02374 table is not partitioned by composite partition method
# alter_table_constraint
该语句用于指定对表上的约束的操作包括对添加约束、删除约束、修改约束和停用或启用约束。
# add_constraint
该语句用于添加约束,同时增加多项在()
中以,
分隔。
# out_of_line_constraint
约束项,关于约束项的详细描述请参考通用SQL语法constraint。
# drop_constraint
该语句用于删除约束项。
如某个约束项在其创建时未指定名称,可以从系统提供视图(如USER_CONSTRAINTS)中查询到其默认名称后再执行删除操作。
删除UNIQUE/PRIMARY KEY约束项会自动删除对应的索引。
示例(HEAP表)
ALTER TABLE branches DROP CONSTRAINT c_branches_1;
-- 存在外键时无法删除主键约束项
ALTER TABLE department DROP PRIMARY KEY;
YAS-02188 this unique/primary key is referenced by some foreign keys
# 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;
ALTER TABLE area MODIFY PRIMARY KEY ENABLE;
-- 在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 ADD CONSTRAINT c_branches_1
FOREIGN KEY (area_no) REFERENCES area(area_no) ON DELETE SET NULL;
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外相同的关键字和含义,但顺序不相同。
示例(HEAP表)
-- modify_constraint中的如下例句:
ALTER TABLE area MODIFY PRIMARY KEY DISABLE CASCADE;
ALTER TABLE area MODIFY PRIMARY KEY ENABLE;
ALTER TABLE branches MODIFY UNIQUE(branch_no, area_no) ENABLE;
ALTER TABLE branches MODIFY CONSTRAINT c_branches_1 ENABLE NOVALIDATE;
-- 在enable_disable_constraint中可以如下表示:
ALTER TABLE area DISABLE PRIMARY KEY CASCADE;
ALTER TABLE area ENABLE PRIMARY KEY;
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;
# reclaim_table_clause
该语句用于在表空间迁移后,为迁移的对象声明存储对象和属性。
Warn:
通常用于在分布式部署中进行节点/节点组扩缩容后,将逻辑对象与物理存储对象进行关联。
在该场景下,数据库会自动生成reclaim语句并自动在目标节点执行。不建议用户手动执行该语句,若不避免可能会导致系统崩溃或其他不可预知的结果。