生成列允许的 ALTER TABLE
操作包括 ADD
、MODIFY
和 CHANGE
。
-
可以添加生成列。
CREATE TABLE t1 (c1 INT); ALTER TABLE t1 ADD COLUMN c2 INT GENERATED ALWAYS AS (c1 + 1) STORED;
-
可以修改生成列的数据类型和表达式。
CREATE TABLE t1 (c1 INT, c2 INT GENERATED ALWAYS AS (c1 + 1) STORED); ALTER TABLE t1 MODIFY COLUMN c2 TINYINT GENERATED ALWAYS AS (c1 + 5) STORED;
-
如果其他列没有引用生成列,则可以重命名或删除生成列。
CREATE TABLE t1 (c1 INT, c2 INT GENERATED ALWAYS AS (c1 + 1) STORED); ALTER TABLE t1 CHANGE c2 c3 INT GENERATED ALWAYS AS (c1 + 1) STORED; ALTER TABLE t1 DROP COLUMN c3;
-
虚拟生成列无法更改为存储生成列,反之亦然。 要解决此问题,请删除该列,然后使用新的定义添加它。
CREATE TABLE t1 (c1 INT, c2 INT GENERATED ALWAYS AS (c1 + 1) VIRTUAL); ALTER TABLE t1 DROP COLUMN c2; ALTER TABLE t1 ADD COLUMN c2 INT GENERATED ALWAYS AS (c1 + 1) STORED;
-
非生成列可以更改为存储生成列,但不能更改为虚拟生成列。
CREATE TABLE t1 (c1 INT, c2 INT); ALTER TABLE t1 MODIFY COLUMN c2 INT GENERATED ALWAYS AS (c1 + 1) STORED;
-
存储生成列(但不是虚拟生成列)可以更改为非生成列。 存储的生成值将成为非生成列的值。
CREATE TABLE t1 (c1 INT, c2 INT GENERATED ALWAYS AS (c1 + 1) STORED); ALTER TABLE t1 MODIFY COLUMN c2 INT;
-
对于存储列(不使用临时表完成),
ADD COLUMN
不是就地操作,因为表达式必须由服务器计算。 对于存储列,索引更改是就地完成的,而表达式更改则不是就地完成的。 列注释的更改是就地完成的。 -
对于非分区表,
ADD COLUMN
和DROP COLUMN
是虚拟列的就地操作。 但是,添加或删除虚拟列不能与其他ALTER TABLE
操作一起就地执行。对于分区表,
ADD COLUMN
和DROP COLUMN
不是虚拟列的就地操作。 -
InnoDB
支持虚拟生成列上的二级索引。 在虚拟生成列上添加或删除二级索引是就地操作。 有关更多信息,请参阅 第 15.1.20.9 节,“二级索引和生成列”。 -
将
VIRTUAL
生成列添加到表或修改表时,无法确保生成列表达式计算的数据没有超出该列的范围。 这可能导致返回不一致的数据并导致语句意外失败。 为了允许控制是否对这些列进行验证,ALTER TABLE
支持WITHOUT VALIDATION
和WITH VALIDATION
子句:-
使用
WITHOUT VALIDATION
(如果未指定任何子句,则为默认值),将执行就地操作(如果可能),不检查数据完整性,并且语句完成得更快。 但是,如果值超出范围,则稍后从表中读取时可能会报告该列的警告或错误。 -
使用
WITH VALIDATION
,ALTER TABLE
将复制该表。 如果发生超出范围或任何其他错误,则语句将失败。 由于执行了表复制,因此该语句需要更长的时间。
WITHOUT VALIDATION
和WITH VALIDATION
仅允许与ADD COLUMN
、CHANGE COLUMN
和MODIFY COLUMN
操作一起使用。否则,会发生ER_WRONG_USAGE
错误。 -
-
如果表达式评估导致截断或向函数提供错误输入,则
ALTER TABLE
语句将终止并出现错误,并且 DDL 操作将被拒绝。 -
更改列
col_name
默认值的ALTER TABLE
语句也可能会更改引用使用col_name
的列的生成列表达式的值,这可能会更改引用使用DEFAULT(
的列的生成列表达式的值。因此,如果任何生成列表达式使用col_name
)DEFAULT()
,则更改列定义的ALTER TABLE
操作会导致表重建。