15.1.9.2 ALTER TABLE 和生成的列
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节,“次要索引和生成列”。 -
当添加或修改虚拟生成列时,不保证由生成列表达式计算的数据不超出该列范围,这可能导致返回不一致的数据和意外失败语句。为了控制是否对这些列进行验证,
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操作。 -
修改列的默认值的
ALTER TABLE
语句也可能会更改使用该列的生成列表达式的值,后者可能会更改使用DEFAULT()
函数的值。因此,修改列定义的ALTER TABLE
操作如果有使用DEFAULT()
函数的生成列表达式,会导致表重建。