字典表和枚举字段在数据库中如何设计?什么时候应该建表?
简化版
固定且很少变化的取值可以用枚举字段或代码常量;需要运营配置、展示文案、多语言、排序、启停、扩展属性或跨系统共享时,应该设计字典表。面试回答要强调:字典表不是把所有枚举都数据库化,而是给“会变化、要治理、要展示”的业务取值一个可维护入口。
详细版
枚举字段适合状态少、语义稳定、强依赖代码逻辑的场景,比如订单状态、支付状态。这类值通常要参与状态机和业务分支,随便在数据库加一项反而危险。
字典表适合“取值本身是业务配置”的场景,比如证件类型、行业分类、渠道来源、门店标签、风险等级展示文案。常见字段包括 dict_type、code、name、sort_no、enabled、remark。
设计时要注意唯一约束、缓存策略、启停语义和历史数据兼容。字典项下线不代表历史记录失效,因此通常不要物理删除,而是用启停字段控制新增选择。
完整版教学
一、先区分“业务状态”和“展示配置”
很多人看到字段有几个固定值,就想建字典表;也有人把所有取值都写死在代码里。这两种都太极端。关键要看这个取值到底是业务状态,还是展示和配置。
订单状态 CREATED/PAID/SHIPPED/CLOSED 通常是业务状态。它会影响流程流转、权限、库存和资金处理,不应该让运营在后台随便新增一个状态。
而“客户来源:官网、抖音、地推、转介绍”更多是配置和统计口径,后续可能新增渠道、调整展示名、排序或禁用,这类更适合字典表。
二、字典表的基本结构
一个常见字典表可以这样设计:
CREATE TABLE sys_dict_item (
id BIGINT PRIMARY KEY,
dict_type VARCHAR(64) NOT NULL,
code VARCHAR(64) NOT NULL,
name VARCHAR(128) NOT NULL,
sort_no INT NOT NULL DEFAULT 0,
enabled TINYINT NOT NULL DEFAULT 1,
remark VARCHAR(255),
UNIQUE KEY uk_type_code (dict_type, code)
);
dict_type 表示一组字典,例如 customer_source;code 是稳定存储值;name 是展示文案。业务表里通常存 code,不要存 name,否则文案改名会污染历史语义。
三、为什么唯一约束很关键
字典表最怕同一个类型下出现两个相同 code。代码读取时到底用哪一个,会变成不确定行为。
例如 customer_source + douyin 如果重复插入两条,统计报表、下拉选择、缓存加载都可能出现重复项。因此 (dict_type, code) 必须有唯一索引。
| 字段 | 是否稳定 | 用途 |
|---|---|---|
code | 稳定 | 入库、接口、统计 |
name | 可变 | 页面展示 |
sort_no | 可变 | 下拉排序 |
enabled | 可变 | 控制是否可选 |
这个表能帮助面试官看到你知道“存储值”和“展示值”要分离。
四、启停和删除要谨慎
字典项不用了,通常先禁用,不要物理删除。因为历史业务数据还可能引用旧 code,报表和详情页仍需要解释它。
假设客户表里有 100 万条 source='offline_2024' 的历史数据。如果你直接删除字典项,页面展示时就只能显示原始 code,用户体验和报表解释都会变差。
更稳的做法是 enabled=0 后不允许新建业务选择,但历史数据仍能展示名称。
五、字典表要不要缓存
字典数据通常读多写少,非常适合缓存。可以在应用启动时加载,也可以用 Redis 缓存 dict_type -> items。
但缓存要有刷新机制。后台修改字典后,可以发送配置变更事件,或设置较长 TTL 加主动删除。不能让运营改了渠道名,线上页面半天不生效。
如果字典参与核心判断,缓存刷新更要谨慎,必要时发布流程和字典变更要有审批。
六、常见误区与追问
- 误区:所有枚举都应该建字典表。 强业务状态更适合代码枚举和状态机保护,随意数据库化会破坏流程约束。
- 误区:业务表直接存字典名称更方便。 名称会变,应该存稳定 code,展示时再翻译。
- 误区:字典项不用了直接删除。 历史数据仍可能引用它,禁用通常比删除安全。
- 追问:字典表唯一约束怎么建? 通常用
(dict_type, code)唯一约束,保证同一组内 code 不重复。 - 追问:字典缓存怎么刷新? 可用主动失效、配置事件或短 TTL,关键是变更后有可控传播路径。
七、加强记忆
记忆钩子:枚举像代码里的交通规则,字典表像路牌和下拉选项;规则不能让人随便改,路牌需要可配置、可展示、可下线。
回答这题时先划边界,再给表结构和约束,最后补启停、历史兼容和缓存刷新。这样能避免把字典表讲成“简单 key-value 表”的浅层答案。