ALTER TABLE
该语句用于修改已存在的表,使其符合新的表结构。ALTER TABLE 语句可以用于:
语法
- AlterTableStmt
- TableName
- AlterTableSpec
- PlacementPolicyOption
示例
创建一个包含初始数据的表:
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 兼容性。