mysql中的enum类型是枚举类型,属于字符串对象的一种,它允许字段在创建表时预先定义一组固定的可选值,后续插入或更新该字段时,只能从这组预定义值中选择,无法直接写入未定义的内容。

enum类型的基本定义方式
在创建mysql表时,可以通过ENUM('值1','值2',...)的语法来定义enum类型的字段,预定义的值需要用单引号包裹,多个值之间用逗号分隔。下面是一个简单的建表示例:
-- 创建用户表,用户状态字段使用enum类型
CREATE TABLE user_info (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
-- 预定义三个可选状态:正常、冻结、注销
user_status ENUM('normal','frozen','cancel') DEFAULT 'normal'
);
enum类型的存储与取值规则
enum类型在存储时并不是直接存储字符串本身,而是存储每个预定义值对应的索引数字,索引从1开始计数。比如上面示例中,normal对应索引1,frozen对应索引2,cancel对应索引3。如果插入时写入的是预定义值的字符串,mysql会自动转换为对应的索引存储;如果直接写入数字,会直接作为索引匹配对应的枚举值。
查询enum字段时,默认返回的是预定义的字符串值,而不是存储的索引数字。如果要获取存储的索引值,可以使用+0的方式转换:
-- 插入测试数据
INSERT INTO user_info (username, user_status) VALUES ('张三', 'normal');
INSERT INTO user_info (username, user_status) VALUES ('李四', 2); -- 2对应frozen状态
-- 查询返回字符串值
SELECT username, user_status FROM user_info;
-- 查询返回索引值
SELECT username, user_status+0 AS status_index FROM user_info;
enum类型的使用限制
- 预定义枚举值的数量最多支持65535个,实际使用中不建议定义过多,否则会影响存储和查询效率。
- enum字段的预定义值不建议修改,如果后续需要新增枚举值,需要使用
ALTER TABLE语句修改字段定义,修改过程中可能会触发全表扫描,对大表影响较大。 - enum字段不支持存储空字符串,除非预定义值中显式包含空字符串,否则写入空字符串会被转换为空值或者报错。
- 如果插入的值不在预定义的枚举列表中,且sql模式没有开启严格模式,mysql会将值转换为空字符串存储,同时产生警告;如果开启严格模式,会直接返回错误。
enum类型的适用场景
enum类型适合用在字段取值范围固定且不会频繁变动的场景,比如性别字段(男、女、未知)、订单状态字段(待支付、已支付、已发货、已完成、已取消)、审核状态字段(待审核、审核通过、审核驳回)等。这类场景下使用enum类型可以天然限制字段的取值范围,避免无效数据写入,同时比使用int类型存储状态码更直观,不需要额外的状态码映射表。
enum类型与varchar类型的对比
| 对比维度 | enum类型 | varchar类型 |
|---|---|---|
| 取值限制 | 只能从预定义值中选择 | 可以写入任意符合长度的字符串 |
| 存储空间 | 根据枚举值数量占用1或2字节 | 根据实际存储的字符串长度占用空间 |
| 修改枚举值成本 | 需要修改表结构,大表成本高 | 不需要修改表结构,直接写入新值即可 |
| 可读性 | 存储索引,查询返回字符串,可读性较好 | 直接存储字符串,可读性好但无取值限制 |
使用enum类型的注意事项
不要在enum的预定义值中包含数字,否则插入时如果写入数字,mysql会优先匹配索引而不是字符串值,容易出现逻辑错误。
另外,如果业务中的枚举值后续可能会频繁新增或者变动,不建议使用enum类型,更适合使用varchar类型配合应用层的取值校验,或者使用独立的字典表存储枚举值,通过外键关联的方式保证数据规范性。