在 MySQL 中,“字段”和“列”**没有实质区别,可以完全互换使用**——它们指的都是表结构中垂直方向上的一个数据单元,比如
id、
username、
created_at这些名字所代表的那“一竖”。所谓“字段”更偏向逻辑/应用层描述(比如 ORM 里常说“映射字段”),而“列”更偏向 SQL 语法和存储层表述(如
SELECT name FROM user中的
name就是一列),但二者在 MySQL 的 DDL/DML 语境下完全等价。
为什么 ALTER TABLE 里写的是 COLUMN 而不是 FIELD?
因为 SQL 标准语法规定:修改结构的操作(
ADD COLUMN、
DROP COLUMN、
MODIFY COLUMN)统一用
COLUMN关键字。MySQL 不支持
ADD FIELD这种写法——这不是设计差异,而是语法约定。你写
ALTER TABLE t ADD b INT看似省略了
COLUMN,其实是 MySQL 允许的简写,底层仍按列处理。
ADD COLUMN是显式、标准、推荐写法;
ADD是隐式简写,但易引发歧义(比如加索引时也用
ADD) 文档、错误提示、权限系统(如
SELECT权限粒度)全以
COLUMN为单位,不存在
FIELD权限或关键字 工具链(如 mysqldump、Navicat、SQLyog)导出的建表语句一律用
COLUMN
字段类型选错的三个典型翻车现场
类型不是随便填的,选错直接影响数据完整性、查询性能甚至迁移成本。常见踩坑点:
TINYINT存状态却没加
UNSIGNED:本想存 0/1/2,结果插入 3 报错——
TINYINT默认有符号,范围是 -128~127;要存非负小整数,必须写
TINYINT UNSIGNED(范围 0~255)
VARCHAR(255)到处滥用:字符集是 utf8mb4 时,
VARCHAR(255)最大占 1020 字节(255×4),可能触发内部临时表降级为磁盘表;真实业务中,用户名通常
VARCHAR(32)足够,邮箱
VARCHAR(254)即可(RFC 5321 限制)
FLOAT存金额:比如
price FLOAT(10,2)插入
99.99,查出来可能是
99.98999786376953——浮点数精度丢失不可控;必须用
DECIMAL(10,2),它按字符串方式精确存储
计算字段(Generated Column)和普通字段的本质区别
计算字段(也叫生成列)看起来像字段,但它**不占用物理存储空间(除非标记为
STORED)**,值是实时计算出来的。例如:
ALTER TABLE user ADD COLUMN full_name VARCHAR(100) GENERATED ALWAYS AS (CONCAT(first_name, ' ', last_name)) STORED;
注意关键点:
没加STORED就是
VIRTUAL(默认),每次
SELECT都重新执行
CONCAT,无法建索引;加了
STORED才真正落盘、可索引、可被外键引用 计算字段不能直接
INSERT或
UPDATE,否则报错
ERROR 3105 (HY000): The value specified for generated column is not allowed.函数必须是确定性的(
NOW()、
RAND()等非确定函数禁止使用),否则建表失败
真正容易被忽略的是:当你用
SHOW CREATE TABLE查看表结构时,生成列会明确标出
GENERATED ALWAYS AS (...) STORED,但它在
DESCRIBE table输出里和普通列长得一模一样——仅靠
DESCRIBE无法分辨,必须看建表语句或查询
information_schema.COLUMNS表里的
GENERATION_EXPRESSION字段。
