首页 / MySQL 入门教程 / 修改表结构 ALTER TABLE

MySQL 入门教程

修改表结构 ALTER TABLE

本教程共 46 篇 · 第 13 篇 · 更新于 2026-07-30 · 约 14 分钟阅读

MySQLMySQL 入门教程ALTER TABLEDDL修改表结构ADD COLUMNRENAME TABLE

13. 修改表结构 ALTER TABLE

本节目标:学会用 ALTER TABLE 给表加列、删列、改列类型、改列名、改表名,理解 MODIFY 和 CHANGE 的区别,并知道大表改结构的风险,养成改表前备份的习惯。

需求永远在变。表建好了,后来发现要加个字段、改个类型、换个名字,怎么办?不可能把表删了重建(数据就没了)。这时就用 ALTER TABLE,它是表结构的”修改器”。

13.1 ALTER TABLE 能干什么

ALTER TABLE 是 DDL 里最常用的语句之一,能做这些事:

  • 加列ADD COLUMN
  • 删列DROP COLUMN
  • 改列类型MODIFY COLUMN
  • 改列名和类型CHANGE COLUMN
  • 改列名RENAME COLUMN
  • 改表名RENAME TORENAME TABLE
  • 加/删约束、加/删索引、改字符集、改存储引擎……

这一节聚焦”列和表名”的修改,约束和索引后面有专门章节。

13.2 准备一张测试表

先建张简单的表,后面在它上面演练:

USE shop;

CREATE TABLE vendors (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(50)
);

13.3 ADD COLUMN:加列

给表加一个新列:

ALTER TABLE vendors
ADD COLUMN phone VARCHAR(15);

执行后用 DESC 看一下:

DESC vendors;
+-------+------------------+------+-----+---------+----------------+
| Field | Type             | Null | Key | Default | Extra          |
+-------+------------------+------+-----+---------+----------------+
| id    | int unsigned     | NO   | PRI | NULL    | auto_increment |
| name  | varchar(50)      | YES  |     | NULL    |                |
| phone | varchar(15)      | YES  |     | NULL    |                |
+-------+------------------+------+-----+---------+----------------+

新列默认加到最后

指定列的位置

FIRSTAFTER 控制新列的位置:

-- 加到最前面
ALTER TABLE vendors
ADD COLUMN code CHAR(5) FIRST;

-- 加到 name 列后面
ALTER TABLE vendors
ADD COLUMN email VARCHAR(100) AFTER name;
Note

COLUMN 关键字可省略,ADD phone VARCHAR(15)ADD COLUMN phone VARCHAR(15) 等价。但写上 COLUMN 更清晰,推荐保留。

一次加多列

用多个 ADD 子句,逗号分隔:

ALTER TABLE vendors
ADD COLUMN address VARCHAR(200),
ADD COLUMN remark VARCHAR(100) DEFAULT '';

13.4 DROP COLUMN:删列

删掉一列,连数据一起没:

ALTER TABLE vendors
DROP COLUMN remark;
Warning

删列是不可逆的,列里的数据也跟着没了。删之前确认:

  • 这列真的不用了吗?
  • 有没有视图、存储过程、应用代码依赖它?
  • 重要数据先备份。
    删了再后悔就来不及了。

如果表里只剩一列,DROP COLUMN 会报错—MySQL 不允许一张表没有列:

-- 只剩 id 一列时
ALTER TABLE vendors DROP COLUMN id;
-- ERROR 1090 (42000): You can't remove all columns with ALTER TABLE

一次删多列

ALTER TABLE vendors
DROP COLUMN phone,
DROP COLUMN email;

13.5 MODIFY COLUMN:改列类型

MODIFY 用来改列的类型或约束,但不动列名

-- 把 name 从 VARCHAR(50) 改成 VARCHAR(100)
ALTER TABLE vendors
MODIFY COLUMN name VARCHAR(100) NOT NULL;

执行后再 DESC

+-------+------------------+------+-----+---------+----------------+
| Field | Type             | Null | Key | Default | Extra          |
+-------+------------------+------+-----+---------+----------------+
| name  | varchar(100)     | NO   |     | NULL    |                |
+-------+------------------+------+-----+---------+----------------+

name 变成了 VARCHAR(100),而且变成 NOT NULL 了。

常见的 MODIFY 场景

-- 改长度
ALTER TABLE vendors MODIFY name VARCHAR(200);

-- 改类型
ALTER TABLE vendors MODIFY phone CHAR(11);

-- 加 NOT NULL 和默认值
ALTER TABLE vendors MODIFY name VARCHAR(100) NOT NULL DEFAULT '';

-- 改默认值(用 ALTER 子句)
ALTER TABLE vendors ALTER name SET DEFAULT 'unknown';

-- 删默认值
ALTER TABLE vendors ALTER name DROP DEFAULT;
Note

MODIFY 改类型有风险。把大类型改成小类型(如 VARCHAR(200)VARCHAR(50)),如果已有数据超过新长度,会被截断或报错。把字符串改成数字这类跨类型修改更要小心,最好先备份。

13.6 CHANGE COLUMN:改列名(和类型)

CHANGE 既能改列名,也能同时改类型。语法和 MODIFY 不同:要写旧列名 + 新列名 + 类型

-- 把 phone 列改名为 mobile,类型不变
ALTER TABLE vendors
CHANGE COLUMN phone mobile VARCHAR(15);

-- 改名同时改类型
ALTER TABLE vendors
CHANGE COLUMN mobile contact CHAR(11) NOT NULL;

CHANGE 后面跟着的是:旧名 新名 新类型

MODIFY 和 CHANGE 的区别

这是新手最容易混淆的两个:

