ENUM 和 SET:方便但有代价
个人主页 for_ever_love__ 欢迎各位大佬莅临其他栏目: 大模型开发从0到1 其他栏目: iOS项目总结大全 其他栏目: 我想学python了 其他栏目: iOS UI 文章目录ENUM 和 SET方便但有代价一、ENUM 怎么用二、ENUM 的优点2.1 省空间2.2 数据校验2.3 可读性好三、ENUM 的坑3.1 排序按内部序号不是字符串3.2 修改取值要 ALTER TABLE3.3 空字符串的坑3.4 NULL vs 空字符串3.5 不能和其他表的外键/JOIN 友好共处3.6 迁移麻烦四、SET 是什么SET 的问题五、替代方案方案 1TINYINT 应用层常量方案 2VARCHAR CHECK 约束8.0.16方案 3字典表 外键六、怎么选七、什么时候 ENUM 确实合适八、性能对比九、迁移从 ENUM 改成 TINYINT十、CHECK 约束8.0.16小结ENUM 和 SET方便但有代价状态字段用 ENUM 还是 TINYINT这篇文章讲清楚 ENUM 的优缺点和替代方案。一、ENUM 怎么用CREATETABLEorders(idINTPRIMARYKEY,statusENUM(pending,paid,shipped,done,canceled)NOTNULL);INSERTINTOordersVALUES(1,paid);INSERTINTOordersVALUES(2,unknown);-- 严格模式下报错内部存的是整数1, 2, 3…只占1~2 字节。二、ENUM 的优点2.1 省空间statusENUM(...)-- 1 字节statusVARCHAR(20)-- 实际长度 1 字节utf8mb4 下最多 81 字节statusTINYINT-- 1 字节2.2 数据校验无效值插不进去严格模式下。数据库层保证了取值合法。2.3 可读性好SELECT*FROMordersWHEREstatuspaid;-- 比 WHERE status 2 直观三、ENUM 的坑3.1 排序按内部序号不是字符串INSERTINTOtVALUES(b),(a),(c);-- ENUM 定义ENUM(a,b,c)SELECTvFROMtORDERBYv;-- 结果a, b, c ← 按序号排-- 如果定义是 ENUM(c,b,a)SELECTvFROMtORDERBYv;-- 结果c, b, a ← 序号变了这是最大的坑——排序结果依赖定义顺序改定义的顺序会改变已有查询的结果。字符串列会按字母序排SELECTvFROMtORDERBYv;-- VARCHARa, b, c固定如果业务依赖排序用 CASTORDERBYCAST(vASCHAR)但这样用不了索引。3.2 修改取值要 ALTER TABLE-- 加一个新状态ALTERTABLEordersMODIFYstatusENUM(pending,paid,shipped,done,canceled,refunding);要重建表大表很慢。虽然 appending 到末尾时 MySQL 可能不用重建取决于是否改变存储大小但在中间插入、删除、改顺序都会重建。对比 VARCHAR/TINYINT-- 加一个状态不用改表结构INSERTINTOorder_status_dictVALUES(6,refunding);-- 或者应用层加个常量业务变化时需要加新状态ENUM 的代价不小。3.3 空字符串的坑INSERTINTOorders(status)VALUES(xxx);-- 非严格模式插入空字符串 内部序号为 0SELECTstatusFROMordersWHEREstatus;-- 能查到SELECTstatus0FROMorders;-- 0严格模式下会报错但非严格模式会静默写入。3.4 NULL vs 空字符串statusENUM(a,b)NULL-- 可以有 NULLstatusENUM(a,b)NOTNULL-- 可以有序号 0空字符串两者混淆容易出 bug。3.5 不能和其他表的外键/JOIN 友好共处需要字典表时CREATETABLEstatus_dict(codeVARCHAR(20)PRIMARYKEY,nameVARCHAR(50),sort_orderINT,colorVARCHAR(20));ENUM 没法直接 JOIN 出中文名、颜色这些附加信息。3.6 迁移麻烦从 MySQL 迁到其他数据库时ENUM 的兼容性差。四、SET 是什么SET 是可以多选的 ENUMCREATETABLEusers(idINTPRIMARYKEY,permsSET(read,write,delete,admin));INSERTINTOusersVALUES(1,read,write);INSERTINTOusersVALUES(2,read,delete,admin);内部用位运算存最多 64 个成员。-- 查询有 write 权限的SELECT*FROMusersWHEREFIND_IN_SET(write,perms);SELECT*FROMusersWHEREperms2;-- write 是第 2 位-- 加权限UPDATEusersSETpermsperms|2WHEREid1;SET 的问题同样的坑改定义要 ALTER加上最多 64 个成员查询要用FIND_IN_SET或位运算可读性差FIND_IN_SET用不了索引权限这种场景通常需要更灵活的模型SET 用得更少了权限一般用关联表或多对多表。五、替代方案方案 1TINYINT 应用层常量CREATETABLEorders(idINTPRIMARYKEY,statusTINYINTNOTNULLCOMMENT1待支付 2已支付 3已发货 4完成 5取消);应用层classOrderStatus:PENDING1PAID2SHIPPED3DONE4CANCELED5NAMES{1:待支付,2:已支付,3:已发货,4:完成,5:取消}优点加状态不用改表排序按数值可控跨库兼容好缺点SQL 里是数字可读性差要依赖注释和文档方案 2VARCHAR CHECK 约束8.0.16CREATETABLEorders(idINTPRIMARYKEY,statusVARCHAR(20)NOTNULL,CONSTRAINTchk_statusCHECK(statusIN(pending,paid,shipped,done,canceled)));优点可读性好数据库层有校验加新值只改约束也要 ALTER但不重建数据实际上改 CHECK 约束也要 ALTER TABLE但通常比改 ENUM 轻。方案 3字典表 外键CREATETABLEorder_status(codeVARCHAR(20)PRIMARYKEY,nameVARCHAR(50)NOTNULL,sort_orderINT,colorVARCHAR(20));CREATETABLEorders(idINTPRIMARYKEY,statusVARCHAR(20)NOTNULL,KEYidx_status(status)-- 可以不加物理外键应用层保证);优点可以存中文名、排序、颜色等元信息加状态插入一条记录即可可以做权限、流程配置缺点要 JOIN 才能拿到名称或者应用层缓存字典这是最灵活的方案适合状态含义丰富、会变化的场景。六、怎么选场景推荐取值固定不变性别、是否、星期ENUM 可以状态可能增加TINYINT / VARCHAR 字典表需要排序且顺序有意义TINYINT序号即顺序需要存中文名等元信息字典表需要 JOIN 出附加信息字典表跨数据库兼容VARCHAR / TINYINT权限/多选关联表不用 SET一句话取值确定不变、不需要附加信息 → ENUM 挺好状态会变、要存元信息 → 用字典表或 TINYINT七、什么时候 ENUM 确实合适-- 性别genderENUM(unknown,male,female)-- 是否启用其实 TINYINT(1) 更好enabledENUM(Y,N)-- 星期weekdayENUM(Mon,Tue,Wed,Thu,Fri,Sat,Sun)-- 支付渠道如果确定就这几种channelENUM(alipay,wechat,card)这些场景取值几乎不会变ENUM 的简洁性才有价值。但说实话几乎不会变这个判断经常出错——业务一年后加了新渠道你就要改表了。八、性能对比-- 测试表CREATETABLEa(sENUM(p,paid,done,cancel)NOTNULL,KEYidx(s));CREATETABLEb(sTINYINTNOTNULL,KEYidx(s));CREATETABLEc(sVARCHAR(20)NOTNULL,KEYidx(s));各 500 万行类型表大小等值查询索引大小ENUM最小最快最小TINYINT一样小一样快一样小VARCHAR(20)大 30%略慢大 3 倍ENUM 和 TINYINT 性能完全一样都是整数存储。VARCHAR 略差但差距通常可以接受。九、迁移从 ENUM 改成 TINYINT-- 1. 加新列ALTERTABLEordersADDCOLUMNstatus_newTINYINT;-- 2. 迁移数据UPDATEordersSETstatus_newCASEstatusWHENpendingTHEN1WHENpaidTHEN2WHENshippedTHEN3WHENdoneTHEN4WHENcanceledTHEN5END;-- 3. 删旧列重命名ALTERTABLEordersDROPCOLUMNstatus;ALTERTABLEorders CHANGE status_newstatusTINYINTNOTNULL;-- 4. 加索引ALTERTABLEordersADDKEYidx_status(status);大表用pt-online-schema-change或 gh-ost 做在线变更。十、CHECK 约束8.0.16替代 ENUM 的一个好选择CREATETABLEorders(idINTPRIMARYKEY,statusVARCHAR(20)NOTNULL,amountDECIMAL(10,2),CONSTRAINTchk_statusCHECK(statusIN(pending,paid,done)),CONSTRAINTchk_amountCHECK(amount0));INSERTINTOordersVALUES(1,xxx,10);-- ERROR 3819: Check constraint chk_status is violated优点可读性好SQL 里是字符串数据库层校验修改约束不用重建表通常缺点8.0.16 之前不支持索引不如整数高效迁移到其他库时 CHECK 的兼容性查看约束SELECT*FROMinformation_schema.table_constraintsWHEREconstraint_typeCHECK;小结类型优点缺点适用ENUM省空间、可读、有校验改定义要重建表、排序依赖定义顺序取值真不变SET多选压缩存储同样的坑 查询麻烦基本不用TINYINT快、小、易扩展SQL 里可读性差状态会变VARCHAR CHECK可读、有校验空间略大8.0.16字典表最灵活、可存元信息要 JOIN 或缓存复杂状态我的建议状态字段默认不用 ENUM——业务总会变用 TINYINT或 SMALLINT 应用层常量加状态不用改表需要更多元信息用字典表8.0.16 可以考虑 VARCHAR CHECK兼顾可读性和校验ENUM 不是不能用但要清楚它带来的约束排序依赖定义顺序、加取值要改表。这两个特性在业务演进时很容易成为负担。

