#### 13.1.9.2 ALTER TABLE 和生成的列

[](<>)

`更改表`生成的列允许的操作是`添加`,`调整`， 和`改变`.

-   可以添加生成的列。

    ```
    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;
    ```

-   `添加列`不是存储列的就地操作（不使用临时表完成），因为表达式必须由服务器计算。对于存储的列，索引更改是就地完成的，而表达式更改不是就地完成的。对列注释的更改已就地完成。

-   对于非分区表，`添加列`和`删除列`是虚拟列的就地操作。但是，添加或删除虚拟列不能与其他列一起执行[`更改表`](alter-table.html)操作。

    对于分区表，`添加列`和`删除列`不是虚拟列的就地操作。

-   `InnoDB`支持虚拟生成列的二级索引。在虚拟生成的列上添加或删除二级索引是就地操作。有关详细信息，请参阅[第 13.1.20.9 节，“二级索引和生成的列”](create-table-secondary-indexes.html).

-   当一个`虚拟的`生成的列被添加到表中或被修改，不能确保由生成的列表达式计算的数据超出列的范围。这可能导致返回不一致的数据和意外失败的语句。为了允许控制是否对此类列进行验证，`更改表`支持`未经验证`和`通过验证`条款：

    -   和`未经验证`（如果没有指定子句，则为默认值），执行就地操作（如果可能），不检查数据完整性，并且语句完成得更快。但是，如果值超出范围，以后从表中读取可能会报告列的警告或错误。

    -   和`通过验证`,`更改表`复制表格。如果发生超出范围或任何其他错误，则语句将失败。因为执行了表复制，所以语句需要更长的时间。

    `未经验证`和`通过验证`只允许与`添加列`,`更改列`， 和`修改栏目`操作。否则，一个[`ER_WRONG_USAGE`](https://dev.mysql.com/doc/mysql-errors/8.0/en/server-error-reference.html#error_er_wrong_usage)发生错误。

-   如果表达式求值导致截断或向函数提供不正确的输入，则[`更改表`](alter-table.html)语句以错误终止并且 DDL 操作被拒绝。

-   一个[`更改表`](alter-table.html)更改列的默认值的语句*`col_name`*还可以更改生成的列表达式的值，该列表达式使用*`col_name`*，这可能会更改生成的列表达式的值，该列表达式使用[`默认（*`col_name`*)`](miscellaneous-functions.html#function_default).为此原因，[`更改表`](alter-table.html)如果任何生成的列表达式使用了更改列定义的操作，则会导致表重建[`默认（）`](miscellaneous-functions.html#function_default).
