PingKai Logo下载

ALTER TABLE

该语句用于修改已存在的表,使其符合新的表结构。ALTER TABLE 语句可以用于:

语法

AlterTableStmt
ALTER IgnoreOptional TABLE TableName AlterTableSpecListOpt AlterTablePartitionOpt ANALYZE PARTITION PartitionNameList INDEX IndexNameList AnalyzeOptionListOpt COMPACT PARTITION PartitionNameList TIFLASH REPLICA
TableName
Identifier . Identifier
AlterTableSpec
TableOptionList SET TIFLASH REPLICA LengthNum LocationLabelList CONVERT TO CharsetKw CharsetName DEFAULT OptCollate ADD ColumnKeywordOpt IfNotExists ColumnDef ColumnPosition ( TableElementList ) Constraint PARTITION IfNotExists NoWriteToBinLogAliasOpt PartitionDefinitionListOpt PARTITIONS NUM CHECK TRUNCATE PARTITION OPTIMIZE REPAIR REBUILD PARTITION NoWriteToBinLogAliasOpt AllOrPartitionNameList COALESCE PARTITION NoWriteToBinLogAliasOpt NUM DROP ColumnKeywordOpt IfExists ColumnName RestrictOrCascadeOpt PRIMARY KEY PARTITION IfExists PartitionNameList KeyOrIndex IfExists CHECK Identifier FOREIGN KEY Symbol EXCHANGE PARTITION Identifier WITH TABLE TableName WithValidationOpt IMPORT DISCARD PARTITION AllOrPartitionNameList TABLESPACE REORGANIZE PARTITION NoWriteToBinLogAliasOpt ReorganizePartitionRuleOpt ORDER BY AlterOrderItem , DISABLE ENABLE KEYS MODIFY ColumnKeywordOpt IfExists CHANGE ColumnKeywordOpt IfExists ColumnName ColumnDef ColumnPosition ALTER ColumnKeywordOpt ColumnName SET DEFAULT SignedLiteral ( Expression ) DROP DEFAULT CHECK Identifier EnforcedOrNot INDEX Identifier VISIBLE INVISIBLE RENAME COLUMN KeyOrIndex Identifier TO Identifier TO = AS TableName LockClause AlgorithmClause FORCE WITH WITHOUT VALIDATION SECONDARY_LOAD SECONDARY_UNLOAD AUTO_INCREMENT AUTO_ID_CACHE AUTO_RANDOM_BASE SHARD_ROW_ID_BITS EqOpt LengthNum CACHE NOCACHE TTL EqOpt TimeColumnName + INTERVAL Expression TimeUnit TTLEnable EqOpt ON OFF REMOVE TTL TTLEnable EqOpt ON OFF TTLJobInterval EqOpt stringLit AFFINITY EqOpt stringLit PlacementPolicyOption
PlacementPolicyOption
PLACEMENT POLICY EqOpt PolicyName PLACEMENT POLICY EqOpt SET DEFAULT

示例

创建一个包含初始数据的表:

CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 INT NOT NULL);
INSERT INTO t1 (c1) VALUES (1),(2),(3),(4),(5);
Query OK, 0 rows affected (0.11 sec)

Query OK, 5 rows affected (0.03 sec)
Records: 5  Duplicates: 0  Warnings: 0

以下查询由于 c1 列未建立索引,因此需要进行全表扫描:

EXPLAIN SELECT * FROM t1 WHERE c1 = 3;
+-------------------------+----------+-----------+---------------+--------------------------------+
| id                      | estRows  | task      | access object | operator info                  |
+-------------------------+----------+-----------+---------------+--------------------------------+
| TableReader_7           | 10.00    | root      |               | data:Selection_6               |
| └─Selection_6           | 10.00    | cop[tikv] |               | eq(test.t1.c1, 3)              |
|   └─TableFullScan_5     | 10000.00 | cop[tikv] | table:t1      | keep order:false, stats:pseudo |
+-------------------------+----------+-----------+---------------+--------------------------------+
3 rows in set (0.00 sec)