相关新闻

第 10 章 Agent 安全与权限控制

第 10 章 Agent 安全与权限控制

前面几章已经让 Agent 能规划、执行、使用工具,也能被监控和追踪。但一个真正能上线的 Agent,还必须解决安全问题。可以把 Agent 想象成一个“新员工”:它能接收指令;它能调用工具;它能访问数据;它还能替你…

2026/10/17 10:45:08 阅读更多 →
Spring Boot酒店管理系统开发实战:从数据库设计到部署答辩全流程

Spring Boot酒店管理系统开发实战:从数据库设计到部署答辩全流程

接手过不少类似的酒店管理项目,说实话这类系统在毕设和课设里出现频率极高,但真正能把业务逻辑理清楚、部署跑通、论文还写得像样的并不算多。这篇内容我就以Spring Boot酒店管理系统为例,把从技术选型、数据库设计、核心代码实现&#xff0c…

2026/10/17 10:45:08 阅读更多 →
ODPS升级:AI原生全模态大数据基础设施

ODPS升级:AI原生全模态大数据基础设施

1. 这不是一次普通升级:当ODPS从“数据仓库”蜕变为AI原生底座“云栖2026 | ODPS 全面升级:构建AI原生的全模态大数据基础设施”——这个标题乍看是场技术发布会预告,但如果你在数据平台一线干过三年以上,第一反应绝不是点开日程表…

