MODIFY COLUMN
ALTER TABLE .. MODIFY COLUMN 语句用于修改已有表上的列,包括列的数据类型和属性。若要同时重命名,可改用 CHANGE COLUMN 语句。
从 v5.1.0 版本起,TiDB 开始支持 Reorg 类型变更,包括但不限于:
- 从
VARCHAR转换为BIGINT DECIMAL精度修改- 从
VARCHAR(10)到VARCHAR(5)的长度压缩
语法图
- AlterTableStmt
- ModifyColumnSpec
- ColumnType
- ColumnOption
- ColumnName
示例
Meta-Only Change
CREATE TABLE t1 (id int not null primary key AUTO_INCREMENT, col1 INT);Query OK, 0 rows affected (0.11 sec)INSERT INTO t1 (col1) VALUES (1),(2),(3),(4),(5);Query OK, 5 rows affected (0.02 sec)
Records: 5 Duplicates: 0 Warnings: 0ALTER TABLE t1 MODIFY col1 BIGINT;Query OK, 0 rows affected (0.09 sec)SHOW CREATE TABLE t1\G*************************** 1. row ***************************
Table: t1
Create Table: CREATE TABLE `t1` (
`id` int NOT NULL AUTO_INCREMENT,
`col1` bigint DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=30001
1 row in set (0.00 sec)Reorg-Data Change
CREATE TABLE t1 (id int not null primary key AUTO_INCREMENT, col1 INT);Query OK, 0 rows affected (0.11 sec)INSERT INTO t1 (col1) VALUES (12345),(67890);Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0ALTER TABLE t1 MODIFY col1 VARCHAR(5);Query OK, 0 rows affected (2.52 sec)SHOW CREATE TABLE t1\G*************************** 1. row ***************************
Table: t1
CREATE TABLE `t1` (
`id` int NOT NULL AUTO_INCREMENT,
`col1` varchar(5) DEFAULT NULL,
PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=30001
1 row in set (0.00 sec)注意:
当所变更的类型与已经存在的数据行产生冲突时,TiDB 会进行报错处理。在上述例子中,TiDB 将进行如下报错:
alter table t1 modify column col1 varchar(4); ERROR 1406 (22001): Data Too Long, field len 4, data len 5由于和 Async Commit 功能兼容,DDL 在开始进入到 Reorg Data 前会有一定时间(约 2.5s)的等待处理:
Query OK, 0 rows affected (2.52 sec)
修改非聚簇主键成员列的类型
TiDB 支持使用 MODIFY COLUMN 修改 NONCLUSTERED PRIMARY KEY 成员列的数据类型,包括单列非聚簇主键和复合非聚簇主键中的成员列。该操作属于 Reorg-Data 类型的在线 DDL。TiDB 会对表中已有数据执行类型转换,并重组受影响的主键索引;如果该列同时被其他二级索引引用,相关索引也会同步重组。
例如:
CREATE TABLE t_pk (
id DECIMAL(20,0) NOT NULL,
tenant_key VARCHAR(10),
PRIMARY KEY (id) NONCLUSTERED
);
INSERT INTO t_pk VALUES (1, 'a'), (2, 'b');
ALTER TABLE t_pk MODIFY COLUMN id BIGINT NOT NULL;Query OK, 0 rows affected复合非聚簇主键中的成员列也支持该操作:
CREATE TABLE t_composite_pk (
tenant_id BIGINT NOT NULL,
id DECIMAL(20,0) NOT NULL,
PRIMARY KEY (tenant_id, id) NONCLUSTERED
);
ALTER TABLE t_composite_pk MODIFY COLUMN id BIGINT NOT NULL;执行该操作时,TiDB 会检查已有数据是否可以安全转换到目标类型、转换后的主键是否仍保持唯一、转换后的索引长度是否满足限制等。如果类型转换不合法或转换后产生重复主键,DDL 会失败并回滚,不会保留部分转换结果。
该能力仅适用于非聚簇主键。对于 CLUSTERED PRIMARY KEY,如果列类型变更会影响 row handle、行键编码或数据物理组织,TiDB 仍不支持执行。
为已有列添加 AUTO_INCREMENT 属性
TiDB 支持使用 MODIFY COLUMN 为已有的符合条件的整型列添加 AUTO_INCREMENT 属性。典型场景是已有表已经使用整型列作为主键或唯一键,后续需要补充自增 ID 分配能力。
例如:
CREATE TABLE t_auto_inc (
id BIGINT NOT NULL PRIMARY KEY,
source_id BIGINT
);
INSERT INTO t_auto_inc VALUES (1, 100), (2, 200);
ALTER TABLE t_auto_inc MODIFY COLUMN id BIGINT NOT NULL AUTO_INCREMENT;
INSERT INTO t_auto_inc (source_id) VALUES (300);
SELECT * FROM t_auto_inc ORDER BY id;+----+-----------+
| id | source_id |
+----+-----------+
| 1 | 100 |
| 2 | 200 |
| 3 | 300 |
+----+-----------+
3 rows in set (0.00 sec)执行该操作时,TiDB 会检查目标列是否为支持 AUTO_INCREMENT 的整型类型、是否满足非空和索引要求、表中是否已经存在其他 AUTO_INCREMENT 列,以及已有数据是否可以安全用于初始化后续自增 ID 的分配起点。如果已有值达到类型上限、目标列不满足索引约束,或者与 AUTO_RANDOM 等其他 ID 分配能力冲突,DDL 会失败并回滚。
MySQL 兼容性
-
TiDB 支持修改
NONCLUSTERED PRIMARY KEY成员列上需要 Reorg-Data 的类型。对于CLUSTERED PRIMARY KEY,如果列类型变更会影响 row handle 或数据物理组织,则仍不支持。例如:CREATE TABLE t (a DECIMAL(20,0) NOT NULL, PRIMARY KEY (a) NONCLUSTERED); ALTER TABLE t MODIFY COLUMN a BIGINT NOT NULL; Query OK, 0 rows affectedCREATE TABLE t (a int primary key clustered); ALTER TABLE t MODIFY COLUMN a BIGINT NOT NULL; ERROR 8200 (HY000): Unsupported modify column: can't modify column in clustered primary keyCREATE TABLE t (a int primary key nonclustered); ALTER TABLE t MODIFY COLUMN a bigint; Query OK, 0 rows affected (0.01 sec) -
支持使用
MODIFY COLUMN为已有的符合条件的整型列添加AUTO_INCREMENT属性。目标列需要满足AUTO_INCREMENT的类型、NOT NULL、索引和唯一性要求,且表中不能已经存在其他AUTO_INCREMENT列。不支持使用ADD COLUMN添加带有AUTO_INCREMENT属性的新列。 -
不支持修改生成列的类型。例如:
CREATE TABLE t (a INT, b INT as (a+1)); ALTER TABLE t MODIFY COLUMN b VARCHAR(10); ERROR 8200 (HY000): Unsupported modify column: column is generated -
不支持修改分区表上的列类型。例如:
CREATE TABLE t (c1 INT, c2 INT, c3 INT) partition by range columns(c1) ( partition p0 values less than (10), partition p1 values less than (maxvalue)); ALTER TABLE t MODIFY COLUMN c1 DATETIME; ERROR 8200 (HY000): Unsupported modify column: table is partition table -
不支持部分数据类型(例如,部分 TIME 类型、BIT、SET、ENUM、JSON 等)向某些类型的变更,因为 TiDB 的
CAST函数与 MySQL 的行为有一些兼容性问题。例如:CREATE TABLE t (a DECIMAL(13, 7)); ALTER TABLE t MODIFY COLUMN a DATETIME; ERROR 8200 (HY000): Unsupported modify column: change from original type decimal(13,7) to datetime is currently unsupported yet