可以使用 ALTER TABLE .. ADD INDEX 语句为表 t1 添加索引。EXPLAIN 结果显示,原有查询现在使用了索引区间扫描,效率更高:

ALTER TABLE t1 ADD INDEX (c1);
EXPLAIN SELECT * FROM t1 WHERE c1 = 3;
Query OK, 0 rows affected (0.30 sec)

+------------------------+---------+-----------+------------------------+---------------------------------------------+
| id                     | estRows | task      | access object          | operator info                               |
+------------------------+---------+-----------+------------------------+---------------------------------------------+
| IndexReader_6          | 10.00   | root      |                        | index:IndexRangeScan_5                      |
| └─IndexRangeScan_5     | 10.00   | cop[tikv] | table:t1, index:c1(c1) | range:[3,3], keep order:false, stats:pseudo |
+------------------------+---------+-----------+------------------------+---------------------------------------------+
2 rows in set (0.00 sec)

TiDB 支持断言 DDL 变更使用特定的 ALTER 算法。注意,这只是一个断言,并不会改变实际用于修改表的算法:

ALTER TABLE t1 DROP INDEX c1, ALGORITHM=INSTANT;
Query OK, 0 rows affected (0.24 sec)

在需要 INPLACE 算法的操作上使用 ALGORITHM=INSTANT 断言会导致语句报错:

ALTER TABLE t1 ADD INDEX (c1), ALGORITHM=INSTANT;
ERROR 1846 (0A000): ALGORITHM=INSTANT is not supported. Reason: Cannot alter table by INSTANT. Try ALGORITHM=INPLACE.

然而,对于 INPLACE 操作使用 ALGORITHM=COPY 断言时,会产生警告而不是报错。这是因为 TiDB 将该断言解释为 此算法或更优。这种行为差异有助于与 MySQL 兼容,因为 TiDB 实际使用的算法可能与 MySQL 不同:

ALTER TABLE t1 ADD INDEX (c1), ALGORITHM=COPY;
SHOW WARNINGS;
Query OK, 0 rows affected, 1 warning (0.25 sec)

+-------+------+---------------------------------------------------------------------------------------------+
| Level | Code | Message                                                                                     |
+-------+------+---------------------------------------------------------------------------------------------+
| Error | 1846 | ALGORITHM=COPY is not supported. Reason: Cannot alter table by COPY. Try ALGORITHM=INPLACE. |
+-------+------+---------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

MySQL 兼容性

在 TiDB 中,ALTER TABLE 受以下主要限制:

  • 在单条 ALTER TABLE 语句中修改多个 schema 对象时:

    • 不支持对同一对象进行多次变更。
    • TiDB 会根据 执行前 的表结构校验语句。例如,执行 ALTER TABLE t ADD COLUMN c1 INT, ADD COLUMN c2 INT AFTER c1; 时会报错,因为列 c1 在表中尚不存在。
    • 对于一条 ALTER TABLE 语句,TiDB 的执行顺序是从左到右依次变更,这在某些情况下与 MySQL 不兼容。
  • 不支持对主键列进行 Reorg-Data 类型的变更。

  • 不支持对分区表的列类型进行变更。

  • 不支持对生成列的列类型进行变更。

  • 由于 TiDB 与 MySQL 在 CAST 函数行为上的兼容性问题,不支持某些数据类型(如部分 TIME、Bit、Set、Enum 和 JSON 类型)的变更。

  • AFFINITY 选项是 TiDB 扩展语法。为表启用 AFFINITY 后,不能再修改该表的分区方案(如添加、删除、重组或交换分区)。如需修改分区方案,必须先移除 AFFINITY。

  • 不支持空间数据类型。

  • ALTER TABLE t CACHE | NOCACHE 是 TiDB 对 MySQL 语法的扩展。详情参见 缓存表。

更多限制,参见 MySQL 兼容性。

另请参阅