843 / 学习讲义

信息技术 / 09

数据库:把事实存得清楚、查得准确

一次解决一个小问题。从具体例子开始,理解条件,再亲手算一遍。

09 / 数据库:把事实存得清楚、查得准确 · 小节 1

关系、键与关系操作

读完这一节,你会

从现实对象建表,并解释每张表一行代表什么。

大纲要求的教学展开 · 技术讲解 · 本节来源与考点

前置知识:把符号读成一句话 · 符号回看

从一个问题开始

把姓名当图书借阅人的唯一标识,会发生什么?

实体、联系与外键

实体、联系与外键。步骤文字在图下。ReaderCopy
1 / 3

读者和实体册分别有唯一编号。

原创教学示意 · 手动播放,可随时暂停;折叠或离开小节时停止。

把这件事讲清楚

关系可直观看作表,属性是列,元组是行,域是允许的值。候选键是能唯一识别元组的最小属性组;选择一个作主键。外键引用另一表的候选唯一标识,维护引用完整性。实体完整性要求主键唯一且非空。SQL表通常允许重复行,不能把数学集合的去重规则无条件套到SQL。

关系选择筛行,投影选列,连接按相关属性组合行。NULL表示缺失或未知,并不等于0或空串;SQL用IS NULL判断,不用= NULL。约束与权限、业务逻辑共同维护有效数据。

为什么成立 · 关键推导

从“一个人可借多本,一本实体册可先后被多人借”推出借阅记录必须独立成表,保存读者、册号、日期。一行代表一次借阅,不是一个读者。书名对应作品,条码对应实体册,应按业务粒度分开。

入门例题 / 1

Reader(id,name)、Copy(id,title)、Loan(id,reader_id,copy_id,returned)。两位同名“小林”靠id区分,Loan.reader_id外键指向Reader.id,避免借给不存在的人。

典型应用与变式 / 2

要查未归还借阅人的姓名:先从Loan选择returned=0的行,再连接Reader的id,最后投影name。若同一人有两次未还记录,结果可能重复,是否去重取决于问题问“记录”还是“人”。

停一下,自己试一试

先独立作答;卡住时看提示,完成后再对照解析。

概念判断

外键必须在本表唯一吗?

需要一点提示

许多订单能引用同一客户。

查看过程、答案与错因

不必。外键常重复;被引用的键要能唯一确定目标。

计算与执行过程

读者1有借阅10、11,读者2有借阅12,连接后几行?

需要一点提示

每条借阅匹配一个读者。

查看过程、答案与错因

3行。若只问有借阅的读者数,应数不同reader_id,答案2。

条件与错误辨析

删除仍被借阅表引用的读者可随意执行吗?

需要一点提示

如何保持引用完整性?

查看过程、答案与错因

应按预设限制、级联或其他规则处理,不能留下无法解释的悬空引用;历史借阅是否保留要由需求决定。

带走这一句

先确定“一行是什么”,再选择键和连接条件。

09 / 数据库:把事实存得清楚、查得准确 · 小节 2

从查询到分组:读懂SQL

读完这一节,你会

能在纸上执行查询,区分筛行与筛组。

大纲要求的教学展开 · 技术讲解 · 本节来源与考点

前置知识:关系、键与关系操作 · 符号回看

从一个问题开始

想找借了至少2本未还书的人,为什么不能直接WHERE COUNT(*)>=2?

把这件事讲清楚

SQL是声明式查询语言:说明要什么结果,数据库选择执行方式。SELECT选输出列,FROM指定来源,JOIN…ON连接,WHERE先筛行,GROUP BY分组,HAVING筛组,ORDER BY排序。COUNT(*)计行;COUNT(column)忽略该列NULL;SUM、AVG等一般忽略NULL。逻辑理解顺序与书写顺序不同。INSERT新增,UPDATE修改,DELETE删除;写操作缺少WHERE可能影响所有行。事务把多步作为一个整体,成功提交COMMIT,失败回滚ROLLBACK。

为什么成立 · 关键推导

固定数据Loan=(id,reader_id,returned):(10,1,0),(11,1,0),(12,2,1),(13,2,0)。先WHERE returned=0剩10、11、13;按reader_id分组得到1有2、2有1;HAVING COUNT(*)>=2仅保留1。事务的原子性防止借阅记录写入而库存未扣这种部分成功。

入门例题 / 1

SELECT reader_id, COUNT(*) AS n FROM Loan WHERE returned=0 GROUP BY reader_id HAVING COUNT(*)>=2;
结果一行:reader_id=1,n=2。n是输出列别名,不是新增存储字段。

典型应用与变式 / 2

Reader=(1,小林),(2,小周),(3,小陈)。LEFT JOIN Loan可保留无借阅的3。统计每人借阅次数应COUNT(Loan.id),结果1→2,2→2,3→0;COUNT(*)会把3的补NULL行也计1。

停一下,自己试一试

先独立作答;卡住时看提示,完成后再对照解析。

概念判断

WHERE与HAVING可以不加区别互换吗?

需要一点提示

一个作用于行,一个作用于组。

查看过程、答案与错因