2026/10/17 10:45:08 阅读更多 →

最新新闻

Argon架构解析:面向毫秒级SLA的AI服务三层解耦设计

Argon架构解析:面向毫秒级SLA的AI服务三层解耦设计

1. 项目概述:这不是一次简单的模型调用,而是一次系统级工程重构“Google 用 Gemini 4 Argon 构建案例”——这个标题乍看像一则新闻简报,但作为在AI基础设施一线摸爬滚打十多年的从业者,我第一反应是:这根本不是在讲“…

2026/10/17 11:32:28 阅读更多 →
n8n集成Gemini 4 Argon与MCP协议构建真Agent工作流

n8n集成Gemini 4 Argon与MCP协议构建真Agent工作流

1. 这不是“又一个AI工作流”,而是n8n生态里首次真正打通MCP协议的Gemini原生集成 我第一次在某跨平台自动化实验室看到这个标题时,下意识点开想确认是不是标题党——毕竟过去两年里,“用XX模型接入n8n”这类文章我至少扫过四十多篇&#xff…

2026/10/17 11:32:28 阅读更多 →
意图优先的版本控制系统:重构代码协作的认知范式

意图优先的版本控制系统:重构代码协作的认知范式

1. 项目概述:这不是又一个Git客户端,而是一次底层协作范式的重写“7个人、5个月,Anthropic造出了Git替代品”——这个标题在技术圈刷屏时,我正带着团队在做一个跨时区协同的嵌入式固件项目。每天早上打开终端,git pull…

2026/10/17 11:32:28 阅读更多 →
DVWA中CSP绕过原理与四类实战利用手法详解

DVWA中CSP绕过原理与四类实战利用手法详解

1. 项目概述:CSP不是铁壁,而是可被理解、可被分析、可被绕过的策略体系“CSP Bypass”这个词在渗透测试和Web安全研究圈里,几乎等同于一次对开发者安全意识的现场压力测试。它不制造漏洞,却能放大漏洞的价值;它不依赖服…

2026/10/17 11:32:28 阅读更多 →
Vue高德地图动态绘制路线与轨迹巡航实战:从坐标转换到动画性能优化

Vue高德地图动态绘制路线与轨迹巡航实战:从坐标转换到动画性能优化

做后台管理系统这么多年,我接到过最典型的“地图需求”就是标题里这个:高德地图动态绘制路线,轨迹巡航,还指定要用 Vue。第一次听可能觉得不就是画一条线加个小车跑吗,真做完才发现里面全是细节:坐标要转换…

2026/10/17 11:32:28 阅读更多 →
STM32F103移植W5500 ioLibrary:SPI驱动与socket通信实战

STM32F103移植W5500 ioLibrary:SPI驱动与socket通信实战

简介:面向基于STM32F103RCT6等MINISTM32平台的嵌入式开发者,这套W5500 ioLibrary移植工程包含完整的驱动适配代码,可直接参考使用。W5500是集成SPI接口的硬核以太网控制器,自带TCP/IP协议栈,配合STM32的SPI外设即可实现…

2026/10/17 11:31:27 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/17 1:44:59 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 21:54:38 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →