简介:一份讲解数据库模型设计的实用文档,面向数据库设计师、软件开发人员及初学者,用于快速分清概念模型、逻辑模型与物理模型的差异及对象转换关系。文档先介绍三类模型的基本定义,再从模型区别、对象转换等维度细化对比:概念模型主要描述真实世界业务实体,逻辑模型进一步分解并贴近数据库管理系统,物理模型则直接定义表、字段、索引、主外键等具体实现。在此基础上,文档还补充了ERWIN与PowerDesigner两款常用建模工具的实操说明,覆盖逻辑模型、物理模型环境下的常用操作,适合正在做课程设计或项目数据库建模的读者参考。包体仅含1个doc文件,整体约189KB,内容以图文解析为主,无需安装额外环境即可阅读学习。目前已有182人浏览学习,文档目录结构清晰,既有基础概念解读也有工具落地要点,能帮助读者减少模型概念混淆,并快速掌握建模工具中的实际应用。
1. 数据库模型设计:三层模型从来不是选择题,而是递进关系
接到过不少数据库设计文档,大多数人的困惑不在建表,而在概念模型、逻辑模型、物理模型到底怎么划界。这份模型设计资料把三个模型的对象转换、工具操作讲得很细,尤其是 ERWIN 与 PowerDesigner 的对比部分,直接省去翻帮助文档的时间。我的看法很直接:搞不清三层模型边界,后面建的表、外键、索引迟早还要返工。数据库模型设计不是画几张图的事,它决定的是表结构能不能扛住业务变化。适合人群:刚接手数据库设计工作的开发、需要评审同事模型文档的架构师、以及准备用建模工具但不想从头啃手册的人。
2. 概念、逻辑、物理:三层模型的对象转换与各自边界
2.1 概念模型:只描述业务,完全不碰实现
概念模型解决的是“这个世界里有什么”,不是“软件里存什么”。文档里强调得很清楚:概念模型是对真实世界中问题域内事物的描述,不是对软件设计的描述。这句话值得反复读三遍。
最经典的表达方式就是 E-R 图。E-R 图三要素:实体用矩形,属性用椭圆形,关系用菱形。关系又分一对一、一对多、多对多三种。还有子类概念,在 E-R 图里体现为超类和子类的“is a”关系,比如“学生”是超类,“本科生”“研究生”是子类。
我一般画概念模型时有个习惯:刻意不写字段长度,不写数据类型,甚至不写主键。这个阶段写那些就是污染,因为业务讨论时人会被技术细节带偏。你只需要确认三件事——有哪些实体、各自什么属性、实体之间什么关系。
2.2 逻辑模型:把概念模型拆细,但仍不依赖具体数据库
文档里给了个精炼定义:逻辑数据模型反映的是系统分析设计人员对数据存储的观点,是对概念数据模型进一步的分解和细化。
这句话拆开看就是两件事。第一,概念模型里含糊的属性要在这里定义完整,比如“姓名”要明确是“员工姓名”“客户姓名”还是“联系人姓名”;第二,关系要开始向表结构靠拢。一个一对多的关系在逻辑模型里基本能看出来它未来会变成外键,多对多关系在逻辑模型里通常已经意识到需要一张中间表。
逻辑模型的关键点在于:它仍然不绑定具体数据库产品。MySQL、Oracle、SQL Server 都能装下这个模型。它表达的是“我要存什么、怎么组织”,还不是“我在哪个库里怎么建”。
2.3 物理模型:表、字段、主键、索引、默认值全部落定
物理模型是对真实数据库的描述,这话很朴素但信息量极大。文档列出的一组对象就是物理模型的全部内容:表、视图、字段、数据类型、长度、主键、外键、索引、是否可为空、默认值。
我的经验是,从逻辑模型进到物理模型,最常翻车的是数据类型选择。同样是存字符串,varchar(50) 和 char(50) 在固定长度场景下的存储行为完全不同。逻辑模型里写“字符串”是安全的,物理模型里必须落到具体类型和长度。NULL 与 NOT NULL 的决策也在这里定,而这两个决定直接影响后续 SQL 的写法。
物理模型一旦定稿,基本就等于把建表 SQL 的草稿画完了。模型评审到这个阶段,评审人看的已经不是“业务对不对”,而是“性能会不会崩、约束是否完整”。
2.4 对象转换对照:实体、属性、关系如何逐层变身
文档里那张对象转换表是整个资料里最值钱的部分,我把它整理成更直白的形式:
| 概念模型对象 | 逻辑模型对象 | 物理模型对象 |
|---|---|---|
| 实体 | 实体 | 表 |
| 属性 | 属性 | 字段 |
| 关系(一对一、一对多、多对多) | 关系(一对多、多对一) | 外键 |
| 多对多关系 | 关系 | 关系表(中间表) |
| 子类 / is a | 超类 | 通过外键或独立表体现 |
四个要点值得单独说。
第一,多对多在物理模型里必须拆成中间表。比如订单和产品是多对多,物理模型里就有订单产品明细表。这个转换不是可选项,是必选项。
第二,一对多关系在物理模型里落实为外键,但要注意外键落在“多”的那一侧。订单和产品的一对多,外键应该放在订单表(如果一张订单包含多个产品)或放在明细表里。
第三,子类关系在物理模型里最灵活也最坑。超类表加一个类型字段是最轻的做法,子类各自建表再通过外键关联是更规范的做法,具体选哪种取决于子类字段差异大小。
第四,概念模型不需要完整定义属性,逻辑模型需要定义一个实体的完整属性,物理模型则需要确定字段名、长度、数据类型、是否为空、初始值。从模糊到精确,每一步的产出物要求不同,这就是三层模型最核心的边界。
3. ERWIN 两模型实战:逻辑与物理的切换、主键设置与关系外键语义
3.1 Logical/Physical Model:一个模型,两种观察视角
ERWIN 跟其他工具不一样的地方在于:它只提供 Logical Model 和 Physical Model 两种模型类型,没有单独的概念模型。文档里特别点了一句:另外还有 Logical/Physical Model,那不是第三种模型类型,只是同一个模型既可以按 Logical 方式显示,又可按 Physical 方式显示。
这个设计在实际使用中非常舒服。你在 Logical 视图里调实体关系,切到 Physical 视图看自动生成的表结构,两边数据实时同步,不用手动来回转换。习惯操作是:先建 Logical/Physical Model,在 Logical 视图里画实体关系,画完切到 Physical 视图,检查字段类型、长度、NULL 约束是否合理。
工具栏上的 Physical / Logical 切换按钮,就是文档里说的“选择工具栏中的 Physical 显示物理模型,选择 Logical 显示逻辑模型”。这个切换只改视图,不改数据。
3.2 显示字段注释与设置主键的两个具体操作
文档记录了 ERWIN 里两个高频操作,几乎每次建模都要用到。
显示字段注释有个前置条件:只有在创建模型时选择了 Logical/Physical Model,才可以显示字段注释。如果你建模型时只选了 Physical Model,后面想再看逻辑注释,就只能重建模型。这个坑我在项目里踩过,当时已经画了三十多张表,发现注释显示不出来,最后只能全部重来。
设置主键的操作路径是:双击实体,在 Column 列表中选择某个字段,在右侧 Tab 的 General 卡片中选中 Primary Key 复选框。这里说的字段在物理模型里就是表的列。主键选择有一个基本原则:优先用业务里天然不会为空的字段,比如员工编号;如果业务上没有稳定的唯一标识,就要加一个自增主键,而不是硬找业务字段凑数。
3.3 两种关系类型:删除父表数据时行为完全相反
ERWIN 物理模型里最值得警惕的是两对关系概念。
Identifying relationship 是标识关系。它的特点是删除父表数据时,如果子表有关联数据,父表数据删除不掉,并且删除时报错。这个报错不是配置出来的,是由外键约束的完整性语义决定的。我在实际项目里遇到过一次线上删除操作报错,就是这种场景——父表的关联数据还在,硬删必然被数据库拒绝。
Non-identifying relationship 是非标识关系。删除父表数据时,如果子表有关联数据,把子表对应的外键字段值设置为空。也就是说,子表记录还在,但外键字段被置为 NULL。
两者的差别一句话总结:标识关系下子表是父表身份的一部分(子表外键是主键的一部分或直接参与主键),非标识关系下子表独立存在(外键只是普通字段)。画关系线时,标识关系用实线,非标识关系用虚线,这个视觉区分在 ERWIN 里很直观。
选择原则:子表离开父表毫无意义时用标识关系,比如“订单明细”离开“订单”就没意义;子表能独立存在时用非标识关系,比如“员工”和“部门”,员工可以没有部门(暂时未分配),部门删掉员工记录还在。用错关系类型,删除操作的行为就会和你预想的完全不同。
3.4 切换数据库与导出 SQL:Change database 和 Forward Engineer
ERWIN 切换数据库的操作路径很直接:Menu 栏的 Database 然后 Choose database,在弹出的窗口里选目标数据库类型。但这个切换有个容易被忽略的影响:同一套物理模型,在 MySQL 和 Oracle 下生成的数据类型映射不同,比如字符串类型在 MySQL 是 varchar,在 Oracle 里可能要映射为 varchar2。切换数据库类型后,务必检查一遍字段类型映射。
导出 SQL 的路径是 Forward Engineer 或 Schema Generation,模式选 Preview 可以预览 SQL,选 Report 可以把 SQL 导出到文件。
Preview 出来的 SQL 大致长这样:
CREATE TABLE student ( student_id INT NOT NULL, student_name VARCHAR(50), birth_date DATE, PRIMARY KEY (student_id) ); CREATE TABLE course ( course_id INT NOT NULL, course_name VARCHAR(100), teacher_name VARCHAR(50), classroom VARCHAR(50), PRIMARY KEY (course_id) );这段代码是生成结果的示意。注意两点:字段名和类型来自 Physical 模型里的定义,主键约束来自那个打勾的 Primary Key 选项;表间关系则体现为外键 语句,标识关系和非标识关系生成的外键语句在删除语义上会有明显区别。选 Report 导出时建议同时导出到文件和预览窗口,因为文件里的 DDL 信息更完整。
ERWIN 我用了两年多,整体感觉是逻辑/物理一体化的设计让它在中型项目里效率很高,但如果你需要完整的概念模型(比如给业务方做汇报用的 E-R 图),它并不擅长,得靠 PowerDesigner 这种三模型工具补位。
4. PowerDesigner 15:概念、逻辑、物理三模型一次走通
4.1 概念模型:Entity、Inheritance、Relationship 与 Association 的区别
PowerDesigner 的版本差异很多人没搞清楚。文档里的关键信息是:PowerDesigner 12 版本只提供两种模型——概念数据模型(CDM)和物理数据模型(PDM);到 PowerDesigner 15 版本才补上逻辑数据模型(LDM)。所以如果你拿到一个 12 的教程去操作 15,菜单里找不到逻辑模型是很正常的。
概念模型里的元素比 ERWIN 更丰富。Entity、Inheritance、Relationship、Association、Association Link 这几个概念,新手最容易卡在 Association 和 Relationship 的区别上。文档一句话点透了:Association 和 Relationship 类似,只是 Association 可以设置属性,Relationship 不可设置属性。
这个区别很实用。比如员工和项目之间的“参与”关系,如果你想知道某个员工从什么时候开始参与某个项目,这个“开始时间”是关系的属性,不是员工实体的属性,也不是项目实体的属性。用 Association 就能建模这种关系上的属性,用 Relationship 就做不到。关系也能有属性,这是概念模型设计里最容易忽略的点。
Relationship 类型包括 One-One、One-Many、Many-One、Many-Many。Inheritance 对应的是子类继承,比如“教职工”分为“教师”和“行政”,在图纸上用继承连线表示。Association Link 用来连接 Entity 和 Association,关系有 0-1、0-n、1-1、1-n 几种基数。概念模型阶段把基数写清楚,后面生成逻辑模型时外键的 NULL 约束就有依据。
4.2 物理模型:Table、View、Reference、Procedure 四类对象
PowerDesigner 物理模型包含的对象文档列得很明确:Table、View、Reference、Procedure,外加模型间依赖(Link/Extended Dependency)。Table 对应表,View 对应视图,Reference 负责外键关联,Procedure 直接建模存储过程。
Reference 与 ERWIN 的 Identifying / Non-identifying relationship 对应,外键语义由子表外键是否参与主键决定。有一点值得注意:PowerDesigner 在生成物理模型的 Reference 时,默认会带上 ON DELETE RESTRICT 或 ON DELETE SET NULL 这样的规则。如果逻辑模型阶段关系基数画得对,这些规则通常会符合预期;如果基数画错,生成的删除规则也会跟着错。
Table 对象里最常用的是字段级别的设置:字段名、数据类型、长度、是否必填、默认值、是否主键。这里我一般建议把“允许为空”的默认设置保持为 NOT NULL,需要为空再手动放开。反过来做的话,很容易把所有字段都生成成 NULL,后续数据质量会很头疼。
4.3 NAME 与 CODE 显示切换:解决建表字段名不一致的通用办法
PowerDesigner 里有个非常容易踩的显示问题:模型里显示的字段名和生成的数据库字段名对不上。原因在于 PowerDesigner 同时维护 NAME 和 CODE 两个属性,NAME 是显示名(可以写中文),CODE 是数据库里的真实字段名。
解决办法是改全局命名转换配置:Tools 菜单下的 Model Options,进入 Naming Convention。把 NAME 和 CODE 的显示约定改为你想要的方式,比如显示 CODE 隐藏 NAME,或者反过来。改完配置后,新建的模型会按新规则显示;已存在的模型需要逐个对象刷新,这个批量刷新操作容易漏,需要把所有实体或表全选后重新应用命名约定。
我遇到的实际情况是:客户提供的文档里字段名是中文,但测试库里的字段是英文缩写。如果不改显示配置,模型图里的 NAME 会把 CODE 遮住,评审时大家看着中文名觉得没问题,生成的 SQL 用的却是另一个名字。把 CODE 显示出来,这个问题当场暴露。
4.4 批量导出 SQL 与单表预览两个操作路径
PowerDesigner 导出整套表结构的 SQL,路径在 Database 菜单下,选 Generate Database。这个操作默认生成全部对象的 DDL。
如果你只需要某一张表的 SQL,不用走全量生成,直接双击目标表,打开表属性窗口,选 Preview 选项卡,里面就有这张表的完整 CREATE TABLE 语句。
ALTER TABLE student ADD CONSTRAINT fk_student_major FOREIGN KEY (major_id) REFERENCES major (major_id);上面的 SQL 是 Preview 面板里常见的外键语句片段。注意外键名称会自动加上 FK 前缀和表名、字段名,这是 PowerDesigner 的默认命名规则,可以在 Naming Convention 里改成你们团队的统一风格。团队如果没有外键命名规范,建议在这里统一配置,否则每个表生成的外键名风格各异,后续排查关联问题时很费劲。
Change Current DBMS 在 Database 菜单下,用来切换目标数据库类型。和 ERWIN 一样,切换后要重新检查字段类型映射。MySQL 切到 Oracle,varchar 变 varchar2,TEXT 字段可能需要调整为 CLOB,这些映射差异不是自动完美处理的,必须人工复核。
4.5 两个工具的选型判断
把我的真实使用感受说透:ERWIN 逻辑/物理一体化的模式很适合从概念直接落库的中型项目,顺手但不适合做顶层业务建模;PowerDesigner 概念、逻辑、物理三层齐全,适合需要先给业务方看概念模型、再逐层落到物理模型的正式项目。团队如果已经有建模标准,优先跟随标准;没有标准,需要给业务方出 E-R 图汇报的话,选 PowerDesigner,纯内部技术设计 ERWIN 效率更高。
5. 数据库模型设计避坑:识别关系、删除语义与工具版本差异
5.1 概念模型画完直接生成物理模型,逻辑模型被跳过
现象:概念模型评审通过后直接进物理建模,后续发现字段命名、关系基数、外键约束反复返工,开发同事也在抱怨表结构不稳定。
原因:概念模型表达的是业务语义,直接落到物理层会让很多业务规则被压缩成一次跳变,中间的决策没有记录,后面想追溯就得靠人回忆。工具支持三层模型不等于应该跳过中间层。
解决:项目周期允许的情况下,至少保留逻辑模型这一步。逻辑模型会把概念模型中的模糊关系变成明确的二选一(一对一还是一对多),再把所有的属性补全并定义合理的约束。这个环节是物理模型能稳定生成的前提。
5.2 ERWIN 里建了 Physical Model,却找不到字段注释显示
现象:听说 ERWIN 可以显示字段逻辑注释,自己在实体上找了半天,工具栏连 Logical 按钮都没有。
原因:建模型时只选了 Physical Model,没有选 Logical/Physical Model。选项决定了模型是否包含逻辑层信息。
解决:回到创建模型的入口,重新选择 Logical/Physical Model。如果已经画了多张表,最省事的办法是新建一个 Logical/Physical Model,再把旧模型中的表复制过去。复制时注意检查每个实体的属性是否完整迁移,特别是关系线,很容易丢。
5.3 PowerDesigner 切换 DBMS 后,生成 SQL 里出现不兼容的类型
现象:模型在 MySQL 下设计完成,切到 SQL Server 后生成脚本,发现某个字段类型在目标库根本不存在。
原因:Change Current DBMS 只是全局切换了目标数据库类型,已有字段的类型映射需要逐个确认。工具会自动做一部分映射,但遇到自定义类型或者各库差异大的类型(如 TEXT、ENUM)时会漏。
解决:切换后强制走一遍字段复核。用 Generate Database 的 Preview 功能检查每个字段的生成结果,重点看字符串类型、长文本类型、布尔类型、时间类型。我的习惯是切换后把所有表全部预览一遍,按表批量过,发现一个改一个,改完再全量生成。
5.4 标识关系设错,删除父表数据时反复报外键错误
现象:删除业务数据时,子表数据明明可以置空,但数据库一直拒绝,报外键约束冲突。
原因:ERWIN 的关系类型选成了 Identifying relationship,生成的物理外键带上了引用约束,默认拒绝删除被引用的父表数据。这种情况不是说删不掉,是当前关系语义不允许置空。
解决:回到模型双击关系线,把标识关系改为非标识关系,重新生成外键语句,让子表外键允许 NULL,再执行删除。改模型后必须重新导出 SQL,线上库需要单独执行 ALTER TABLE 来替换原有外键约束。
5.5 PowerDesigner 里 NAME 和 CODE 混淆,导致图面显示与 SQL 字段名不一致
现象:模型图上的字段名全是中文,生成的建表语句里字段名是英文,评审时对着图找字段找半天。
原因:物理模型的 CODE 属性是生成 SQL 的名字来源,NAME 只是业务显示名。中文字段说明都填在 NAME 里,CODE 没跟着维护,生成时自然按 CODE 输出。
解决:在 Model Options 的 Naming Convention 中设置按 CODE 显示,让图面直接暴露真实字段名。同时团队约定:新增每个实体或表时,NAME 和 CODE 同步填写,不允许只填一个。生成 SQL 的 Preview 里看到的是 CODE 还是 NAME,就是判断有没有设置错的快速办法。
这五条避坑记录里,标识关系那条是发生在我自己项目上的,那次删除报错排查了将近一天,最后发现是建模时关系类型的语义理解错了。从那以后,我每次画关系线都会先问一句:子表离了父表还能不能单独存在。
6. 三层模型逆向验证:从物理模型回查概念模型的检查清单
6.1 自底向上的验证顺序
正向设计是概念 → 逻辑 → 物理,但我的验证习惯是反着来:先看物理模型里的外键和约束,再回查逻辑模型里的关系卡片,最后回概念模型确认业务语义。因为物理模型是最具体的,错在哪一眼就能看出来,再往上层回溯能更准确定位是哪个环节引入的问题。
第一步,在物理模型里逐个查看外键。每个外键都问两个问题:这张子表是不是真的依赖父表?删除父表数据时应该拒绝还是置空?答案和模型设置不一致就改。
第二步,回逻辑模型查看关系基数。这一点容易看错,我一般用文档里那张对象转换表做对照。一个多对多关系如果没有变成独立的关系表,逻辑模型这步肯定有问题,直接打回。
第三步,回概念模型确认实体关系。重点看有没有把两个本不该直接关联的实体通过关系线连在一起。这一步是业务层检查,需要业务人员在场。
SECOND,建立外键约束时明确指明删除行为。这种需求常见,但偏向具体库的配置,所以在物理设计阶段固定约束行为比较稳妥。
6.2 一个实用的检查模板
日常评审别人的模型,我习惯用下面这套模板快速过:
| 检查项 | 具体做法 | 通过标准 |
|---|---|---|
| 多对多关系 | 概念/逻辑模型里允许,物理模型里必须已拆中间表 | 每个多对多都有对应关系表,外键指向两侧主表 |
| 一对多外键落位 | 外键放在“多”方 | 订单明细表里有订单ID,而不是订单表里放明细ID |
| 标识/非标识选择 | 子表无法独立存在用标识关系,能独立存在用非标识关系 | 删除父表数据时行为符合业务预期 |
| 字段 NULL 约束 | 物理模型逐字段确认 | 属性和关系描述与表字段一一对应,类型和长度无意外缺省 |
| 物理模型字段类型映射 | 切换 DBMS 后逐表预览 | 生成的 DDL 在目标数据库可直接执行 |
| 编码规范 | NAME/CODE 按团队约定显示 | 模型图显示与生成 SQL 字段一致 |
这套模板的来源就是那份文档里的模型区别表和两工具常用操作。你可以把它打印出来贴在工位边上,评审模型时按行打钩。
6.3 模型定稿前的最后一步
模型定稿前的兜底动作,我会做一次全量生成并保存 SQL 脚本:ERWIN 用 Forward Engineer 的 Report 模式,PowerDesigner 用 Generate Database,把生成结果存成一份带日期的脚本文件。验证时再用正则批量检查外键语句的关键字,确认删除行为与模型设置一致。
这个动作不复杂,但能避免两种后悔:一是模型定稿很久后想去追溯决策依据,却找不到当时的物理模型文件;二是在一个没有日常版本管理的建模文件里改了又改,最后谁也说不清哪个版本对应线上结构。
我早期自己带项目时,跳过这个步骤,后来线上数据库和模型文档对不上,排查问题时对着两份结构硬看了两个多小时。从那以后,每次模型定稿都强制走一遍全量 SQL 生成加脚本归档。从那以后,我又加了一条:三份东西必须同步——模型文件、生成的 SQL 脚本、线上数据库结构。希望这套验证顺序和检查细化能帮你少踩几个坑。
本文还有配套的精品资源,点击获取