系统分析师笔记(六)-- 数据库:主属性、候选码、超码、E-R图
用“元素”和“集合”的视角来区分,这是理解数据库范式和关系理论的逻辑。
理解复盘与微调:
-
主属性 = 元素(原子属性) ✅
- 正确。主属性是单个的属性(比如
A、B)。注意,它必须是包含在任意一个候选码里的属性。
- 正确。主属性是单个的属性(比如
-
候选码 = 只由主属性构成的最小集合 ✅(逻辑上绝对正确)
- 这里的“最小”有两层含义:一是属性个数最少,二是完全函数依赖(不能有冗余属性)。
- 补充一个细节:既然候选码是由主属性构成的,那非主属性能不能进候选码?不能。因为如果非主属性在候选码里,它就能决定其他属性,那它本身就变成主属性了(自相矛盾)。所以你的“只由主属性构成”这句话,逻辑闭环非常完美。
-
超码 = 包含候选码的更大的集合 ✅
- 正确。超码就是“候选码 + 任意其他属性(可以是主属性,也可以是非主属性)”。
- 补充一个细节:超码是不要求最小的。所以超码可能很“臃肿”,包含了一堆无关的属性。
一个形象的比喻(乐高积木理论)
- 主属性 = 乐高积木块(单个零件)。
- 候选码 = 能够拼成一辆完整小汽车(决定所有属性)的最少积木组合(比如:底盘+轮子)。拆掉任何一个,车就拼不成。
- 超码 = 在“底盘+轮子”的基础上,你再随便加几块多余的积木(比如加个车顶,或者加个尾翼),它仍然是一辆完整的车(依然能决定所有属性),但积木数量变多了,不是最小的了。
唯一需要小心的“逻辑陷阱”
虽然“候选码只由主属性构成”是对的,但千万不要反过来理解为“只要由主属性构成的集合就是候选码”。
比如,主属性有 A 和 B,超码 {A, B} 是由主属性构成的,但它不是候选码(因为它太大了,单独 A 或 B 就能决定所有属性)。
修正后的完整表述:
- 主属性是构成候选码的“零件”。
- 候选码是由主属性构成的、能唯一标识元组、且不能再精简的最小集合。
- 超码是包含至少一个候选码的集合(可能包含非主属性的冗余零件)。
多值依赖(有冗余,要拆表)

关键:两个一对多,两个“多”独立
-
怎么快速识别多值依赖?
只要看到:A决定B(一对多),A决定C(一对多),且B和C没有依赖关系,B和C的数据呈现出完全交叉组合(笛卡尔积)。
立刻判定:存在多值依赖 A →→ B 和 A →→ C。 -
多值依赖带来的问题(考点)
- 极度冗余:“数据库”三个字重复了4次,张老师重复了2次,书名也重复了2次。
- 操作异常:
- 如果我们要新增一位“李老师”教“数据库”,如果不给他指定参考书,我们就无法插入这条记录(插入异常)。
- 如果我们要删除《SQL必知必会》这本书,就会连带把王老师教数据库的信息也删掉(删除异常)。
---------------------> 多值依赖 不存在 函数依赖<------------------------
- 如何消除多值依赖?(第四范式 4NF)
- 要消除多值依赖,必须把这张表拆开,拆成两张表:
- 表1(课程-教师):课程,教师
- 表2(课程-参考书):课程,参考书
- 这样,教师和参考书各自独立,互不影响,彻底解决了冗余和异常。
- 要消除多值依赖,必须把这张表拆开,拆成两张表:
这也是软考中常考的第四范式(4NF)的核心定义:在满足3NF的基础上,消除非平凡且 非函数依赖 的多值依赖。
笛卡尔积
一、 生活里的“笛卡尔积”:组合搭配
假设你早上出门挑衣服:
- 上衣(集合A):有2件 ——
- 裤子(集合B):有3条 ——
如果要求你必须穿一件上衣搭配一条裤子,请问有多少种穿法?
答案是:2 × 3 = 6 种。
这所有可能的组合,就是“上衣”和“裤子”的笛卡尔积。
二、 数学上的正式定义
在数学中,两个集合 (A) 和 (B) 的笛卡尔积,记作 (A \times B)。
它的定义是:用集合A里的每一个元素,去匹配集合B里的每一个元素,组成的所有“有序对”的集合。
- 数学公式:(A \times B = {(a, b) \mid a \in A, b \in B})
- 规律:结果的总个数 = 集合A的元素个数 × 集合B的元素个数。
三、 数据库里的“笛卡尔积”(关系代数)(元素 <--> 行)
在数据库里,“集合”变成了“表(关系)”,“元素”变成了“行(元组)”。笛卡尔积的规则是:
- 列数相加:结果表的列数 = 表A的列数 + 表B的列数。
- 行数相乘:结果表的行数 = 表A的行数 × 表B的行数。
- 每一行进行“拼接”:表A的每一行,都要和表B的每一行拼成一条完整的新行。
举个数据库的例子:
有两张表:
表A(学生表)
| 学号 | 姓名 |
|---|---|
| 1 | 张三 |
| 2 | 李四 |
表B(课程表)
| 课程号 | 课程名 |
|---|---|
| C1 | 语文 |
| C2 | 数学 |
表A × 表B(笛卡尔积结果):
| 学号 | 姓名 | 课程号 | 课程名 |
|---|---|---|---|
| 1 | 张三 | C1 | 语文 |
| 1 | 张三 | C2 | 数学 |
| 2 | 李四 | C1 | 语文 |
| 2 | 李四 | C2 | 数学 |
你会发现,2个学生 × 2门课 = 4条记录(行数相乘),列数也是4列(2+2)。
这就是数据库里的笛卡尔积。
四、 “完全独立的笛卡尔积”
现在再看之前“课程-教师-参考书”的例子,就好懂了:
- 对于“数据库”这门课(固定值):
- 教师有2个:
- 参考书有2本:
- 因为“教师”和“参考书”完全独立,所以它们就像上衣和裤子一样,必须进行“全排列组合”(2×2=4种),就构成了“完全独立的笛卡尔积”。
五、 笛卡尔积在考试和实际中的意义
- 它是“连接(Join)”的基础:在数据库里,两张表想要关联起来(比如查询“选了语文课的学生”),第一步在底层就是先做笛卡尔积(把所有学生和所有课程组合起来),然后再通过条件(WHERE 学号=选课表.学号)去过滤掉无意义的组合。
- 它是一个“超级炸弹”:在没有过滤条件的情况下,如果你对两张几千行、几百行的表做笛卡尔积,结果可能变成几亿行,直接把数据库内存撑爆。所以我们在写 SQL 时,一定要避免产生无意义的笛卡尔积(即忘记写多表连接的条件)。
- 多值依赖的灾难:之前说的多值依赖,本质上就是由于表里出现了“完全独立的笛卡尔积”(比如教师和书),导致了极度严重的数据冗余。解决的办法就是“拆表”,把“课程-教师”和“课程-参考书”拆开,这样每个表里就没有笛卡尔积了。
范式:概念及判断

范式,是用来度量关系函数的好坏的
| 函数依赖 X → A 的情况 | 最高只能达到 | 分析 |
|---|---|---|
存在 非主属性 部分依赖于 组合码 |
1NF | X 是组合码的真子集 |
存在 非主属性 传递依赖于 非超码 |
2NF | X 是非超码,A 是非主属性 |
| 存在 主属性 依赖于 非超码 | 3NF | X 是非超码,A 是主属性 |
| 所有 X(左边) 都是 超码 | BCNF | 完美,无任何非超码决定属性 |
浙公网安备 33010602011771号