ER图不画业务流程:数据关系、基数与SQL反向建模

发布时间:2026/9/17 16:12:11
ER图不画业务流程:数据关系、基数与SQL反向建模 上周帮一个团队做数据库设计评审他们投屏上来一张ER图我第一眼以为是业务流程图——图上画着用户提交申请→风控审核→放款这种带箭头的链路实体框里还写着审核通过待放款这类状态词。图确实很漂亮也确实把业务讲清楚了但它不是ER图。这件事让我想起一个被反复说、又反复被误解的论点ER图表示的是数据关系而不是业务关系。这两句话只差两个字画出来的东西却完全是两回事。搞清楚这条边界对刚入行的后端、正在准备课程设计的学生、以及要接手别人遗留库的运维来说都能省下大量返工时间。下面我把这条边界从概念、判定、画法、工具到排查完整拆一遍。1. 先把概念掰开ER图到底在描述什么1.1 实体、属性、联系三元组的分工ER图这套东西最早是陈品山在1976年提出的学名叫实体-联系模型三个基本构件就是实体、属性、联系。这三个词看起来很朴素但它们的定义范围卡得很死一旦放宽就会失控。实体Entity指的是系统里需要被记录下来的同类事物的集合注意是集合不是某一个具体对象。比如客户是实体张三这个客户只是实体的一个实例。很多人画图时把实例写进框里框里写张三2024年3月的订单这就跑偏了因为实例是数据行不是模型元素。属性Attribute是实体自身携带的描述信息比如客户有手机号、注册时间、证件号。联系Relationship是两个或多个实体之间的关联比如客户与账户之间有持有这个联系。关键在于这三样东西描述的通通是数据结构层面的事实也就是数据要存哪些东西、彼此怎么挂靠。它不负责回答谁先谁后什么条件下发生发生了要通知谁。这三类问题属于流程与行为是另一套图要管的事。1.2 数据关系与业务关系的分界线在哪我总结了一条判断标准非常实用把图上所有实体名和联系名取出来如果里面出现了动词的时态、状态形容词、条件判断、审批层级、时间先后那它大概率是业务关系不该出现在ER图里。再具体一点数据关系说的是数量上的约束——一个客户能有几个账户一张订单里能放几个商品一个商品能出现在几张订单里。这就是所谓的基数Cardinality1:1、1:N、M:N。基数是一句关于能配几个的陈述跟流程无关。业务关系说的是行为上的流转——客户申请之后先走风控还是先走人工审批不通过是退回还是终结放款之后多少天内要还第一期。这些是流程性的东西会随时间、政策、运营策略变化。一个特别容易混淆的例子电商里的订单-支付。一张订单可以有多笔支付记录——这是数据关系要画。支付失败之后订单要在30分钟内自动关闭——这是业务关系不该画。前者决定了表怎么建后者决定了定时任务怎么写。1.3 用银行储蓄系统做一次对照实验拿银行储蓄系统ER图这个被搜烂的关键词举例。假设有客户、账户、交易流水、网点、柜员这几样东西。数据关系视角下应该画出来的东西客户与账户是一对多一个客户能开多个账户一个账户归属于一个客户账户与交易流水是一对多网点与柜员是一对多柜员与交易流水是一对多一个柜员能办理多笔业务。这四条连线构成了骨架数据库照着它就能建表。业务关系视角下大家爱塞进来的东西先是开户→存款→取款→销户这条链路再是大额取款需要主管授权还有账户余额不足时拒绝取款。这三条里第二条和第三条其实是有数据痕迹的——授权可能对应一张授权记录表拒绝可能落一条失败流水。但它们作为规则本身不该以箭头的形式画在实体之间。你可以把授权记录建成实体那才是数据模型的活把余额不足则拒绝写成校验规则那是代码的活。这条边界一划清图立刻干净。图上的每一条线都能对应到数据库里的一条外键或一张中间表评审的时候谁也挑不出毛病。2. 为什么业务关系总被塞进ER图2.1 三种高频误画法第一种用箭头表示流程方向。实体之间画一条带箭头的线箭头从客户指向订单意思是客户下单。ER图里的方向箭头其实另有含义它通常表示引用方向或依赖方向比如外键指向被引用表跟业务流程的先后顺序没关系。被引用端永远是主引用端永远是从这个方向由外键决定不由谁先动决定。第二种框里写状态。实体框里写待审核订单已完成订单这等于把状态机塞进了实体。正确做法是订单实体加一个 status 属性或者单独建订单状态字典表。状态是字段的取值不是实体的名字一个订单不会因为状态变了就变成另一个实体。第三种把动作画成实体。审核审批支付这种动名词被画成方框然后连一堆线。除非它背后真的有一张表要落记录比如审核日志表否则它不该是实体。动作是方法不是数据。2.2 业务关系该放哪儿流程性的东西有它自己的图时序图Sequence Diagram管交互顺序活动图Activity Diagram管流程分支状态机图State Machine Diagram管单个对象的状态迁移用例图Use Case Diagram管角色和功能边界。这几种图各有各的用途混用反而谁都讲不清楚。我一般的做法是ER图定骨架状态机图定关节。订单这张表里有一个 status 字段status 的取值范围和迁移规则用状态机图讲清楚ER图只负责说订单表有 status 这个字段。两张图各司其职产品经理看状态机图能确认流程对不对开发看ER图能确认表建得对不对。谁也不用去猜对方那张图的意思。2.3 混淆之后要付出的代价代价有三个都很实际。一是建模返工。业务规则会变流程会调整如果规则画进了ER图每次流程调整都要改模型改完之后还要同步到数据库工作量翻倍。而实际上流程调整根本不需要动表结构因为表结构描述的是数据结构本来就该稳定。二是表结构冗余。为了表达这单走到哪一步了很多人会加一堆布尔字段is_audited、is_paid、is_shipped、is_closed字段之间互相矛盾数据一致性根本管不住。正确做法是一个 status 加一张流转记录表。一个状态字段加一张流转表能表达任意复杂的流程而且流程改了不用改表。三是沟通错位。产品经理看ER图以为在看流程开发看ER图以为在看表结构两边对同一张图的解读不同评审会上就得吵。这种争吵往往不是因为谁水平差而是因为图本身承载了两种含义这是画图人的责任。3. 数据关系的四种基数与关键画法3.1 一对一、一对多、多对多的判定逻辑判定方法就一句话站在任意一端问另一端能配几个两边都问完答案就是基数。这句话听起来简单但实际操作时很多人只问一边。一对一1:1一个用户对应一份实名认证信息一份认证信息只属于一个用户。实际建模里1:1经常是因为字段太多或者访问频率差异大而拆表很少是业务上真的强制一对一。既然是拆表认证信息这张表的主键一般直接引用用户主键不另设自增。一对多1:N最普遍。客户对订单、部门对员工、订单对订单明细。判断的时候要注意外键永远放在多的那一端因为多端只能有一个父那就在多端存一个父的标识。反过来的话一对多就没法表达了。多对多M:N必须拆成中间表。学生选课、订单商品、文章标签都是典型的多对多。中间表通常由两个外键组成联合主键如果业务上允许重复——比如同一个商品在一张订单里出现两次——就要加代理主键或者把数量字段也放进主键。3.2 主键、外键、候选键在图上怎么标很多人搜ER图主键怎么表示这个问题本身就有两个答案取决于你画的是概念模型还是物理模型。概念模型用陈氏记号法属性下面画一条下划线表示主键虚线表示部分键弱实体双下划线表示多值属性。物理模型用 Crows Foot 或 IE 记号法PowerDesigner、Navicat、MySQL Workbench 默认就是这种主键字段前面标 PK外键标 FK唯一键标 U1、U2。实体画成表格样式字段一行一行列出来。记号体系主键表示外键表示常见工具陈氏记号法属性名加下划线一般不单独体现Visio、draw.ioCrows FootPK 前缀或钥匙图标FK 前缀PowerDesigner、MySQL WorkbenchUML 类图属性前加约束标记关联线加角色名StarUML、PlantUMLIDEF1X主键区独立成块虚线关联ERwin选哪种不重要重要的是整张图统一别一半陈氏一半Crows Foot。混用会让看图的人先花十分钟对齐记号含义纯属浪费时间。3.3 弱实体与菱形联系的取舍弱实体Weak Entity指的是自己没有独立主键、必须依附于另一个实体存在的实体。典型例子是订单明细依赖订单订单没了明细就没意义。弱实体在图上一般画双线矩形它跟强实体的联系用双线菱形这种联系叫标识性联系。这张表的主键通常是父表主键加自身序号的组合。菱形联系要不要画取决于你在做哪个层次的模型。概念模型里菱形是主角它把实体之间的关系可视化。物理模型里菱形基本消失因为你已经在表里用外键表达了。PowerDesigner 生成物理模型时会自动把菱形转成外键列这个转换过程值得盯一眼有时候基数判断错了会生成错误的中间表。比如本该一对多的关系被标成了多对多工具就会凭空给你加一张中间表这张表在业务上毫无意义却会在入库时带来一堆冗余数据。4. 从SQL反向生成ER图工具与实操4.1 MySQL表结构导出的三条路径路径一mysqldump 只导结构。这是最常用的方式命令如下mysqldump -h 127.0.0.1 -u root -p --no-data --skip-add-drop-table mydb schema.sql--no-data 表示不带数据只带建表语句文件小、跑得快。加上 --skip-add-drop-table 是为了让后续工具解析时不被 DROP TABLE 干扰。有些解析器遇到 DROP 语句会先把表删掉再重建如果顺序乱了就容易出问题加上这个参数更稳妥。路径二information_schema 直接查。适合你把结构导到 Excel 里做对照或者自己写脚本生成图SELECT TABLE_NAME, COLUMN_NAME, COLUMN_TYPE, COLUMN_KEY, IS_NULLABLE FROM information_schema.COLUMNS WHERE TABLE_SCHEMA mydb ORDER BY TABLE_NAME, ORDINAL_POSITION;这条路的好处是可以精准筛选比如只导某几张表或者排除掉视图。路径三SHOW CREATE TABLE 单表看。适合排查个别表不适合批量。表多的时候一条条来太慢。注意导出的 schema.sql 一定要先确认字符集和排序规则utf8mb4 和 latin1 混在一起导进建模工具后中文注释会变乱码而且乱码之后很难恢复因为原始信息已经丢了。4.2 SQL转ER图工具的选型对比工具类型反向工程能力价格适合场景PowerDesigner桌面强支持多种方言商业授权正规项目、企业级建模MySQL Workbench桌面支持免费快速看库、个人开发Navicat桌面支持商业已经在用 Navicat 的团队draw.io网页加桌面不支持纯手画免费画概念图、评审用在线SQL转ER图工具网页支持部分方言免费或限次临时应急、不方便装软件关于在线工具我的态度很明确结构不涉密的库可以图省事用在线工具涉密的库坚决本地处理。你把建表语句贴到网页上等于把整个数据模型的轮廓交出去了。字段名、表名、注释这些东西组合起来懂行的人能推断出业务结构这种风险不值得为省几分钟去冒。在线工具的另一个隐性问题是方言支持不全。分区表、生成列、外键级联、注释这些语法各家解析器支持程度差异很大经常出现表识别出来了但外键全丢的情况。遇到这种只能回到本地工具或者手工补线。4.3 PowerDesigner反向工程的完整步骤这套流程我跑过很多遍按这个顺序走基本不踩坑。第一步File 菜单下新建 ModelModel type 选 Physical Data ModelDBMS 选你实际的版本MySQL 5.0 之后的版本一般选 MySQL 5.0 或者 MySQL 8。第二步Database 菜单下选 Reverse Engineer Database弹窗里选 Using script files把你导出的 schema.sql 加进去。第三步点 Options至少勾上 Tables、Columns、Primary keys、Foreign keys、Indexes。如果不勾 Foreign keys生成出来的图里没有任何连线你会以为是工具坏了其实是自己在配置里把外键过滤掉了。第四步点确定等它跑完。表多的时候几百张会卡一会儿耐心等。第五步生成完之后第一件事是对表数量。原库有多少张表图里应该有多少个实体对不上就是解析漏了得回去看解析日志。第六步切到概念模型Tools 菜单下选 Generate Conceptual Data Model。这一步会把菱形联系补出来但基数经常需要手工修。第七步调整布局。PowerDesigner 自带的 Auto-Layout 对大图效果一般我一般手工按业务域分块摆核心表放中间字典表放边上。提示反向工程生成的模型默认不带注释。如果建表语句里有 COMMENT需要在 Options 里勾上 Comment否则表名下面那行说明是空的评审时还得一个个补。5. 从零手工建模流程与规范5.1 从业务需求抽取实体抽取实体有个笨办法但很管用把需求文档里的名词圈出来把动词划掉。名词候选就是实体形容词和状态词是属性动词是联系或者流程。这一步不需要任何工具一支笔一张纸就行。圈完之后做一轮清洗。同义词合并比如用户和会员是不是同一张表得问清楚。上级概念剔除有了订单明细还要不要商品答案是要因为商品是独立实体。中间产物判断比如购物车是实体还是临时结构看业务要不要持久化如果只在会话里存在就不用建表。这一步别急着画图先在纸上列一张实体清单写清楚每个实体的主键候选和职责边界。清单没理顺就动笔改起来比重画还费劲。5.2 命名与布局规范命名上我坚持三条。实体名单数、全小写、下划线分隔比如 customer、order_item、payment_record。联系名用动词短语但只描述结构比如 customer_owns_account。避免保留字order、user、group 这些在 MySQL 里都要小心要么加前缀要么换名。布局上我一般把核心实体放中间字典表放右侧一列关联表夹在它连接的两张主表之间。这样看图的视线动线最顺评审的时候别人跟着你的布局走不用来回找。注意别追求图好看。ER图是工程文档不是海报。字段对齐、连线交叉少、注释完整比配色重要得多。我见过配色堪比杂志的ER图结果字段名全是拼音缩写谁也看不懂。5.3 交付前的自检清单我每次交模型前都会过一遍这个清单。每个实体有且只有一个主键主键类型全库统一要么全用自增 bigint要么全用 UUID不要混着来。所有外键都有对应的被引用表而且被引用字段是主键或唯一键。多对多全部拆成了中间表中间表没有业务属性泄漏也就是说业务字段不该出现在中间表里。没有孤立的实体也就是没有任何连线的表出现这种情况大概率是漏画了。没有循环外键A 引用 B、B 引用 A 这种情况插入数据时会死锁。字段命名风格统一时区、金额单位、状态值都在注释里写清楚。最后一条也是最重要的一条图上没有任何流程箭头、状态词、审批层级。看到这些东西就说明边界又破了。6. 常见问题与排查实录6.1 问题速查表现象大概率原因排查方法反向工程后没有连线没勾 Foreign keys 或建表语句无外键检查 Options 勾选项查 schema.sql表数量对不上视图被当表或分区表解析失败过滤 VIEW看解析日志中文注释乱码字符集不匹配统一转 utf8mb4 再导入中间表字段重复联合主键设置错误检查中间表的 PRIMARY KEY 定义生成的图一团乱麻表太多没分域按业务域拆成多张子图用分组功能一对多方向画反了外键放错端外键永远在多端6.2 我踩过的几个坑坑一拿生产库直接反向工程。生产库里有临时表、备份表、历史遗留的废弃表全导进来图就没法看了。正确做法是只导核心 schema或者在建表语句里先过滤。我吃过一次亏导进来三百多张表光清理废弃表就花了一下午。坑二以为 ER 图能替代文档。图能表达结构表达不了为什么这个字段是 varchar(64) 而不是 varchar(128)。模型必须配一份字段说明否则半年后自己都看不懂。我现在交模型一定配一份字段字典哪怕只是 Excel。坑三把业务规则写成联系。我见过一张图实体之间连了一条线叫超过5000元需要复核这种联系在数据库里根本没地方落最后只能删掉重画。而且这种线一旦画上去别的人照着它建表就会建出一张莫名其妙的表。坑四忽略外键的物理代价。图上有外键约束很好看但高并发写入场景下外键检查是性能开销。很多团队线上库是不加外键约束的只在代码层保证。这种时候ER图上的连线就变成了逻辑外键图里要标注清楚不然新人会以为数据库里真的有约束测试的时候发现插不进数据还要来问你怎么回事。我在实际项目里最深的体会是ER图的价值不在于画得多全而在于边界守得多严。一张只有十五个实体、但每条线都能对上一张真实表的ER图比一张画了八十个框、线像蛛网的ER图有用得多。后者看着热闹真要照着建表的时候你会发现一半的连线不知道该落成外键还是落成代码里的 if 判断。下次再动笔之前不妨先问自己一句话这条线在数据库里对应什么如果答案是一段代码而不是一个约束那就把它从图里拿掉。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询