2.2 实体关系模型


2.2 实体关系模型

本节摘要:ER 模型用实体、属性、关系三要素描述业务世界的数据结构,是概念设计的标准工具。本节讲三种基数关系如何识别与表达,重点拆解多对多关系落地成中间表的完整过程——这是评审会上争议最集中的设计点。位置:2.1 流程中"概念设计"阶段的手册,产出物直接喂给 2.3 的范式校对。

ER 图是业务与技术的翻译器

评审会 ER 环节最有意思的现象:业务方和技术方经常在"同一句话"上各说各话。产品说"一个商品可以有多个活动价",设计听到的是"价格要独立建模";产品说"订单发货时可以拆包",设计听到的是"订单和包裹是 1:N"。ER 图的作用就是把这种口语翻译成双方都能指认的图形——实体是名词,属性是形容词,关系是动词。图画出来当天,理解偏差当场暴露;不画,偏差要到上线后某个对不上账的深夜才暴露。

三要素对应的表达惯例:矩形是实体,椭圆是属性,菱形是关系,线上的 1 和 N 标注基数。实际工程里更多用带鸦爪符号的工具或直接用 mermaid 的 erDiagram,语义等价。

三种基数关系与识别方法

一对一(1:1):一个用户一份实名认证档案。识别特征是"两边都唯一"。一对一通常出现在两种场合:主表字段太宽需要垂直拆分(把大字段、低频字段挪去附属表),或者某类信息只对部分主体存在(只有企业用户才有对公账户)。

一对多(1:N):一个客户多个订单。这是关系的绝对主流。落地方向固定:"多"的一方持有"一"一方的主键做外键——orders.customer_id 指向 customer。

多对多(M:N):一个订单包含多个商品,一个商品出现在多个订单里。多对多不能直接建,必须拆出中间表:order_item 各持有两边的主键,把一个 M:N 拆成两个 1:N。

识别基数不需要天赋,只需要追问三个问题:一边的东西,另一边最多有几个?反过来呢?如果两边都可能"多个",中间是不是还夹着业务事实(数量、价格快照、状态)?第三问最关键——夹着的业务事实就该住进中间表。

完整演练:电商三角从口语到 DDL

背景:评审会给出业务口语——客户下单买商品,订单可含多种商品,下单时记录成交价。操作:先画关系,再落表。

把 ER 图翻译成 DDL 时,注意 ORDER_ITEM 这张中间表的字段构成:

CREATE TABLE order_item ( order_id BIGINT UNSIGNED NOT NULL, product_id BIGINT UNSIGNED NOT NULL, quantity INT UNSIGNED NOT NULL, deal_price DECIMAL(10,2) NOT NULL COMMENT '成交价快照', PRIMARY KEY (order_id, product_id) ) ENGINE=InnoDB COMMENT '订单明细';

结果与解读:复合主键保证同一订单同一商品只有一行;deal_price 是本节的灵魂字段——商品表里的 list_price 是"现在的售价",会随促销变动,而订单明细里的价格必须是下单那一刻的快照。评审会曾在这里争论"要不要直接 JOIN 商品表实时取价",答案是不能:三个月后调价,历史订单金额全变,财务对不上账。凡是"当时"的事实,落库时就要定格。这也解释了为什么中间表经常"长胖":它承载的不只是关系本身,还有关系发生时的业务快照。

变式一:如果一个订单里同一商品允许出现多行(比如分批次发货),复合主键要加一列 item_no 序号。变式二:自引用关系也是常见考题——分类表的 parent_id 指向本表主键,表达"分类下有子分类",画 ER 图时实体自己连自己即可。

易错点与评审清单

  • 把关系存成逗号分隔字符串:"商品 ID 列表存一个字段"是初学者最高频的错误,它让所有按商品查订单的查询退化为全表扫描和字符串匹配,范式一节会正式宣判它的死刑;
  • 快照字段遗漏:收货地址、优惠金额、用户昵称,凡是展示"下单当时"语义的字段都要在中间表或订单表定格,评审时逐个过;
  • 基数标错:以为"一个客户只有一个收货地址"结果业务支持多地址,1:1 变 1:N,提前确认业务规则的"现在与未来";
  • 中间表命名随意:建议语义化命名如 order_item 而非 t3、rel1,中间表很快会长出业务字段,名字要配得上它的地位。

评审追问集:关系建模的两个进阶题型

追问一:子类型怎么建模? 商品有实物商品、虚拟商品、服务商品,公共字段占八成,各自特有字段占两成。三种方案摆上台面:单表加类型列(特有字段全 nullable,表宽但简单);主表加多张子表(子表只放特有字段,主键同值一对一,结构清晰但查询要连表);JSON 列装特有属性(灵活但失去约束)。评审会的结论句式:特有字段多且要参与查询约束,拆子表;特有字段纯展示,JSON 列;总数少于十个字段,单表。没有标准答案,但有决策依据。

追问二:关系可以带自己的生命周期吗? 优惠券发放是典型的三要素之外还有状态机的关系:客户领券、使用、过期、退回,每个状态变化都是业务事件。这时关系表要升级为"关系实体"——coupon_grant 表带 status、used_at、expire_at, 甚至把使用流水独立成表。判断口诀:当一段关系需要被单独查询、统计、追溯时,它就该升格为实体。ER 图上表现为菱形旁边又长出了一个矩形,这不是画错了,是建模的进化。

要点回顾:ER 三要素是翻译协议;多对多必拆中间表;中间表是业务快照的天然居所;一对一多为拆分或可选信息的产物;子类型三方案按字段特征选,关系带状态机时升格为实体。概念设计完成后,下一节用范式给这张关系模式做语法校对。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U