下午题第一道是结构化分析与设计,考的是数据流图,第二道就是数据库设计,这两道加起来差不多30分,占了下午场整整40%的分值。很多人上午选择题背得滚瓜烂熟,到了下午题却在这里反复丢分。说实话,这两道题是所有下午题里最容易拿分、也最容易练出稳定正确率的模块,关键是搞清楚考试到底在考什么、阅卷时在找什么。这篇内容就是围绕软件设计师考试中系统设计与数据库设计这两大块,把我在备考和刷题过程中总结的套路、易错点、实用方法完整捋一遍。不管是零基础第一次考,还是二战想冲高分,只要把DFD数据流图、数据库概念设计、ER图转关系模式、范式判定这几块练扎实,下午题基本就稳了一半。1. 下午题的分数结构:先搞清楚考什么1.1 系统设计与数据库设计在考试里的真实分布软件设计师考试的下午题一共六道题,总分75分,合格线45分。题型分布一般是:第1题:结构化分析与设计,主要考数据流图,有时带数据字典,15分第2题:数据库设计,考E-R图、关系模式、范式、SQL语句,15分第3题:UML建模,用例图、类图、顺序图、状态图等,15分第4题:数据结构与算法,15分第5题:程序设计(C语言或Java),15分第6题:系统设计、测试、架构等综合题,15分你会发现,和“系统设计”直接相关的其实是第1、3、6题,而“数据库设计”是独立的第2题。但大家通常说的“系统设计与数据库设计”,核心就是前两道题。这两道题有个共同特点——它们不是纯背诵题,也不是纯编程题,而是“建模题”。你要按照题目给出的上下文,画出或补全模型,并且把模型转成可落地的关系模式或代码。这里先给一个总判断:数据流图侧重视图逻辑和规范检查,数据库设计题侧重完整的数据建模链条,两者考的是“有没有工程设计思维”,而不是“记没记住知识点”。这也是为什么很多程序员去裸考,上午题能过,下午题却折在这两道题上——因为平时写代码的人不太习惯用这种“画图建模、逐条校验”的方式思考问题。1.2 阅卷方式决定了答题策略另一个需要先建立认知的事情:下午题是人工阅卷还是电脑辅助阅卷,答案其实不重要,重要的是阅卷老师手里有一张“采分表”。他一眼扫过去,看你有没有写对几个关键点,比如“外键名称”“主键名称”“关系模式包括哪些列”“某个加工是否缺少输入数据流”。这带来一个非常实际的答题启示:命中的关键词和结构表达,比语句是否优美重要得多。很多考生明明会做,却因为写得“模棱两可”丢了分,比如把关系模式写成“学生(学号, 姓名, 系别)”忘记标下划线主键,或者把数据流图中外部实体的名字写错方向。阅卷时这种细节就是采分点,少了就是少了,不会因为你整体思路对就给你补全。所以我的建议是,平时做真题时一定要严格按“采分点模式”对答案。不要只看“思路差不多”就放过,要列出来:这个加工的名字我写对没有,数据流的方向标对没有,关系模式的主键外键标出来没有,规范化分解后的每个模式是否满足3NF。标准就是标准,模拟阶段苛刻一点,考场上才不会手松。2. 系统设计:DFD数据流图的绘制与检验2.1 数据流图的基本元素与命名铁律数据流图(DFD)是结构化分析的核心产出,用来表达系统“做什么”,不关心“怎么做”。考试里给你一个业务场景,让你补全外部实体、数据存储、加工、数据流,或者指出某个图中的错误。基本元素四个:外部实体:用矩形表示,是数据的来源或去向,比如“学生”“图书管理员”“教务老师”“支付平台”,注意它不属于系统内部。加工:用圆角矩形或带圆边的矩形表示,也叫处理、功能,是对数据执行的某种操作,比如“验证登录信息”“计算考试总分”。数据流:用箭头表示,描述数据的流动方向。箭头方向就是数据实际移动的方向,不是“控制流”。数据存储:用开口矩形或两条平行线表示,描述数据在哪里静止存放,比如“D1 学生信息表”“D2 课程表”。命名是这门课的“送分点”和“送命点”。加工的名词必须是动宾短语,比如“统计成绩”“查询库存”;数据流和数据存储必须是名词短语,比如“借书请求”“订单信息”,不能出现“验证是否合法”这种带流程感的句子。我在真题里经常见有人把加工写成“图书查询”,这就是把加工写成名词了,标准答案通常要求动宾结构。养成习惯:看到加工就确认它是不是一个动作,不是的话立即改。另一个容易混淆的是数据流和数据存储。数据流是动态的数据传输,数据存储是静态的数据存放。如果一条数据流直接连接两个加工,没有任何存储或外部实体介入,这通常就是错误的——加工之间不能直接传递数据,数据必须经过外部实体或数据存储中转。这个规则考试里反复出,刷题时碰到一次记住一次。2.2 分层拆解:父子平衡是怎么检查的DFD的分层设计,核心是“逐层分解,保持平衡”。考试和真实项目中一般画到三层:顶层图:只有一个加工,代表整个系统,和所有外部实体相连,标出输入输出数据流。0层图:把顶层图的加工拆成几个主要子加工,仍然覆盖全部外部实体的输入输出。1层图(可选):把0层图中的复杂加工再往下拆一层。这里最重要的检查规则就是“父图子图平衡”。父图中的某个加工被分解为子图后,子图必须保持和父图相同的外部输入输出数据流——也就是说,子图的边界上出现的数据流,必须能一一对应到父图中该加工的输入输出数据流。不能多,也不能少。举个简单例子。顶层图里“图书借阅系统”从外部实体“读者”接收“借阅请求”,向外输出“借阅结果”。0层图里把加工拆成“P1 验证读者身份”“P2 办理借阅登记”“P3 更新库存信息”三个子加工,那读者和系统之间的数据流仍然是“借阅请求”和“借阅结果”,如果0层图里把“借阅请求”漏了,或者多加了一条“预约请求”,就是破坏了平衡。实际绘制时,我习惯按三步走:把题目文字里所有“谁发起了什么信息”“谁接收了什么信息”找出来,确定外部实体。找“存放数据的地方”,比如“学生的基本信息可以存到学生表”,确定数据存储。把业务过程按先后顺序拆成加工,用数据流把它们串起来。画完之后一定要从头到尾检查一遍每个加工:有输入吗?有输出吗?每个数据存储有人写吗?有人读吗?如果某个数据存储只进不出,说明系统一直存数据但从不使用,这是分析遗漏。2.3 三个典型失分场景与避坑方法第一个典型问题是“加工黑洞”。有些考生画了一个加工,输入数据流有了,但没有输出数据流。这在语义上意味着数据进去后消失了,软件工程里叫“黑洞”,考试里直接扣分。反过来,只有输出没有输入叫“奇迹”,也不合格。每个加工至少要有一条输入和一条输出,这是自查的最快方法。第二个问题是对外部实体边界判断错误。比如一个“网上选课系统”,考生把“课程信息管理系统”也画成外部实体,其实课程信息如果由本系统维护,它就是系统内部的加工或数据存储,不是一个独立于系统之外的角色。判据很简单:这个对象会不会与系统交互数据?它是不是系统之外的用户、部门或第三方系统?不满足就不是外部实体。第三个问题在数据字典部分。DFD有时会配合数据字典一起考,让你补充数据项的结构。比如数据流“学生选课记录”由“学号+课程号+选课日期+成绩”组成。这类题没什么技术含量,但容易因为漏字段丢分。做的时候把题干的表格内容和正文逐字逐句对应,题目明说“包括以下信息”时,所有信息都要出现在数据字典里。比起后面要讲的数据库设计,DFD其实是最容易通过练习形成肌肉记忆的部分。建议找四五道真题,每道做完后不看答案,先自己检查“平衡”“黑洞”“奇迹”“加工命名”四点,再对照答案。练过一轮之后,这15分基本就是送的。3. 数据库概念设计:E-R图建模的关键判断3.1 实体、属性与联系的判别标准数据库设计题从概念模型开始,最常考的就是E-R图。你需要根据业务描述,确定有哪些实体、哪些属性、哪些联系、联系的类型是什么。实体是客观存在、可以相互区分的对象,比如学生、教师、课程、部门、仓库。属性是实体某方面的特征,比如学生的学号、姓名、所属院系。联系是实体之间的业务关联,比如“学生选课”“教师授课”“部门包含员工”。难点通常不在概念本身,而在“度”的把握。题目里描述了一个业务概念,到底该建模成实体、属性还是联系?我总结出三个实战判据:一个概念有没有独立的存在价值和自己的属性。比如“订单”,它有订单号、下单时间、总金额,应该建模成实体;而“订单状态”只是订单的一个特征,建模成属性。“属性”是否能被多个对象共用。如果同一个值要被多个实体引用,通常应该单独拆出来作为实体。比如“职称”,如果只是标注教师的职称名称,可以是属性;但如果你还要维护职称对应的课时费标准,而多个教师共享同一职称,那职称更适合做成实体。业务上是否需要对两个或多个实体之间的关系进行额外记录。如果是,建模成联系,并且给联系加属性。比如“选课”这个联系本身要记录“成绩”,那就不只是简单联系,而是带属性的联系。我一直提醒考生:不要用“看起来像”来判断,要用“我要不要在这个概念上继续附加属性”来判断。能附加属性,优先考虑实体或联系;不能附加属性、只是描述性信息,就做属性。3.2 联系类型与参与约束的建模细节联系分三种类型:1:1联系:一个实体A实例最多对应一个实体B实例,反之亦然,比如一个系只有一个主任,一个主任只管理一个系。1:n联系:一个A实例对应多个B实例,一个B实例只对应一个A实例,比如一个部门有多个员工,一个员工属于一个部门。m:n联系:一个A实例对应多个B实例,一个B实例也对应多个A实例,比如一个学生选多门课,一门课被多个学生选。判断联系类型的核心是读题时做“双向判断”。先站在A侧看一个A对应多少个B,再站在B侧看一个B对应多少个A。两侧都问一遍,就不会把方向搞反。这里最容易出错的是1:1和1:n的区分。比如“每个班级配一个辅导员,每位辅导员负责一个班级”,看起来像是1:1,但如果题目说“辅导员可以临时带多个班级”,那就变成1:n了。一切以题干约束为准,不要自己脑补业务的“通常情况”。参与约束也是E-R图的一部分。如果一个实体在联系中是“必须参与”,建模时用双线连接,表示全参与;如果是“可选参与”,用单线连接,表示部分参与。这个细节在概念模型题里偶尔会出现,比如“每个学生必须选至少一门课”和“存在未选课的学生”,对应到图上就是完全不同的画法。更关键的是,它影响后面逻辑设计时的空值约束——全参与方的外键要设置为非空。3.3 弱实体、派生属性与多值属性的处理一个实体如果没有自己的主键,必须依赖另一个实体才能存在,这种实体叫弱实体。典型的例子是“家属”:家属没有独立身份证或业务编号,必须通过“员工”的编号来标识,一个家属是“哪个员工的家属”决定了它存在的意义。考试里对弱实体的考查方式,通常是让你补充E-R图,或判断关系模式的主键构成。弱实体在E-R图中用双矩形框、双菱形联系表示,转关系模式时,需要把依赖实体的主键作为外键并入,弱实体的标识通常由“依赖实体主键+弱实体自身的部分键”组合而成。比如“(员工号, 家属序号)”是这个家属实体的主键。属性方面有两个特殊标记要记住:多值属性用双椭圆,例如“课程”的“先修课程”可以有多门;派生属性用虚线椭圆,例如“年龄”可以由“出生日期”计算出来。逻辑设计时,多值属性通常要单独拆成一张表,派生属性一般可以不存储在数据库中。这些细节不一定每年都考,但考到就是靠记忆拿分,不能丢。关于E-R图我还想多说一句:画图时务必用铅笔和尺子,实体、属性、联系之间不要交叉连线,能走直线就走直线,标识完整。真题阅卷经常有“改卷看不清不给分”的争议,平时就要养成制图习惯,宁可构图慢一点,也不要让阅卷老师看不清你的菱形框里写的到底是联系还是属性。4. 逻辑结构设计:E-R图到关系模式的转换规则4.1 三类联系的固定转换套路E-R图转换为关系模式,是整个数据库设计题分值最集中的地方。掌握了规则,得分非常稳定。实体单独转成一张表,属性就是表的列,实体的主键就是表的主键。比如实体“学生”有学号、姓名、系别,转换后就是“学生(学号, 姓名, 系别)”,学号加下划线作主键。联系按类型分别处理:1:1联系:将一端的实体的主键放入另一端实体作为外键。比如“系”和“系主任”是1:1联系,通常把“系主任编号”加到系表的列里,或者反过来,并把联系上的属性也一并放到合并后的表中。1:n联系:把“1”端实体的主键放入“n”端实体作为外键。比如部门(1) : 员工(n),员工表里加一列“部门编号”,外键指向部门表。联系自身的属性,比如“入职时间”,也可以放到n端表中。m:n联系:单独生成一张新表,表中至少包含两个实体的主键,作为联合主键;联系自身的属性也加进新表。比如“学生选课”m:n,生成“选课(学号, 课程号, 成绩)”,主键是(学号, 课程号),学号和课程号分别外键引用学生表、课程表。在这里有个特别常见的丢分点:m:n联系的联合主键里,两个外键能不能单独作为主键的一部分?答案是它们共同组成主键,但单个外键也允许重复值,因为一个学生可以选多门课,学号在选课表里会出现多次。有些同学会下意识把“选课表”的主键设成一个自增ID,这在工程上是合理的,但考试题如果让你根据E-R图转换关系模式,标准答案通常就是联合主键。考试先按套路写,工程实现可以另说。还有一类情况:联系本身有多个属性,比如“选课”联系除了成绩,还有“选课时间”“考核方式”。属性处理后放到对应的n端表或单独的联系表中,不要遗漏。4.2 求候选键:闭包计算的基本功数据库设计题里很大一部分是给你一组函数依赖,让你判断候选键、主键或范式等级。做这类题,前提是会算属性集的闭包。闭包的计算方法非常机械:给定关系模式R(U),U是全体属性集,F是函数依赖集合。属性集X的闭包X+,就是从X出发,不断使用F中函数依赖推导出来的属性集合。算法口诀是:初始化X+为X;循环扫描F中的所有函数依赖X→Y,只要X的所有属性都在当前的X+里,就把Y并入X+;重复扫描,直到X+不再变大为止。举个例子。R(A, B, C, D),F = {B→D, D→C}。我们要求候选键。先求单属性闭包:A+ = {A},不包含B、C、D,不是候选键。B+ = {B, D, C},缺失A,不是候选键。C+ = {C},不是。D+ = {D, C},不是。再求组合属性。AB+:从{A, B}出发,B→D得到D,D→C得到C,结果是{A, B, D, C}=ABCD,覆盖全部属性。所以AB是候选键。这是考试里最友好的情形——单属性闭包都不够,两个属性合并后正好覆盖全集。但有些题目候选键不止一个,比如R(A,B,C,D),F={AB→C, C→D, D→A},你要先求闭包再验证冗余。判候选键的标准只有一个:闭包等于全集,且去掉其中任意一个属性,闭包都不等于全集。这里还有一个实用技巧:一个属性如果从来没出现在任何函数依赖的右侧,那么它一定属于候选键。比如上面的例子,A不出现在右侧,但A+≠全集,所以候选键必然包含A。先从这类“必选属性”入手,通常能大大减少试探次数。4.3 范式判定与规范化实战范式判定是数据库设计题中区分度较高的部分。很多考生死记硬背定义却不知道怎么用,本质上还是没把“函数依赖”和“主键”的关系打通。四个范式只需要记住核心判断标准:1NF:属性都是原子的,不可再分。2NF:消除“非主属性对候选键的部分函数依赖”。3NF:消除“非主属性对候选键的传递函数依赖”。BCNF:消除“主属性对候选键的部分函数依赖”,等价于每个函数依赖X→Y中,X都包含候选键。判定一个关系达到第几范式,操作步骤是:求候选键。确定所有主属性(属于某个候选键的属性就是主属性)。看是否存在“候选键的一部分就能决定某个非主属性”,存在则不满足2NF。看是否存在“非主属性决定另一个非主属性”,存在则不满足3NF。看是否存在“某个非主属性或非候选键决定主属性”,例如X→主属性而X不包含候选键,则不满足BCNF。举个例子,经典的“选课-教师”场景。关系R(学号, 课程号, 成绩, 教师姓名, 教师职称),函数依赖:(学号, 课程号) → 成绩课程号 → 教师姓名教师姓名 → 教师职称候选键是(学号, 课程号)。主属性是学号、课程号,非主属性是成绩、教师姓名、教师职称。因为教师姓名由课程号决定,而课程号只是候选键的一部分,所以存在非主属性对候选键的部分函数依赖,R不满足2NF。要规范到3NF,分解步骤:R1(学号, 课程号, 成绩),主键(学号, 课程号)。移除部分依赖涉及的相关属性后,剩余(课程号, 教师姓名, 教师职称)。这里候选键是课程号,但教师姓名→教师职称,这是非主属性之间的传递依赖,所以要继续分解:R2(课程号, 教师姓名),主键课程号。R3(教师姓名, 教师职称),主键教师姓名。最后得到三个关系模式,都满足3NF。整个过程就是“发现部分依赖就拆,发现传递依赖就拆”,拆到每个表里都只有一个“老大”属性集能决定所有其他列,就是3NF了。我在刷题时发现一个普遍问题:很多同学卡在判断“函数依赖的传递性上”。要记住,传递依赖不一定需要三个属性链条都在同一张原表里出现,而是看“非主属性”是否通过另一个“非主属性”被主键间接决定。一旦发现“非主属性A→非主属性B”,立刻就要拆表。还有一点要注意,考试有时会问“最高范式是多少”,这个判断要按达到的最高级别报。比如某个模式满足1NF和2NF但不满足3NF,最高就是2NF。题目如果限定你只能保留一个答案,不要画蛇添足说它也可以“通过分解达到3NF”,那是另一问的答案。5. 物理设计与并发控制:从概念到落地5.1 索引设计的常见考题思路数据库设计题不只是画E-R图和关系模式,有时会在SQL部分问你“为某个列建立索引的目的是什么”或“给出的索引能否提高某条查询的性能”。这类题不需要你写真正执行计划,但要有基本判断。建立索引的核心逻辑很简单:查询中频繁出现在WHERE条件、JOIN连接、ORDER BY排序里的列,适合建索引;经常被修改的列,建索引要慎重,因为每次插入、修改、删除都要同步维护索引结构,代价不低;区分度很低的列,比如“性别”“状态”这种只有两三个取值,索引性价比极差。外键列几乎总是要建索引的。因为外键关联操作(比如删除父表记录时检查子表、连接查询)需要频繁在子表外键列上做等值查找,没有索引就是全表扫描。真题如果给你两张关系模式并问“连接查询慢,应该给哪些列建索引”,答案大概率是“子表的外键列”。联合索引的最左前缀原则偶尔也会考。比如索引(X, Y)能加速X=、X=? AND Y=?这类查询,但不能加速只带有Y=?的查询。可以把联合索引理解成一本先按姓氏排列、再按名字排列的电话簿:知道姓氏才能快速缩小范围,只给名字是没法直接利用索引顺序的。这个类比我讲过很多次,考场上一想到电话簿,基本就不会选错。5.2 反规范化:什么时候可以主动冗余反规范化和规范化是反向操作。规范化追求消除冗余和更新异常,反规范化则是有意引入一些冗余,以换取查询性能。常见反规范化手段:增加冗余列:把别的表中的某个字段复制一份到本表,减少连接查询。比如订单表里冗余一个“收货人姓名”,查订单时就不用每次join用户表。增加派生列:把可计算的统计结果存下来,比如订单表里加“订单总金额”,每次插入明细时同步更新。水平拆分:把一张大表按某种维度拆成多张结构相同的表,比如按月拆订单表。垂直拆分:把使用频率差别很大的列拆到不同表,比如经常读主字段、很少读附件内容的大字段。真题里考反规范化,通常是给一个“查询很慢”的业务场景,问你怎么优化。此时你心里要有一根弦:不是所有慢查询都要反规范化;反规范化解决的痛点是“多表连接开销太大”或“聚合计算太频繁”,而付出的代价则是“更新冗余数据可能不一致”。回答时一定要把“为什么冗余这个列”和“怎么保证一致性”两方面都带上,分数会更稳。5.3 事务并发问题与封锁协议数据库物理设计之外,数据库设计题偶尔会把事务并发控制拖进来一起考,特别是封锁协议这种概念辨析题。事务的ACID特性是基础,不再展开。并发操作可能带来的三个典型问题:脏读:事务A读到事务B未提交的数据,B回滚后A读到的数据就是无效的。不可重复读:事务A两次读取同一数据,期间事务B修改并提交,A两次结果不一致。幻读:事务A按条件查询得到一批记录,期间事务B插入了一条满足条件的新记录并提交,A再次查询时多出“幻影”记录。封锁协议是和这些问题对应的:一级封锁协议:修改数据前加X锁(排他锁),直到事务结束才释放。能防止丢失更新,但不能避免脏读。二级封锁协议:在一级基础上,读取前加S锁(共享锁),读完立即释放。可以防止脏读,但不能防止不可重复读。三级封锁协议:在一级基础上,读取前加S锁,事务结束后才释放。可以防止不可重复读,也是最常用的标准方案。两段锁协议:事务中所有加锁操作都在所有解锁操作之前。满足两段锁的调度是可串行化的,能保证并发调度的正确性。X锁和S锁的相容性也要会判断:S锁与S锁相容,S锁与X锁互斥,X锁与X锁互斥。也就是“共享读可以并行,写必须独占”。真题考这个模块时,要么给一段并发场景让你判断会出现什么问题,要么问你“解决某个问题应该用哪个封锁协议”。做题时先把三个问题记清楚,再把每个协议对应的防护能力记住,基本不会错。死锁相关的考得少,但要知道死锁的四个必要条件不需要全部落实到题目里。6. 典型案例复盘与常见问题速查6.1 一个选课系统的完整数据库设计走查下面我用一个虚构的“高校选课系统”场景,把前面讲的流程完整过一遍,你会发现考题就是这些环节的组合。题目背景:系统需要记录学生信息、教师信息、课程信息。学生有学号、姓名、系别;教师有工号、姓名、职称;课程有课程号、课程名、学分。每个学生可以选修多门课程,每门课程可以被多个学生选,选课要记录成绩。每门课程由一名教师负责,但一名教师可以负责多门课程。第一步,概念模型设计。实体包括学生、教师、课程。学生和课程之间存在m:n联系“选课”,联系属性是“成绩”;教师和课程之间存在1:n联系“授课”。第二步,转换关系模式。实体直接转表:学生(学号, 姓名, 系别),主键学号。教师(工号, 姓名, 职称),主键工号。课程(课程号, 课程名, 学分, 工号),主键课程号,外键工号引用教师表。选课作为m:n联系单独成表:选课(学号, 课程号, 成绩),联合主键(学号, 课程号),学号、课程号分别外键引用学生表、课程表。第三步,范式分析。假设你在这个基础上想引入“教师职称对应的课时费标准”,把职称收费标准加进教师表,没问题。但如果你在课程表中加上“教师姓名”或“教师职称”,而这两个属性又由工号决定,就会出现传递依赖或冗余。考题经常就是让你发现这处冗余并分解,手法和4.3节完全一致。第四步,SQL补充。考试会让你写create table、加外键、写查询。选课表建表SQL可以写成:CREATE TABLE 选课 ( 学号 VARCHAR(20) NOT NULL, 课程号 VARCHAR(20) NOT NULL, 成绩 DECIMAL(5,2), PRIMARY KEY (学号, 课程号), FOREIGN KEY (学号) REFERENCES 学生(学号), FOREIGN KEY (课程号) REFERENCES 课程(课程号) );查询每个学生的选课均分:SELECT 学号, AVG(成绩) AS 平均成绩 FROM 选课 GROUP BY 学号;这类题没有太多技巧,就是把关系模式翻译成SQL语句。平时多练几道真题,注意字段名和表名保持一致,不要自己改名,基本不会错。6.2 备考实操建议与易错点速查最后留一张自己在备考期间反复对照的易错点表格,希望对大家有帮助。常考环节常见错误正确思路DFD加工命名写成名词,如“图书查询”必须为动宾短语,如“查询图书”DFD数据流检查只输入不输出,或只输出不输入每个加工至少要有一条输入和一条输出父图子图平衡子图增加或遗漏数据流子图边界的数据流必须与父图该加工的输入输出完全一致E-R图联系类型将m:n误判为1:n双向判断:一侧对应多个、另一侧也对应多个,就是m:n弱实体主键单独给弱实体设一个自增主键通常由依赖实体主键+弱实体自身标识共同组成转换规则m:n联系处理成一条外键必须单独建表,联合主键候选键求法凭感觉猜主键用闭包算法机械计算3NF分解只消除部分依赖,不消除传递依赖只要存在非主属性决定非主属性,继续拆SQL外键表名别名与题干不一致保持和关系模式中的名称完全一致关于复习顺序,我是建议优先把DFD和E-R转换练熟,因为它们套路固定、见效最快。接着练候选键闭包和范式判定,这两块占数据库设计的后半壁江山。最后用3至5套真题做整体模拟,把SQL和并发选择放进去一起做。我见过很多备考者,最大的问题不是不懂知识点,而是练习量不够。数据流图的“平衡检查”、关系模式的“联合主键”、范式的“传递依赖”,这几个坑一旦踩过一次,基本就不会再错。怕的是只看不练,到了考场上发现自己知道规则却不会在题目里定位错误点。备考软件设计师,如果只让我选一个核心动作,那就是:把近五年的下午题真题逐题做透,每道题都按采分点给自己打分,错了就去翻知识点而不是背答案。系统设计和数据库设计这两块尤其如此,因为它们不是“背下来”的科目,而是“练出来”的能力。
下午题第一道是结构化分析与设计,考的是数据流图,第二道就是数据库设计,这两道加起来差不多30分,占了下午场整整40%的分值。很多人上午选择题背得滚瓜烂熟,到了下午题却在这里反复丢分。说实话,这两道题是所有下午题里最容易拿分、也最容易练出稳定正确率的模块,关键是搞清楚考试到底在考什么、阅卷时在找什么。这篇内容就是围绕软件设计师考试中系统设计与数据库设计这两大块,把我在备考和刷题过程中总结的套路、易错点、实用方法完整捋一遍。不管是零基础第一次考,还是二战想冲高分,只要把DFD数据流图、数据库概念设计、ER图转关系模式、范式判定这几块练扎实,下午题基本就稳了一半。1. 下午题的分数结构:先搞清楚考什么1.1 系统设计与数据库设计在考试里的真实分布软件设计师考试的下午题一共六道题,总分75分,合格线45分。题型分布一般是:第1题:结构化分析与设计,主要考数据流图,有时带数据字典,15分第2题:数据库设计,考E-R图、关系模式、范式、SQL语句,15分第3题:UML建模,用例图、类图、顺序图、状态图等,15分第4题:数据结构与算法,15分第5题:程序设计(C语言或Java),15分第6题:系统设计、测试、架构等综合题,15分你会发现,和“系统设计”直接相关的其实是第1、3、6题,而“数据库设计”是独立的第2题。但大家通常说的“系统设计与数据库设计”,核心就是前两道题。这两道题有个共同特点——它们不是纯背诵题,也不是纯编程题,而是“建模题”。你要按照题目给出的上下文,画出或补全模型,并且把模型转成可落地的关系模式或代码。这里先给一个总判断:数据流图侧重视图逻辑和规范检查,数据库设计题侧重完整的数据建模链条,两者考的是“有没有工程设计思维”,而不是“记没记住知识点”。这也是为什么很多程序员去裸考,上午题能过,下午题却折在这两道题上——因为平时写代码的人不太习惯用这种“画图建模、逐条校验”的方式思考问题。1.2 阅卷方式决定了答题策略另一个需要先建立认知的事情:下午题是人工阅卷还是电脑辅助阅卷,答案其实不重要,重要的是阅卷老师手里有一张“采分表”。他一眼扫过去,看你有没有写对几个关键点,比如“外键名称”“主键名称”“关系模式包括哪些列”“某个加工是否缺少输入数据流”。这带来一个非常实际的答题启示:命中的关键词和结构表达,比语句是否优美重要得多。很多考生明明会做,却因为写得“模棱两可”丢了分,比如把关系模式写成“学生(学号, 姓名, 系别)”忘记标下划线主键,或者把数据流图中外部实体的名字写错方向。阅卷时这种细节就是采分点,少了就是少了,不会因为你整体思路对就给你补全。所以我的建议是,平时做真题时一定要严格按“采分点模式”对答案。不要只看“思路差不多”就放过,要列出来:这个加工的名字我写对没有,数据流的方向标对没有,关系模式的主键外键标出来没有,规范化分解后的每个模式是否满足3NF。标准就是标准,模拟阶段苛刻一点,考场上才不会手松。2. 系统设计:DFD数据流图的绘制与检验2.1 数据流图的基本元素与命名铁律数据流图(DFD)是结构化分析的核心产出,用来表达系统“做什么”,不关心“怎么做”。考试里给你一个业务场景,让你补全外部实体、数据存储、加工、数据流,或者指出某个图中的错误。基本元素四个:外部实体:用矩形表示,是数据的来源或去向,比如“学生”“图书管理员”“教务老师”“支付平台”,注意它不属于系统内部。加工:用圆角矩形或带圆边的矩形表示,也叫处理、功能,是对数据执行的某种操作,比如“验证登录信息”“计算考试总分”。数据流:用箭头表示,描述数据的流动方向。箭头方向就是数据实际移动的方向,不是“控制流”。数据存储:用开口矩形或两条平行线表示,描述数据在哪里静止存放,比如“D1 学生信息表”“D2 课程表”。命名是这门课的“送分点”和“送命点”。加工的名词必须是动宾短语,比如“统计成绩”“查询库存”;数据流和数据存储必须是名词短语,比如“借书请求”“订单信息”,不能出现“验证是否合法”这种带流程感的句子。我在真题里经常见有人把加工写成“图书查询”,这就是把加工写成名词了,标准答案通常要求动宾结构。养成习惯:看到加工就确认它是不是一个动作,不是的话立即改。另一个容易混淆的是数据流和数据存储。数据流是动态的数据传输,数据存储是静态的数据存放。如果一条数据流直接连接两个加工,没有任何存储或外部实体介入,这通常就是错误的——加工之间不能直接传递数据,数据必须经过外部实体或数据存储中转。这个规则考试里反复出,刷题时碰到一次记住一次。2.2 分层拆解:父子平衡是怎么检查的DFD的分层设计,核心是“逐层分解,保持平衡”。考试和真实项目中一般画到三层:顶层图:只有一个加工,代表整个系统,和所有外部实体相连,标出输入输出数据流。0层图:把顶层图的加工拆成几个主要子加工,仍然覆盖全部外部实体的输入输出。1层图(可选):把0层图中的复杂加工再往下拆一层。这里最重要的检查规则就是“父图子图平衡”。父图中的某个加工被分解为子图后,子图必须保持和父图相同的外部输入输出数据流——也就是说,子图的边界上出现的数据流,必须能一一对应到父图中该加工的输入输出数据流。不能多,也不能少。举个简单例子。顶层图里“图书借阅系统”从外部实体“读者”接收“借阅请求”,向外输出“借阅结果”。0层图里把加工拆成“P1 验证读者身份”“P2 办理借阅登记”“P3 更新库存信息”三个子加工,那读者和系统之间的数据流仍然是“借阅请求”和“借阅结果”,如果0层图里把“借阅请求”漏了,或者多加了一条“预约请求”,就是破坏了平衡。实际绘制时,我习惯按三步走:把题目文字里所有“谁发起了什么信息”“谁接收了什么信息”找出来,确定外部实体。找“存放数据的地方”,比如“学生的基本信息可以存到学生表”,确定数据存储。把业务过程按先后顺序拆成加工,用数据流把它们串起来。画完之后一定要从头到尾检查一遍每个加工:有输入吗?有输出吗?每个数据存储有人写吗?有人读吗?如果某个数据存储只进不出,说明系统一直存数据但从不使用,这是分析遗漏。2.3 三个典型失分场景与避坑方法第一个典型问题是“加工黑洞”。有些考生画了一个加工,输入数据流有了,但没有输出数据流。这在语义上意味着数据进去后消失了,软件工程里叫“黑洞”,考试里直接扣分。反过来,只有输出没有输入叫“奇迹”,也不合格。每个加工至少要有一条输入和一条输出,这是自查的最快方法。第二个问题是对外部实体边界判断错误。比如一个“网上选课系统”,考生把“课程信息管理系统”也画成外部实体,其实课程信息如果由本系统维护,它就是系统内部的加工或数据存储,不是一个独立于系统之外的角色。判据很简单:这个对象会不会与系统交互数据?它是不是系统之外的用户、部门或第三方系统?不满足就不是外部实体。第三个问题在数据字典部分。DFD有时会配合数据字典一起考,让你补充数据项的结构。比如数据流“学生选课记录”由“学号+课程号+选课日期+成绩”组成。这类题没什么技术含量,但容易因为漏字段丢分。做的时候把题干的表格内容和正文逐字逐句对应,题目明说“包括以下信息”时,所有信息都要出现在数据字典里。比起后面要讲的数据库设计,DFD其实是最容易通过练习形成肌肉记忆的部分。建议找四五道真题,每道做完后不看答案,先自己检查“平衡”“黑洞”“奇迹”“加工命名”四点,再对照答案。练过一轮之后,这15分基本就是送的。3. 数据库概念设计:E-R图建模的关键判断3.1 实体、属性与联系的判别标准数据库设计题从概念模型开始,最常考的就是E-R图。你需要根据业务描述,确定有哪些实体、哪些属性、哪些联系、联系的类型是什么。实体是客观存在、可以相互区分的对象,比如学生、教师、课程、部门、仓库。属性是实体某方面的特征,比如学生的学号、姓名、所属院系。联系是实体之间的业务关联,比如“学生选课”“教师授课”“部门包含员工”。难点通常不在概念本身,而在“度”的把握。题目里描述了一个业务概念,到底该建模成实体、属性还是联系?我总结出三个实战判据:一个概念有没有独立的存在价值和自己的属性。比如“订单”,它有订单号、下单时间、总金额,应该建模成实体;而“订单状态”只是订单的一个特征,建模成属性。“属性”是否能被多个对象共用。如果同一个值要被多个实体引用,通常应该单独拆出来作为实体。比如“职称”,如果只是标注教师的职称名称,可以是属性;但如果你还要维护职称对应的课时费标准,而多个教师共享同一职称,那职称更适合做成实体。业务上是否需要对两个或多个实体之间的关系进行额外记录。如果是,建模成联系,并且给联系加属性。比如“选课”这个联系本身要记录“成绩”,那就不只是简单联系,而是带属性的联系。我一直提醒考生:不要用“看起来像”来判断,要用“我要不要在这个概念上继续附加属性”来判断。能附加属性,优先考虑实体或联系;不能附加属性、只是描述性信息,就做属性。3.2 联系类型与参与约束的建模细节联系分三种类型:1:1联系:一个实体A实例最多对应一个实体B实例,反之亦然,比如一个系只有一个主任,一个主任只管理一个系。1:n联系:一个A实例对应多个B实例,一个B实例只对应一个A实例,比如一个部门有多个员工,一个员工属于一个部门。m:n联系:一个A实例对应多个B实例,一个B实例也对应多个A实例,比如一个学生选多门课,一门课被多个学生选。判断联系类型的核心是读题时做“双向判断”。先站在A侧看一个A对应多少个B,再站在B侧看一个B对应多少个A。两侧都问一遍,就不会把方向搞反。这里最容易出错的是1:1和1:n的区分。比如“每个班级配一个辅导员,每位辅导员负责一个班级”,看起来像是1:1,但如果题目说“辅导员可以临时带多个班级”,那就变成1:n了。一切以题干约束为准,不要自己脑补业务的“通常情况”。参与约束也是E-R图的一部分。如果一个实体在联系中是“必须参与”,建模时用双线连接,表示全参与;如果是“可选参与”,用单线连接,表示部分参与。这个细节在概念模型题里偶尔会出现,比如“每个学生必须选至少一门课”和“存在未选课的学生”,对应到图上就是完全不同的画法。更关键的是,它影响后面逻辑设计时的空值约束——全参与方的外键要设置为非空。3.3 弱实体、派生属性与多值属性的处理一个实体如果没有自己的主键,必须依赖另一个实体才能存在,这种实体叫弱实体。典型的例子是“家属”:家属没有独立身份证或业务编号,必须通过“员工”的编号来标识,一个家属是“哪个员工的家属”决定了它存在的意义。考试里对弱实体的考查方式,通常是让你补充E-R图,或判断关系模式的主键构成。弱实体在E-R图中用双矩形框、双菱形联系表示,转关系模式时,需要把依赖实体的主键作为外键并入,弱实体的标识通常由“依赖实体主键+弱实体自身的部分键”组合而成。比如“(员工号, 家属序号)”是这个家属实体的主键。属性方面有两个特殊标记要记住:多值属性用双椭圆,例如“课程”的“先修课程”可以有多门;派生属性用虚线椭圆,例如“年龄”可以由“出生日期”计算出来。逻辑设计时,多值属性通常要单独拆成一张表,派生属性一般可以不存储在数据库中。这些细节不一定每年都考,但考到就是靠记忆拿分,不能丢。关于E-R图我还想多说一句:画图时务必用铅笔和尺子,实体、属性、联系之间不要交叉连线,能走直线就走直线,标识完整。真题阅卷经常有“改卷看不清不给分”的争议,平时就要养成制图习惯,宁可构图慢一点,也不要让阅卷老师看不清你的菱形框里写的到底是联系还是属性。4. 逻辑结构设计:E-R图到关系模式的转换规则4.1 三类联系的固定转换套路E-R图转换为关系模式,是整个数据库设计题分值最集中的地方。掌握了规则,得分非常稳定。实体单独转成一张表,属性就是表的列,实体的主键就是表的主键。比如实体“学生”有学号、姓名、系别,转换后就是“学生(学号, 姓名, 系别)”,学号加下划线作主键。联系按类型分别处理:1:1联系:将一端的实体的主键放入另一端实体作为外键。比如“系”和“系主任”是1:1联系,通常把“系主任编号”加到系表的列里,或者反过来,并把联系上的属性也一并放到合并后的表中。1:n联系:把“1”端实体的主键放入“n”端实体作为外键。比如部门(1) : 员工(n),员工表里加一列“部门编号”,外键指向部门表。联系自身的属性,比如“入职时间”,也可以放到n端表中。m:n联系:单独生成一张新表,表中至少包含两个实体的主键,作为联合主键;联系自身的属性也加进新表。比如“学生选课”m:n,生成“选课(学号, 课程号, 成绩)”,主键是(学号, 课程号),学号和课程号分别外键引用学生表、课程表。在这里有个特别常见的丢分点:m:n联系的联合主键里,两个外键能不能单独作为主键的一部分?答案是它们共同组成主键,但单个外键也允许重复值,因为一个学生可以选多门课,学号在选课表里会出现多次。有些同学会下意识把“选课表”的主键设成一个自增ID,这在工程上是合理的,但考试题如果让你根据E-R图转换关系模式,标准答案通常就是联合主键。考试先按套路写,工程实现可以另说。还有一类情况:联系本身有多个属性,比如“选课”联系除了成绩,还有“选课时间”“考核方式”。属性处理后放到对应的n端表或单独的联系表中,不要遗漏。4.2 求候选键:闭包计算的基本功数据库设计题里很大一部分是给你一组函数依赖,让你判断候选键、主键或范式等级。做这类题,前提是会算属性集的闭包。闭包的计算方法非常机械:给定关系模式R(U),U是全体属性集,F是函数依赖集合。属性集X的闭包X+,就是从X出发,不断使用F中函数依赖推导出来的属性集合。算法口诀是:初始化X+为X;循环扫描F中的所有函数依赖X→Y,只要X的所有属性都在当前的X+里,就把Y并入X+;重复扫描,直到X+不再变大为止。举个例子。R(A, B, C, D),F = {B→D, D→C}。我们要求候选键。先求单属性闭包:A+ = {A},不包含B、C、D,不是候选键。B+ = {B, D, C},缺失A,不是候选键。C+ = {C},不是。D+ = {D, C},不是。再求组合属性。AB+:从{A, B}出发,B→D得到D,D→C得到C,结果是{A, B, D, C}=ABCD,覆盖全部属性。所以AB是候选键。这是考试里最友好的情形——单属性闭包都不够,两个属性合并后正好覆盖全集。但有些题目候选键不止一个,比如R(A,B,C,D),F={AB→C, C→D, D→A},你要先求闭包再验证冗余。判候选键的标准只有一个:闭包等于全集,且去掉其中任意一个属性,闭包都不等于全集。这里还有一个实用技巧:一个属性如果从来没出现在任何函数依赖的右侧,那么它一定属于候选键。比如上面的例子,A不出现在右侧,但A+≠全集,所以候选键必然包含A。先从这类“必选属性”入手,通常能大大减少试探次数。4.3 范式判定与规范化实战范式判定是数据库设计题中区分度较高的部分。很多考生死记硬背定义却不知道怎么用,本质上还是没把“函数依赖”和“主键”的关系打通。四个范式只需要记住核心判断标准:1NF:属性都是原子的,不可再分。2NF:消除“非主属性对候选键的部分函数依赖”。3NF:消除“非主属性对候选键的传递函数依赖”。BCNF:消除“主属性对候选键的部分函数依赖”,等价于每个函数依赖X→Y中,X都包含候选键。判定一个关系达到第几范式,操作步骤是:求候选键。确定所有主属性(属于某个候选键的属性就是主属性)。看是否存在“候选键的一部分就能决定某个非主属性”,存在则不满足2NF。看是否存在“非主属性决定另一个非主属性”,存在则不满足3NF。看是否存在“某个非主属性或非候选键决定主属性”,例如X→主属性而X不包含候选键,则不满足BCNF。举个例子,经典的“选课-教师”场景。关系R(学号, 课程号, 成绩, 教师姓名, 教师职称),函数依赖:(学号, 课程号) → 成绩课程号 → 教师姓名教师姓名 → 教师职称候选键是(学号, 课程号)。主属性是学号、课程号,非主属性是成绩、教师姓名、教师职称。因为教师姓名由课程号决定,而课程号只是候选键的一部分,所以存在非主属性对候选键的部分函数依赖,R不满足2NF。要规范到3NF,分解步骤:R1(学号, 课程号, 成绩),主键(学号, 课程号)。移除部分依赖涉及的相关属性后,剩余(课程号, 教师姓名, 教师职称)。这里候选键是课程号,但教师姓名→教师职称,这是非主属性之间的传递依赖,所以要继续分解:R2(课程号, 教师姓名),主键课程号。R3(教师姓名, 教师职称),主键教师姓名。最后得到三个关系模式,都满足3NF。整个过程就是“发现部分依赖就拆,发现传递依赖就拆”,拆到每个表里都只有一个“老大”属性集能决定所有其他列,就是3NF了。我在刷题时发现一个普遍问题:很多同学卡在判断“函数依赖的传递性上”。要记住,传递依赖不一定需要三个属性链条都在同一张原表里出现,而是看“非主属性”是否通过另一个“非主属性”被主键间接决定。一旦发现“非主属性A→非主属性B”,立刻就要拆表。还有一点要注意,考试有时会问“最高范式是多少”,这个判断要按达到的最高级别报。比如某个模式满足1NF和2NF但不满足3NF,最高就是2NF。题目如果限定你只能保留一个答案,不要画蛇添足说它也可以“通过分解达到3NF”,那是另一问的答案。5. 物理设计与并发控制:从概念到落地5.1 索引设计的常见考题思路数据库设计题不只是画E-R图和关系模式,有时会在SQL部分问你“为某个列建立索引的目的是什么”或“给出的索引能否提高某条查询的性能”。这类题不需要你写真正执行计划,但要有基本判断。建立索引的核心逻辑很简单:查询中频繁出现在WHERE条件、JOIN连接、ORDER BY排序里的列,适合建索引;经常被修改的列,建索引要慎重,因为每次插入、修改、删除都要同步维护索引结构,代价不低;区分度很低的列,比如“性别”“状态”这种只有两三个取值,索引性价比极差。外键列几乎总是要建索引的。因为外键关联操作(比如删除父表记录时检查子表、连接查询)需要频繁在子表外键列上做等值查找,没有索引就是全表扫描。真题如果给你两张关系模式并问“连接查询慢,应该给哪些列建索引”,答案大概率是“子表的外键列”。联合索引的最左前缀原则偶尔也会考。比如索引(X, Y)能加速X=、X=? AND Y=?这类查询,但不能加速只带有Y=?的查询。可以把联合索引理解成一本先按姓氏排列、再按名字排列的电话簿:知道姓氏才能快速缩小范围,只给名字是没法直接利用索引顺序的。这个类比我讲过很多次,考场上一想到电话簿,基本就不会选错。5.2 反规范化:什么时候可以主动冗余反规范化和规范化是反向操作。规范化追求消除冗余和更新异常,反规范化则是有意引入一些冗余,以换取查询性能。常见反规范化手段:增加冗余列:把别的表中的某个字段复制一份到本表,减少连接查询。比如订单表里冗余一个“收货人姓名”,查订单时就不用每次join用户表。增加派生列:把可计算的统计结果存下来,比如订单表里加“订单总金额”,每次插入明细时同步更新。水平拆分:把一张大表按某种维度拆成多张结构相同的表,比如按月拆订单表。垂直拆分:把使用频率差别很大的列拆到不同表,比如经常读主字段、很少读附件内容的大字段。真题里考反规范化,通常是给一个“查询很慢”的业务场景,问你怎么优化。此时你心里要有一根弦:不是所有慢查询都要反规范化;反规范化解决的痛点是“多表连接开销太大”或“聚合计算太频繁”,而付出的代价则是“更新冗余数据可能不一致”。回答时一定要把“为什么冗余这个列”和“怎么保证一致性”两方面都带上,分数会更稳。5.3 事务并发问题与封锁协议数据库物理设计之外,数据库设计题偶尔会把事务并发控制拖进来一起考,特别是封锁协议这种概念辨析题。事务的ACID特性是基础,不再展开。并发操作可能带来的三个典型问题:脏读:事务A读到事务B未提交的数据,B回滚后A读到的数据就是无效的。不可重复读:事务A两次读取同一数据,期间事务B修改并提交,A两次结果不一致。幻读:事务A按条件查询得到一批记录,期间事务B插入了一条满足条件的新记录并提交,A再次查询时多出“幻影”记录。封锁协议是和这些问题对应的:一级封锁协议:修改数据前加X锁(排他锁),直到事务结束才释放。能防止丢失更新,但不能避免脏读。二级封锁协议:在一级基础上,读取前加S锁(共享锁),读完立即释放。可以防止脏读,但不能防止不可重复读。三级封锁协议:在一级基础上,读取前加S锁,事务结束后才释放。可以防止不可重复读,也是最常用的标准方案。两段锁协议:事务中所有加锁操作都在所有解锁操作之前。满足两段锁的调度是可串行化的,能保证并发调度的正确性。X锁和S锁的相容性也要会判断:S锁与S锁相容,S锁与X锁互斥,X锁与X锁互斥。也就是“共享读可以并行,写必须独占”。真题考这个模块时,要么给一段并发场景让你判断会出现什么问题,要么问你“解决某个问题应该用哪个封锁协议”。做题时先把三个问题记清楚,再把每个协议对应的防护能力记住,基本不会错。死锁相关的考得少,但要知道死锁的四个必要条件不需要全部落实到题目里。6. 典型案例复盘与常见问题速查6.1 一个选课系统的完整数据库设计走查下面我用一个虚构的“高校选课系统”场景,把前面讲的流程完整过一遍,你会发现考题就是这些环节的组合。题目背景:系统需要记录学生信息、教师信息、课程信息。学生有学号、姓名、系别;教师有工号、姓名、职称;课程有课程号、课程名、学分。每个学生可以选修多门课程,每门课程可以被多个学生选,选课要记录成绩。每门课程由一名教师负责,但一名教师可以负责多门课程。第一步,概念模型设计。实体包括学生、教师、课程。学生和课程之间存在m:n联系“选课”,联系属性是“成绩”;教师和课程之间存在1:n联系“授课”。第二步,转换关系模式。实体直接转表:学生(学号, 姓名, 系别),主键学号。教师(工号, 姓名, 职称),主键工号。课程(课程号, 课程名, 学分, 工号),主键课程号,外键工号引用教师表。选课作为m:n联系单独成表:选课(学号, 课程号, 成绩),联合主键(学号, 课程号),学号、课程号分别外键引用学生表、课程表。第三步,范式分析。假设你在这个基础上想引入“教师职称对应的课时费标准”,把职称收费标准加进教师表,没问题。但如果你在课程表中加上“教师姓名”或“教师职称”,而这两个属性又由工号决定,就会出现传递依赖或冗余。考题经常就是让你发现这处冗余并分解,手法和4.3节完全一致。第四步,SQL补充。考试会让你写create table、加外键、写查询。选课表建表SQL可以写成:CREATE TABLE 选课 ( 学号 VARCHAR(20) NOT NULL, 课程号 VARCHAR(20) NOT NULL, 成绩 DECIMAL(5,2), PRIMARY KEY (学号, 课程号), FOREIGN KEY (学号) REFERENCES 学生(学号), FOREIGN KEY (课程号) REFERENCES 课程(课程号) );查询每个学生的选课均分:SELECT 学号, AVG(成绩) AS 平均成绩 FROM 选课 GROUP BY 学号;这类题没有太多技巧,就是把关系模式翻译成SQL语句。平时多练几道真题,注意字段名和表名保持一致,不要自己改名,基本不会错。6.2 备考实操建议与易错点速查最后留一张自己在备考期间反复对照的易错点表格,希望对大家有帮助。常考环节常见错误正确思路DFD加工命名写成名词,如“图书查询”必须为动宾短语,如“查询图书”DFD数据流检查只输入不输出,或只输出不输入每个加工至少要有一条输入和一条输出父图子图平衡子图增加或遗漏数据流子图边界的数据流必须与父图该加工的输入输出完全一致E-R图联系类型将m:n误判为1:n双向判断:一侧对应多个、另一侧也对应多个,就是m:n弱实体主键单独给弱实体设一个自增主键通常由依赖实体主键+弱实体自身标识共同组成转换规则m:n联系处理成一条外键必须单独建表,联合主键候选键求法凭感觉猜主键用闭包算法机械计算3NF分解只消除部分依赖,不消除传递依赖只要存在非主属性决定非主属性,继续拆SQL外键表名别名与题干不一致保持和关系模式中的名称完全一致关于复习顺序,我是建议优先把DFD和E-R转换练熟,因为它们套路固定、见效最快。接着练候选键闭包和范式判定,这两块占数据库设计的后半壁江山。最后用3至5套真题做整体模拟,把SQL和并发选择放进去一起做。我见过很多备考者,最大的问题不是不懂知识点,而是练习量不够。数据流图的“平衡检查”、关系模式的“联合主键”、范式的“传递依赖”,这几个坑一旦踩过一次,基本就不会再错。怕的是只看不练,到了考场上发现自己知道规则却不会在题目里定位错误点。备考软件设计师,如果只让我选一个核心动作,那就是:把近五年的下午题真题逐题做透,每道题都按采分点给自己打分,错了就去翻知识点而不是背答案。系统设计和数据库设计这两块尤其如此,因为它们不是“背下来”的科目,而是“练出来”的能力。