命令能改列名吗能改类型吗语法
MODIFY不能MODIFY 列名 新类型
CHANGECHANGE 旧列名 新列名 新类型

简单记:只改类型用 MODIFY,要改名用 CHANGECHANGEMODIFY 的超集,但写起来啰嗦,只改类型时优先用 MODIFY

Tip

CHANGE 改列名时,类型必须重新写一遍,哪怕不变。漏写类型会报语法错误。这是 CHANGE 容易写错的地方。

13.7 RENAME COLUMN:只改列名(8.0+)

从 MySQL 8.0 起,新增了 RENAME COLUMN,专门用来只改列名,不动类型,语法更简洁:

ALTER TABLE vendors
RENAME COLUMN phone TO mobile;

不用写类型,比 CHANGE 干净。但要注意:8.0 才支持,老版本没有这个语法。

Note

三种改列方式总结:

  • 改类型不改名 -> MODIFY
  • 改名又改类型 -> CHANGE
  • 只改名(8.0+)-> RENAME COLUMN

13.8 改存储引擎和字符集

ALTER TABLE 还能改整张表的属性。

改存储引擎

ALTER TABLE vendors ENGINE = MyISAM;
Warning

改存储引擎会重建整张表,大表上非常慢,而且 InnoDB 转 MyISAM 会丢事务、外键等特性。除非必要,别改引擎,新表统一 InnoDB。

改字符集和排序规则

ALTER TABLE vendors
CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;

改的是表的默认字符集,已有列的字符集不会自动跟着变。要让列也变,得用 MODIFY 逐列转换:

ALTER TABLE vendors
MODIFY name VARCHAR(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;

13.9 改表名:RENAME TABLE

表名想改,有两种写法。

方式一:ALTER TABLE … RENAME TO

ALTER TABLE vendors
RENAME TO suppliers;

方式二:RENAME TABLE 语句

RENAME TABLE vendors TO suppliers;

RENAME TABLE 还能一次改多个表:

RENAME TABLE
    vendors TO suppliers,
    buyers TO customers;
Tip

RENAME TABLE 改表名是原子操作(要么全成功要么全失败),而且很快,因为它只改数据字典里的名字,不动数据文件。比 ALTER TABLE ... RENAME 更适合批量改名。

改表名的注意事项

改名前要想清楚这几个影响:

  1. 视图、存储过程、外键:引用了旧表名的对象不会自动更新,改名后可能失效;
  2. 应用代码:SQL 里写死旧表名的地方都要改;
  3. 权限:旧表的权限不会自动迁移到新表名;
  4. 临时表RENAME TABLE 不能改临时表,临时表要用 ALTER TABLE ... RENAME TO
Warning

我之前踩过坑:把一张被外键引用的表改名了,结果外键约束指向了不存在的表,后续操作各种报错。改名前先用 SHOW CREATE TABLE 看看有没有被引用,改完要同步更新依赖对象。

13.10 大表 ALTER 的风险与建议

这一节最后必须讲风险。ALTER TABLE 在大表上可能很慢、甚至锁表。

哪些操作贵

  • 改列类型、改字符集:通常要重建整张表,大表上耗时很长;
  • 加普通索引:要扫描全表建索引;
  • 改存储引擎:整表重建。

哪些操作便宜(8.0+ 优化)

InnoDB 在 8.0 后对很多 DDL 做了即时(INSTANT)优化

  • 加列到末尾:8.0.12+ 支持 INSTANT,秒级完成;
  • 删列:8.0.29+ 支持 INSTANT;
  • 改列默认值:通常很快;
  • 改表名:极快。
Note

26.7 里 INSTANT DDL 覆盖更广,加列、删列、改默认值这类常见操作对大表也几乎无感。但改列类型、改字符集这种仍可能需要重建表,大表上要谨慎。

改表前的安全建议

  1. 先备份mysqldump 导出表结构和数据,改坏了能恢复;
  2. 低峰期操作:大表 ALTER 可能锁表,避开业务高峰;
  3. 先在测试库验证:确认 SQL 语法和效果,再上生产;
  4. 预估耗时:大表可以先在同样规模的测试库测一下耗时;
  5. 用工具:生产大表改结构,业界常用 pt-online-schema-changegh-ost 这类在线改表工具,避免长时间锁表。

13.11 一个完整的改表示例

把这一节的操作串起来,演示一次完整的表结构演进:

-- 原表
CREATE TABLE vendors (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(50)
);

-- 1. 加列
ALTER TABLE vendors
ADD COLUMN phone VARCHAR(15),
ADD COLUMN email VARCHAR(100) AFTER name;

-- 2. 改类型
ALTER TABLE vendors
MODIFY name VARCHAR(100) NOT NULL DEFAULT '';

-- 3. 改列名(8.0+)
ALTER TABLE vendors
RENAME COLUMN phone TO mobile;

-- 4. 删列
ALTER TABLE vendors
DROP COLUMN email;

-- 5. 改表名
RENAME TABLE vendors TO suppliers;

-- 验证
DESC suppliers;
SHOW CREATE TABLE suppliers\G

13.12 小结

这一节掌握了 ALTER TABLE 的全部常用操作:

  • ADD COLUMN 加列,FIRST/AFTER 控制位置;
  • DROP COLUMN 删列,不可逆,删前备份;
  • MODIFY 改类型不改名;
  • CHANGE 改名又改类型(旧名 新名 类型);
  • RENAME COLUMN(8.0+)只改名;
  • RENAME TABLE 改表名,原子操作,可批量;
  • 大表改类型/字符集要重建表,低峰操作、先备份、用在线工具。

下一节讲删除表、临时表和复制表,把表操作这块收尾。