
简介数据库模型设计.doc是一份帮助数据库学习者理清概念模型、逻辑模型与物理模型差异的实用文档适合数据库入门人员、开发工程师及数据建模相关读者。文档从模型种类讲起说明概念模型通过“实体-关系”图表达现实业务场景逻辑模型对概念模型做进一步分解细化物理模型则对应表、字段、主键、外键、索引等真实数据库对象并给出对象转换示例与多维度对比直观展示三者从抽象到具体的递进关系。同时文档还介绍了ERWIN、PowerDesigner两款常用建模工具各自支持的模型类型与典型操作便于读者结合实际项目选择合适的工具。压缩包内为1个doc格式文件大小约189KB全文约9页目录结构清晰。目前已有182人浏览学习适合在数据库课程设计、系统开发或面试复习时作为快速参考资料。1. 数据库模型设计先分清三层再谈建表做数据库设计这几年见的最多的一种翻车是概念模型画得很漂亮、E-R 图人人叫好结果一到物理建模阶段字段类型随便选、外键关系含糊把设计评审开成了“考古现场”。这份《数据库模型设计》文档核心就干了一件事把概念模型、逻辑模型、物理模型这三层的边界、转换规则和常用工具操作讲透。它解决的实际问题是“从业务需求到能跑起来的建表脚本中间到底发生了什么”适合刚接触数据库建模的开发者和需要规范化设计流程的团队。我读完第一遍的感受是内容不花哨但每一页都值得照着做一遍。2. 概念模型与逻辑模型从业务实体到数据结构的两次翻译2.1 概念模型业务视角的 E-R 图不是软件设计图文档里有一句话很关键概念模型是对真实世界中问题域内事物的描述不是对软件设计的描述。这意味着画概念模型时眼里应该只有业务对象和业务规则不要去想表结构、字段类型、主键这些实现层面的东西。概念模型最常用的表达方式就是“实体-关系”图也就是 E-R 图。组成 E-R 图的三个基本要素是实体、属性和关系分别用矩形、椭圆和菱形表示。实体就是业务里的人和物比如学生、课程、订单属性描述实体的特征比如学生的姓名、课程的学时关系表达实体之间的联系。这里有个容易被新手忽略的点E-R 图中的关系是有方向性和基数语义的。一对一、一对多、多对多这三种关系在概念层必须明确区分因为它们决定了后续逻辑模型里外键放在哪张表、需不需要建中间关系表。文档专门提到了子类实体也就是继承关系——本科生是学生的子类教师里的行政人员和授课教师也是子类。在概念模型里子类用带“is a”语义的专门符号表达这个结构如果画对了后面逻辑模型里的超类表设计就有据可依。我见过不少人画概念模型时直接在一个实体框里把所有字段写满连数据类型都标上了。这其实是把概念模型当逻辑模型用了反而掩盖了真正的业务边界。概念模型的价值在于“和业务方对齐”所以它的属性不需要完整定义只要能把业务对象彼此区分开就够了。2.2 逻辑模型概念向关系模型的第一次落地逻辑模型是系统分析设计人员对数据存储观点的反映这个概念听着抽象但落到实际工作里只有两层含义一是把概念模型里的实体细化为有完整属性的实体二是确定实体之间的关联关系在关系模型里怎么表达。文档对逻辑模型的定义是“对概念数据模型进一步的分解和细化”。这个“细化”体现在几个方面实体的属性要补全不能像概念层那样只画几个关键特征每个属性要不要是实体本身的属性、要不要拆出去单独建表都要在逻辑层决定关系的基数也要细化比如概念层是“多对多”逻辑层就要开始考虑这个多对多关系是否需要一个中间表来承载。但主键在这一阶段仍然不需要确定。这里还要注意一点概念模型和逻辑模型的界限在实践里是模糊的文档也承认这一点。ERWIN 干脆只提供逻辑模型和物理模型两种PowerDesigner 早期版本也只提供概念模型和物理模型到 15 版本才把三种模型补全。这说明工具的实现差异也会影响你对模型分层的理解。我的建议是如果用了 ERWIN就认可它“逻辑模型包含概念层职责”的设计如果用了 PowerDesigner 15 以上版本就严格按概念、逻辑、物理三层走每层各自聚焦。2.3 模型转换的对象映射规则文档的“对象转换”一节给出了一个非常实用的对照表这是我从头到尾反复看的重点。概念模型里的实体在逻辑模型里仍然是实体到物理模型就变成了数据库表属性变字段关系变外键多对多关系变关系表。这张表最有价值的点是“多对多”的转换规则订单和产品是多对多关系在概念模型里直接画线但在物理模型里必须确立一张“订单产品明细表”来承载这个关系。很多人物理模型建错很多就错在这里——直接把多对多关系的两端用中间表以外的方案硬连结果行数据冗余得一塌糊涂。概念模型逻辑模型物理模型实体实体表属性属性字段关系一对一/一对多/多对多关系一对多/多对一外键多对多关系关系关系表如订单产品明细表子类is a 超类子类实体表/关系表除对象映射外文档还列了其它对比维度概念模型的属性不需要完整定义逻辑模型要定义实体的完整属性物理模型要确定字段名、长度、数据类型、是否可空、初始值主键在概念层和逻辑层都不用确定只有物理层必须确定主键。这个递进关系如果能贯穿设计全程模型层之间就不会“串味”。2.4 从 E-R 图到建表 SQL一次完整的手工推导概念模型和逻辑模型设计完成后落到物理层的工作就是把上一步确定的实体表、字段、主键、外键关系转成建表 SQL。这里用文档提到的“学生选课”场景就不用工具直接从逻辑模型手工推导一遍。假设某个教学场景里学生和课程是多对多关系学生实体有学号、姓名课程实体有课程号、课程名。逻辑模型阶段要新增一张选课表来承载选课行为选课表里至少要有学号和课程号两个属性外加选课时间和成绩字段。SQL 可以这样写CREATE TABLE student ( student_id INT PRIMARY KEY, student_name VARCHAR(50) NOT NULL ); CREATE TABLE course ( course_id INT PRIMARY KEY, course_name VARCHAR(100) NOT NULL ); -- 学生与课程是多对多关系逻辑模型必须细化出中间表选课表 CREATE TABLE course_selection ( student_id INT NOT NULL, course_id INT NOT NULL, select_time DATETIME, score DECIMAL(5,2), PRIMARY KEY (student_id, course_id), CONSTRAINT fk_sel_student FOREIGN KEY (student_id) REFERENCES student(student_id), CONSTRAINT fk_sel_course FOREIGN KEY (course_id) REFERENCES course(course_id) );这段 SQL 里student 和 course 是基础实体表course_selection 就是文档里说的“关系表”复合主键阻止了同一位学生重复选择同一门课程两个外键约束维护了参照完整性。参数方面要注意主键字段用了 INT 自增类型适合绝大多数场景VARCHAR(50) 的人名长度按国内姓名习惯大概率够用DECIMAL(5,2) 的成绩字段最多支持 999.99放百分制成绩绰绰有余。从这段推导可以看出模型分层的价值如果直接跳到建表你很可能忘了“多对多需要中间表”这条规则或者把成绩字段误放在 student 表里。而顺着概念模型 → 逻辑模型 → 物理模型的顺序走每一步都有上一层的产出作为依据不容易漏表也不容易错放字段。3. ERWIN 实操逻辑模型与物理模型的对应关系3.1 逻辑模型建模实体、子类与关系的正确用法ERWIN 提供 Logical Model 和 Physical Model 两种模型类型外加一个 Logical/Physical Model 显示模式。最后这个不是第三种模型只是同时支持两种视角切换显示。我第一次接触这个工具时被这个设计绕了一下以为是多了一个建模类型后来才明白它只是展示层的变化。在逻辑模型里ERWIN 提供的元素包括实体、完整子类和不确定子类、标识关系、多对多关系、非标识关系。其中“标识关系”和“非标识关系”的区分是这个工具里最重要的建模决策之一我放到下一节单独讲。建逻辑模型时双击画布上的实体即可在里面添加属性属性名称在这一阶段用业务词汇即可不用考虑数据库字段名。3.2 Identifying 与 Non-identifying 关系删除语义差异这是 ERWIN 里最值得细心体会的一组关系。文档明确指出的行为差异如下Identifying relationship标识关系删除父表数据时如果子表有关联数据父表数据删除不掉并且删除时报错。Non-identifying relationship非标识关系删除父表数据时如果子表有关联数据则把子表对应的外键字段值设置为空。关系类型父表删除时子表行为适用场景Identifying relationship禁止删除报错子表必须在父表语境下存在如订单明细依赖订单Non-identifying relationship子表外键置空子表可独立存在如员工表中的部门外键我实际踩过的场景是某系统的员工表有一个 department_id 外键关联部门表当时用的是 Identifying relationship上线后发现部门有员工时删除部门会直接报错数据库层面把数据保护住了。这在规范设计里是好事但如果业务上希望“部门解散后员工自动变为未分配部门”就应该用 Non-identifying relationship。关键判断标准是子表记录离开了父表还能不能独立存在。能独立用 Non-identifying不能独立必须用 Identifying。3.3 物理模型落地主键设置与字段注释显示从逻辑模型切换到物理模型后实体变成表属性变成字段。这时要做三件琐碎但必须的事设置主键、调整字段类型和长度、写字段注释。设置主键在 ERWIN 里的操作是双击实体对象打开 Column 列表选中目标字段然后在右侧 General 选项卡中勾选 Primary Key 复选框。这里有个容易翻车的细节显示字段注释不是默认开启的只有在创建模型时选择了 Logical/Physical 模型类型才能切换显示字段的注释。如果一开始选了纯 Physical 模型后面再想看到逻辑层的注释信息就得重新生成模型后悔药都难找。我一般建模型时一律选 Logical/Physical这样无论画概念还是核对物理字段注释信息都能直接展示。物理模型中字段类型的选择要贴近目标数据库。ERWIN 里可以在模型属性里设定目标数据库平台这样每个字段的数据类型会自动匹配该平台支持的类型比如字符串在 SQL Server 里是 varchar在 Oracle 里是 varchar2。在逻辑模型里写业务属性名物理模型里再映射为正式字段名缩写规则要提前和团队定好。3.4 导出 SQL 与切换数据库从模型到脚本文档提供了两条操作路径切换数据库平台和导出 SQL。切换数据库用菜单 Menu → Database → Choose database这里可以选择目标 DBMS 类型比如 MySQL、Oracle、SQL Server。导出 SQL 则用 Forward Engineer 或 Schema Generation 功能在弹出的窗口里点 Preview 可以预览生成的建表脚本点 Report 可以把 SQL 导出到文件。这里有个实际工作中的小技巧生成 DDL 之前先确认你要导的是全库还是单表。全库导出的脚本包含表、外键、索引和视图定义适合初始化数据库单表导出则用在其它的增量变更场景。Preview 功能我每次都先点开看一眼确认主键和外键约束都已经生成正确再导出为文件。# 导出后的 SQL 文件可以先在本地做语法校验以 MySQL 为例 mysql -u root -p your_database generated_schema.sql上面这段命令的逻辑是把 ERWIN 导出的建表脚本通过 mysql 客户端导入到本地数据库实例验证脚本在目标数据库上能否一次性执行通过。因为不同数据库对 DDL 的细节要求不同比如自增关键字的写法差异这一步能提前暴露兼容性问题。如果脚本执行报错基本可以排查两个方向一是物理模型里的字段类型选择与目标数据库不匹配二是外键约束的顺序不对比如先建子表后建父表。4. PowerDesigner 三模型切换概念、逻辑、物理的完整链路4.1 概念模型Entity、Relationship 与 Association 的选择PowerDesigner 15 版本提供了概念模型、逻辑模型、物理模型三种建模类型这是我个人觉得最完整的建模链路。概念模型部分PowerDesigner 提供了 Entity、Inheritance、Relationship、Association、Association Link、Link/Extended Dependency 等元素。概念模型里最值得关注的是 Relationship 和 Association 的取舍。文档明确指出Association 和 Relationship 类似但 Association 可以设置属性Relationship 不可以设置属性。这意味着当关联关系本身带有业务属性时必须用 Association。举个常见的例子学生和课程之间的关系是“选修”这个关系带“选课时间”和“成绩”两个属性在 PowerDesigner 概念模型里就应该把它建模为 Association而不是简单画一条 Relationship 连线。后续转换到逻辑模型时这个 Association 会自然转化为一张关系表。这个概念层的一个细节值得多说一句Association Link 用来连接 Entity 和 Association关系基数有 0-1、0-n、1-1、1-n 几种。如果你看到一个实体的关联是可选的比如“员工可以没有被分配的部门”就在连接线上用 0-1 表达这在后续属性约束设计里会被继承下来。4.2 逻辑模型与物理模型n-n 关系、Reference 与 Procedure在逻辑模型里PowerDesigner 提供了 Entity、Relationship、n-n Relationship、Inheritance 等元素。这里的 n-n Relationship 是逻辑模型特有的表述方式它表示多对多关系。与概念模型不同的是在逻辑模型里需要更细致地描述这个多对多关系是否要转化为中间实体。物理模型层面的元素则包括 Table、View、Reference、Procedure、Link/Extended Dependency。Reference 对应外键关联这一步在 PowerDesigner 物理模型里是显式的建模对象不像 ERWIN 那样在关系连线时自动生成外键需要你手动创建 Reference 并指定主表和子表的关键字段。Procedure 允许在模型里直接定义存储过程这属于数据库端逻辑的建模适合有复杂业务逻辑需要事前设计的项目。从我自己的操作习惯来看物理模型里每一个 Reference 都应该检查两遍一遍看关联字段是否为主键或唯一键另一遍看删除规则是否需要设置级联。PowerDesigner 可以在 Reference 属性里配置 On Delete 和 On Update 的级联行为这比在创建表之后再去手动改外键约束要方便得多。4.3 命名转换与 DBMS 切换NAME 和 CODE 的坑PowerDesigner 里 NAME 和 CODE 是两个独立字段。NAME 用于显示业务名称比如“学生信息表”CODE 是实际生成的数据库对象名比如“student_info”。文档里给的切换入口是 Menu → Tools → Model Options → Naming Convention可以通过设置控制显示 NAME 还是 CODE也可以配置从 NAME 自动生成 CODE 的转换规则。这里有一个非常容易翻车的场景设计人员在 NAME 里写中文CODE 留空生成数据库时发现表名和字段名都变成了中文或者是乱码。原因在于 PowerDesigner 默认会用 NAME 填充 CODE如果 naming convention 配置不当生成的 DDL 里就会出现非 ASCII 字符。我的习惯是概念模型和逻辑模型阶段NAME 用中文业务词汇进入物理模型前强制走一遍“用英文生成 CODE”的规则转换把所有表名、字段名统一成小写加下划线风格。这一步必须手工核对一遍不能完全依赖工具自动转换因为某些业务词汇的英文映射需要人工确认。# 排查生成脚本中的非法字符检查是否有中文或特殊符号出现在对象名中 grep -nP [\x{4e00}-\x{9fa5}] generated_schema.sql上面这行命令用于在生成的 SQL 文件里搜索中文字符判断模型命名是否已经成功转为英文。如果执行后没有任何输出说明对象定义中没有中文残留可以正常导入如果列出了代码行就要回到 PowerDesigner 的 Naming Convention 设置里调整转换规则。4.4 生成数据库脚本整库导出与单表 PreviewPowerDesigner 生成数据库脚本的入口是 Menu → Database → Generate Database。生成之前要选择目标 DBMS入口是 Menu → Database → Change Current DBMS这里的选择和 ERWIN 里的 Choose database 作用一致决定生成 SQL 的方言。整库导出时第一步先把建模对象列表过一遍确认哪些表、视图、存储过程需要包含在生成范围内。第二步选好输出文件路径和编码方式国内团队建议直接用 UTF-8 编码避免后续导入数据库时出现中文乱码。第三步在选项里勾选是否生成建库语句、外键约束、索引和触发器。如果只需要导出某张表的建表脚本文档里也给出了一个高效操作双击该表打开表属性窗口切换到 Preview 选项卡PowerDesigner 会动态生成该表的 CREATE TABLE 语句。这个功能我用的频率比整库导出还高因为日常变更单表结构调整时直接在表属性里看 Preview 就能确认修改是否符合预期不用等整库脚本生成完再检索目标表。5. 模型设计避坑五个常见翻车点与排查路径5.1 概念模型里过早定义主键导致物理模型返工现象概念模型评审会上业务方指着某个实体当场拍板“这个就用编号做主键”设计人员顺手把主键符号画上去了后面物理建模时发现字段类型和长度都不够用又要回炉重审。原因概念模型不关心主键这是文档里“其它对比”一节明确写的规律。概念层过早确定主键相当于把物理层的决策提前后续优化空间被锁死。解决概念模型阶段只用业务标识属性区分实体比如用“学生编号”这个业务属性描述实体特征即可不设置主键约束。进入物理模型时再根据表结构重新评估主键方案优先考虑自增主键或业务唯一键。5.2 多对多关系不建关系表直接硬连现象某课程项目的数据库里学生表和课程表之间直接建了一个外键字段。导致一个课程要关联几十个学生时只能不断给课程表加冗余行数据越存越乱。原因概念模型里的多对多关系没有在逻辑模型中细化为中间表。文档里订单和产品的关系处理方式是标准答案多对多必须转换为“订单产品明细表”这样的关系实体外键分列在关系表里。解决在逻辑模型设计阶段把每一个多对多关系都圈出来逐一为它们创建中间表并把关系上的属性如选课时间、成绩放进中间表。5.3 Identifying 关系误用删除父表数据报错现象某系统上线后运营人员在后台删除一条已经失效的部门记录系统直接抛出外键约束冲突报错用户以为系统出了 bug。原因物理模型里把部门和员工的关联建成了 Identifying relationship而部门的删除是否允许取决于子表是否有数据这不符合“部门解散后员工继续存在”的业务规则。解决回到 ERWIN 模型里把该关系类型改为 Non-identifying relationship。改完后再导出 SQL重新生成外键约束并明确子表的外键字段允许为空这样删除父表时子表外键会被置空数据仍然保留。5.4 PowerDesigner 里 Association 和 Relationship 混用现象概念模型里所有关系都用 Relationship 画结果录入关系属性时发现根本没地方填只能把属性强行塞在某个实体上造成数据归属混乱。原因Relationship 不支持属性只有 Association 支持。团队对两个概念的区别不熟悉直接沿用了最顺手的连线元素。解决在概念建模规范里明确如果两个实体之间的关系本身需要携带数据一律用 Association如果只是表达关联事实用 Relationship。这个规则最好写进团队设计规范文档。5.5 NAME 和 CODE 映射混乱生成 SQL 出现中文对象名现象PowerDesigner 导出建表脚本后导入数据库执行失败报错信息指向表名或字段名包含非法字符检查发现对象名带着中文拼音缩写混排。原因NAME 字段里写的是中文业务名CODE 字段没有按要求维护工具生成时直接把 NAME 带入了 SQL。解决进入物理模型前先通过 Naming Convention 设置好从 NAME 转换 CODE 的规则再导出脚本前用 grep 命令校验对象名中是否有中文残留。这一步我现在每次导出都强制过一遍宁可多花五分钟检查也不要在导入阶段才排查。6. 模型落地的三个收尾习惯命名、文档与版本最后分享三个我自己一直在用的实操习惯它们不一定写在建模工具的教程里但每一次项目交付都帮我少走弯路。第一个习惯是物理模型建完后强制做一次“模型命名走查”。逐表检查字段名是否符合团队约定的命名规范比如统一小写、下划线分隔、不用保留字。这一步不需要任何工具把导出的 SQL 从头读一遍就够了但读的过程能发现大量潜在问题比如外键字段长度和主键字段长度不一致这种情况不检查 DDL 几乎是发现不了的。第二个习惯是给每个模型配一页“设计说明文档”内容包括用户和业务背景、模型分层说明、每张表的核心职责以及最关键的一条改动记录。模型文件本身无法表达“为什么这么设计”只有文档能承载这个信息。例如某张表为什么选择用业务唯一键而不引入自增主键这类决策如果不写下来三个月后没有任何人能解释清楚。第三个习惯是版本管理。模型文件我全部放入版本库管理和代码一样打标签每次评审通过后归档一个版本。不要用文件名的“review 1”“review 2”来管理那是最容易把版本搞混的方式。碰到团队多人合作时我会规定同一时间只有一个人能在模型文件上做修改改完提交后再合并避免多人同时打开导致工具层面的冲突。以上大致的数据库模型设计落地细节就这些了。从那以后我每次建模都会强制走一遍“三层模型逐层评审 导出前命名走查 交付时附设计说明”的流程这个习惯帮我挡掉过不止一次“设计评审没问题、上线之前全返工”的尴尬。希望帮到你。本文还有配套的精品资源点击获取