不能。聚合后的条件应HAVING;聚合前过滤可改变分组输入。

计算与执行过程

固定数据中COUNT(*)、COUNT(DISTINCT reader_id)各多少?

需要一点提示

完整Loan有四行,两位读者。

查看过程、答案与错因

分别4和2。若先筛未还,则行数3但不同读者仍2。

条件与错误辨析

把用户输入直接拼进SQL字符串安全吗?

需要一点提示

输入可能被解释为语法。

查看过程、答案与错因

不安全。应用应使用参数化查询并配权限;字符串转义不能代替完整的安全设计。

对照完整 C / SQL 示例与语法说明 →

带走这一句

先筛行,再分组,再筛组;输出几行要能手算。

09 / 数据库:把事实存得清楚、查得准确 · 小节 3

函数依赖、规范化与ER设计

读完这一节,你会

发现更新异常,把一张混杂表拆成有约束的关系。

大纲要求的教学展开 · 技术讲解 · 本节来源与考点

前置知识:从查询到分组:读懂SQL · 符号回看

从一个问题开始

每条借阅记录都重复存读者电话,换号码要改多少行?

实体、联系与外键

实体、联系与外键。步骤文字在图下。ReaderCopy
1 / 3

读者和实体册分别有唯一编号。

原创教学示意 · 手动播放,可随时暂停;折叠或离开小节时停止。

把这件事讲清楚

函数依赖X→Y表示相同X必有相同Y,是业务约束,不是一次数据巧合。1NF要求每个属性值在当前模型中不可再分;2NF在1NF上消除非主属性对候选键的部分依赖;3NF消除相应传递依赖(正式判据为每个非平凡依赖X→A,X是超键或A为主属性);BCNF进一步要求所有非平凡依赖的决定因素为超键。主属性指属于某候选键的属性。

规范化减少插入、删除、更新异常,分解必须考虑无损连接与依赖保持,表越多不一定越好。ER图表示实体、属性和联系;1对多常在多侧放外键,多对多通常另建联系表。

为什么成立 · 关键推导

流程:需求与业务规则→概念ER模型→关系模式与键→依赖与分解→约束/索引/权限→验证典型查询。先明确实体粒度,例如“课程”与“某学期某班开课”可能不同,不能只凭名词建表。

入门例题 / 1

表(学生号,课程号,学生名,成绩),键(学生号,课程号),学生号→学生名。学生名只依赖键的一部分,违反2NF。拆Student(学生号,学生名)和Enroll(学生号,课程号,成绩)。共同学生号是Student键,可无损重连。

典型应用与变式 / 2

表(员工号,部门号,部门电话),员工号是键,部门号→部门电话,电话经部门传递依赖员工号。拆Employee与Department,改电话只改一处;仍须外键保证员工引用的部门存在。

停一下,自己试一试

先独立作答;卡住时看提示,完成后再对照解析。

概念判断

当前数据中姓名没有重复,就能声明姓名→学号吗?

需要一点提示

依赖应在所有合法状态成立。

查看过程、答案与错因

不能。还需业务规则保证,未来同名会破坏该依赖;数据观察只是线索。

计算与执行过程

作者与书多对多,给关系表及键。

需要一点提示

联系自身也要记录。

查看过程、答案与错因

Author(author_id,…)、Book(book_id,…)、Authorship(author_id,book_id),联系表以二者组合为键并各设外键;如需署名次序另加属性和约束。

条件与错误辨析

任意把表一分为二都可无损恢复吗?

需要一点提示

连接可能制造伪元组。

查看过程、答案与错因

不能。须核对共同属性的决定关系等条件;例如拆出两张只靠非唯一姓名相连的表可能产生错误组合。

带走这一句

规范化依据业务依赖,设计完成后还要验证能否正确连回。

章末 / 把知识接起来

综合训练

原创综合训练

Reader(id,name),Loan(id,reader_id,returned)。设计外键;写每位读者未还数量;解释为何不在每行Loan重复电话。

需要一点提示

LEFT JOIN的筛选放ON可保留零借阅者;COUNT计右表非空键。

查看过程、答案与错因

外键Loan.reader_id引用Reader.id。SELECT r.id, COUNT(l.id) AS n FROM Reader r LEFT JOIN Loan l ON l.reader_id=r.id AND l.returned=0 GROUP BY r.id; 电话属于读者事实,重复会产生更新异常,应放Reader。WHERE l.returned=0会筛掉补NULL的零记录读者。

一点一点,积累下来。

今日学习

00:00:00

累计学习

00:00:00

学习天数

0 天

点击“开始计时”后累计时间。同一科目内切换章节或刷新会接续;切换科目不会自动启动另一科。仅当前获得焦点的可见页面累计,离开、关闭或休眠期间不补计。两科的时间与成就分别保存。

记录保存在当前浏览器,关闭后仍保留;清除网站数据会删除记录。每天累计满 1 分钟记为一个学习日,不要求连续打卡。

学习成就

已达成 0 / 10

成就记录投入与阅读进展,不代表掌握程度。阅读类成就随已读标记更新,撤销标记后会重新计算。