上周带了个实习生,小姑娘对着数据库发愁半天,就为一个事儿——怎么往表里加个字段。她翻了一下午文档,试了七八种写法,不是报语法错误,就是把表结构搞坏了。我叹了口气,这问题看着简单,真写起来门道多着呢。今天就把这些门道一次说清楚,从最基础的ALTER TABLE到各种坑,让你看完就能上手。

ALTER TABLE 表名 ADD COLUMN 字段名 数据类型;
比如你有个用户表users,想加个年龄字段:
ALTER TABLE users ADD COLUMN age INT;
就这么简单。但别高兴太早,实际开发里你很少会加这么简单的字段。大多数时候你得考虑:这个字段能不能为空?有没有默认值?要不要加注释?于是写法变成了这样:
ALTER TABLE users ADD COLUMN age INT DEFAULT 0 COMMENT '用户年龄';
DEFAULT 0意思是没填的时候自动补0,COMMENT是给字段加说明,方便后来人看懂。这俩在正式项目里几乎是标配,别偷懒省掉。
接下来是个大坑:字段加在哪儿?默认情况下,新字段会加在表的最末尾。但有时候你想把它放在某个字段旁边,比如想放在name字段后面,就得用AFTER:
ALTER TABLE users ADD COLUMN age INT AFTER name;
ALTER TABLE users ADD COLUMN idnew INT FIRST;
这里提醒一句:MySQL支持AFTER和FIRST,但PostgreSQL、SQL Server这些数据库不支持。跨数据库开发的话,老老实实让它加在末尾,别折腾位置了。
再聊一个新手特别容易犯的错:重复添加字段。你跑了一遍脚本加了字段,第二次没注意又跑了一遍,数据库直接报错:Duplicate column name。怎么避免?加个判断,MySQL里可以这样写:
ALTER TABLE users ADD COLUMN IF NOT EXISTS age INT;
但注意,这个IF NOT EXISTS在MySQL 8.0以下版本不支持。老版本的话,你得先查informationschema表判断字段存不存在,再决定要不要执行ALTER。麻烦是麻烦点,但总比线上报错强。
还有个更隐蔽的坑:大表加字段会锁表。你有个表几千万行数据,直接ALTER TABLE加字段,MySQL会锁住整个表,期间所有读写都得等着。业务高峰期这么搞,分分钟搞挂线上服务。解决办法有两个:一是用在线DDL工具,比如pt-online-schema-change,它通过创建临时表、拷贝数据、切换表名的方式实现无锁变更;二是选业务低峰期操作,比如凌晨两三点。小公司没那么多讲究,但大厂这是铁律。
字段类型的选择也有讲究。加个整数,用INT还是BIGINT?加个字符串,用VARCHAR(50)还是VARCHAR(255)?这里有个实用建议:拿不准长度就按业务需求的最大值再乘1.5倍留余量。比如存手机号,11位就够了,你写VARCHAR(20)绰绰有余。但存用户昵称,有些人能起个50字的超长名字,你写VARCHAR(50)可能就不够,干脆VARCHAR(100)。记住了,字段类型和长度一旦定下来,后期改起来代价极高,因为所有历史数据都得跟着转换。
说到修改字段,顺带提一嘴:ALTER TABLE不仅能加字段,还能改字段。改字段类型用MODIFY,改字段名用CHANGE:
ALTER TABLE users MODIFY age BIGINT;
ALTER TABLE users CHANGE age newage INT;
这两个命令挺实用,但同样有锁表问题,操作前掂量掂量。
说点实战经验。加字段之前,先想清楚三件事:第一,存量数据怎么处理?新加的字段有默认值还好,如果没默认值,存量行的这个字段会是NULL,你的代码得能处理NULL的情况。第二,索引要不要一起建?如果这个字段以后要频繁查询,建议加字段的同时把索引也建了,省得二次操作:
ALTER TABLE users ADD COLUMN email VARCHAR(100), ADD INDEX idxemail (email);
第三,也是最重要的——先在测试环境跑一遍完整的ALTER语句和回滚方案。别直接在生产库上试,出了事哭都来不及。我见过太多人,一激动在生产库上敲了条ALTER,结果字段类型写错,几百万行数据全乱了,只能从备份恢复。
写到这里,该说的都说得差不多了。数据库加字段这事,说破天就是一条ALTER TABLE,但真正的高手会在动手前把类型、位置、默认值、索引、锁表风险、存量数据全过一遍脑子。新手最容易栽跟头的,恰恰是那些看起来不起眼的细节。你把这篇文章里提到的坑都避开,再加几十次字段,基本就成老手了。下次再有人问你数据库怎么加字段,你也能像我一样,噼里啪啦讲出一堆门道来。


