ALTER TABLE 是 MySQL 中修改現有表結構的核心命令,涵蓋表屬性、欄位屬性、索引與約束的增刪改。本文系統整理各類修改操作的語法、範例與注意事項。
ALTER [IGNORE] TABLE <table_name> <alter_specification> [, <alter_specification>]...
支援一次語句組合多個修改操作,減少鎖表次數與資料複製開銷。
-- 方式一:ALTER TABLE RENAME
ALTER TABLE `student` RENAME TO `s`;
-- 方式二:RENAME TABLE (可跨資料庫、多表原子重命名)
RENAME TABLE `s` TO `student`;
建議:使用 RENAME TABLE,支援多表原子操作,避免中間狀態可見性問題。
ALTER TABLE `student` ORDER BY `stu_id` DESC;
物理重排資料頁,使主鍵順序與查詢順序一致,提升範圍掃描效能。注意:僅對 MyISAM/InnoDB 主鍵聚簇索引有效,大表操作會鎖表長時間,建議低峰期執行。
ALTER TABLE `student`
ADD `sex` CHAR(1) AFTER `stu_name`;
FIRST 或 AFTER col_name 指定位置。NOT NULL 則預設填 NULL;若有 NOT NULL 且無 DEFAULT,MySQL 會依類型填充預設值(數值 0、字串空、日期 '0000-00-00')。ALTER TABLE `student` DROP `sex`;
同步移除該欄位相關索引與約束,不可恢復,謹慎操作。
| 場景 | 語法 | 說明 |
|---|---|---|
| 修改名稱+類型+位置 | CHANGE old_col new_col new_definition [FIRST|AFTER col] | 必須指定完整新定義,含類型、屬性、註解 |
| 僅修改類型/屬性,名稱不變 | MODIFY col_name new_definition [FIRST|AFTER col] | 語法更簡潔,推薦此方式 |
範例:將 stu_tel INT 改為 tel CHAR(3) 並移至 stu_score 之後:
ALTER TABLE `student` CHANGE `stu_tel` `tel` CHAR(3) AFTER `stu_score`;
再改回 INT:
ALTER TABLE `student` MODIFY `tel` INT(3);
<integrity_constraint_change> ::=
ADD [CONSTRAINT [symbol]] PRIMARY KEY [index_type] (key_part, ...)
| ADD [CONSTRAINT [symbol]] UNIQUE [INDEX|KEY] [index_name] [index_type] (key_part, ...)
| ADD [CONSTRAINT [symbol]] FOREIGN KEY [index_name] (col_list) REFERENCES tbl_name (col_list) [ON DELETE reference_option] [ON UPDATE reference_option]
| ADD [CONSTRAINT [symbol]] CHECK (expr) [[NOT] ENFORCED]
| DROP PRIMARY KEY
| DROP FOREIGN KEY fk_symbol
| DROP CONSTRAINT constraint_name
| DROP INDEX index_name
| ALTER INDEX index_name {VISIBLE|INVISIBLE}
-- 刪除主鍵
ALTER TABLE `student` DROP PRIMARY KEY;
-- 新增主鍵
ALTER TABLE `student` ADD PRIMARY KEY (`stu_id`);
-- 新增唯一索引
ALTER TABLE `student` ADD UNIQUE KEY `uk_stu_name` (`stu_name`);
-- 新增外鍵 (假設 class 表存在)
ALTER TABLE `student`
ADD CONSTRAINT `fk_student_class`
FOREIGN KEY (`class_id`) REFERENCES `class`(`class_id`)
ON UPDATE CASCADE ON DELETE RESTRICT;
-- 新增檢查約束 (MySQL 8.0.16+)
ALTER TABLE `student` ADD CONSTRAINT `chk_score` CHECK (`stu_score` BETWEEN 0 AND 100);
-- 刪除外鍵 (需先查詢 CONSTRAINT_NAME)
ALTER TABLE `student` DROP FOREIGN KEY `fk_student_class`;
-- 刪除索引
ALTER TABLE `student` DROP INDEX `uk_stu_name`;
錯誤做法(兩次鎖表、兩次複製):
ALTER TABLE `t` ADD COLUMN `b` VARCHAR(10);
ALTER TABLE `t` ADD INDEX `idx_aa` (`aa`);
正確做法(單次鎖表、單次複製):
ALTER TABLE `t`
ADD COLUMN `b` VARCHAR(10),
ADD INDEX `idx_aa` (`aa`);
-- 僅修改表預設字符集 (不影響現有欄位)
ALTER TABLE `t` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci;
-- 連同現有欄位一起轉換 (會重建表)
ALTER TABLE `t` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `t` DISABLE KEYS; -- 僅 MyISAM 有效,InnoDB 忽略
-- 大量 INSERT/LOAD DATA
ALTER TABLE `t` ENABLE KEYS; -- 重建索引
| 錯誤現象 | 原因 | 解決 |
|---|---|---|
| ERROR 1025 (HY000): Error on rename | 外鍵約束衝突、磁碟空間不足、權限問題 | 檢查外鍵、清理空間、確認權限 |
| ERROR 1833 (HY000): Cannot change column 'c': used in a foreign key constraint | 欄位被外鍵引用,無法直接修改 | 先刪除外鍵 → 修改欄位 → 重建外鍵 |
| 操作極慢、阻塞業務 | 大表複製、鎖表、IO 滿載 | 使用 pt-osc/gh-ost、低峰期、分區表 |
掌握 ALTER TABLE 的完整語法與實戰技巧,能讓資料庫結構演進更安全、高效,是 DBA 與後端開發必備核心技能。