MySQL枚举与集合

MySQL枚举与集合

引言

状态、性别、标签这类取值固定的字段,有人用varchar存中文,导致拼写不一、无法约束。MySQL提供ENUM单选和SET多选两个字符串型,把合法值列在定义里,从源头限制脏数据。

ENUM单选

一个字段只能取定义值中的一个,适合性别、订单状态:

CREATE TABLE orders (
    id INT PRIMARY KEY AUTO_INCREMENT,
    status ENUM('待付款','已付款','已发货','已完成','已取消') NOT NULL DEFAULT '待付款'
);

插入不在列表的值,严格模式直接报错,非严格模式存空串,避免写错状态。

SET多选

一个字段可存多个定义值,适合兴趣、标签、权限位:

CREATE TABLE users (
    id INT PRIMARY KEY,
    interest SET('阅读','运动','音乐','旅行') NOT NULL
);
-- 插入多个值,逗号分隔
INSERT INTO users(interest) VALUES('阅读,音乐');

底层按位存储,最多64个成员。

两者区别

  • ENUM单选,SET多选;
  • ENUM内部按序号1、2、3存储,SET按二进制位;
  • ENUM常见于状态机,SET常见于标签和多选权限;
  • SET查单个值用FIND_IN_SET:
    SELECT * FROM users WHERE FIND_IN_SET('阅读', interest);

注意事项

  • 新增/修改枚举值要ALTER TABLE,字段多、值不稳定就别用ENUM;
  • 枚举值排序按内部序号而非字面字母序,容易误判;
  • 中文枚举注意字符集一致;
  • 关系型设计里多值标签更推荐关联表,SET只适合简单固定多选;
  • 不要用ENUM存会频繁增长的分类。

总结

ENUM单选约束状态,SET多选存标签,底层分别用序号和位存储。取值固定且变动少的字段用它们防脏数据,值频繁增加或需要多对多关系时改用独立关联表更规范。


emer 发布于  2026-10-19 07:24