主题
关系模型与完整性
第二讲。关系模型是本课的数学地基——"关系"不是日常说的关系,而是集合论里的笛卡尔积子集。学完这讲,键的判定和三类完整性约束不再是背诵题。
先记住一句话:候选键是"能唯一标识元组的最小属性集",主键是"被选中的一个候选键",外键是"指向别家主键的自家属性"。
一、关系的严格定义
设 D₁, D₂, …, Dₙ 为 n 个域(属性的取值范围),D₁×D₂×…×Dₙ 的笛卡尔积的子集称为关系(relation),记作 R(D₁, D₂, …, Dₙ)。
拆成人话:
| 术语 | 对应表里的 | 数学身份 |
|---|---|---|
| 关系 relation | 一张二维表 | 笛卡尔积的子集 |
| 元组 tuple | 一行 | 笛卡尔积的一个元素 |
| 属性 attribute | 一列 | 域的名字 |
| 域 domain | 列的取值范围 | 非空原子值集合 |
| 候选码/候选键 | 能唯一标识行的最小列集 | 无冗余的标识集合 |
| 分量 | 某行某列的值 | 单个值 |
两个必须背下的性质:候选键具有最小性(去掉任何一个属性就不再唯一);主属性是所有候选键里的属性,其余叫非主属性。
二、键的判定:一道例题走三遍
设有表 SC(sno, cno, tname, grade)(学号、课程号、教师、成绩),语义:每门课只由一位教师开,一个学生每门课只有一条成绩记录。
- 哪些是候选键?只有 (sno, cno):单凭 sno 不能区分不同课程,单凭 cno 不能区分不同学生——合起来才唯一
- (sno, cno, tname) 是候选键吗?不是——包含 (sno, cno) 还多出 tname,违反最小性
- tname 是主属性吗?不是——它不属于任何候选键,是非主属性(这个判定第五讲判范式时还要用)
🧠 记忆锚点:先找唯一,再砍冗余,剩下的才是候选键。
选定一个候选键作主键(primary key),其余候选键叫备用键。主键的属性值不允许 NULL、不允许重复——这就是实体完整性的要求。
三、三类完整性约束
| 约束 | 针对谁 | 规则 | 例子 |
|---|---|---|---|
| 实体完整性 | 主键 | 主属性非空、不重复 | 两个学生不能同号;sno 不能是 NULL |
| 参照完整性 | 外键 | 外键值要么为 NULL,要么必须存在于被参照表的主键中 | SC 的 sno 必须在 student 表里存在(否则是幽灵学生) |
| 用户定义完整性 | 具体业务 | 用户根据语义自行设定 | sage BETWEEN 14 AND 45;ssex IN ('男','女') |
**外键(foreign key)**的要点:设 F 是表 R 的属性集,F 与表 S 的主键对应,则 F 是 R 的外键,R 是参照关系,S 是被参照关系。两个经典追问:
- 为什么外键可以取 NULL? NULL 表示"尚未确定",比如成绩表先登记了课程、学生还没选——语义上允许
- 删除被参照行时怎么办? 三种策略:
RESTRICT(拒绝删除,有成绩记录的学生不许删)、CASCADE(级联删除,学生删了成绩跟着删)、SET NULL(外键置空)。SQL 里建外键时用ON DELETE指定
四、关系代数:五种基本运算
关系代数是 SQL 的数学原型,考试常考"用关系代数写出查询"。五个基本运算:
text
选择 σ(selection): σ_sage>18(student) → 挑行(水平方向切)
投影 π(projection): π_sname,sage(student) → 挑列(垂直方向切,自动去重)
并 ∪、差 −: 两个同构关系的行集合运算
笛卡尔积 ×: 两表逐行配对(结果列数相加、行数相乘)其余运算都可用基本运算导出,最常用的是交 ∩(R ∩ S = R − (R − S))和连接 θ-join(笛卡尔积 + 选择)。
连接的三个考点:
| 连接 | 定义 | 例子 |
|---|---|---|
| θ 连接 | R ×ₐθᵦ S,按条件筛配对 | R.B > S.B |
| 等值连接 | θ 取等号的特例 | R.sno = S.sno |
| 自然连接 | 等值连接后去掉重复列,同名属性自动匹配 | student ⋈ SC |
⚠️ 等值连接和自然连接的区别是高频选择题:自然连接去掉了重复列,等值连接不去;且自然连接要求两表有同名属性。
五、动手:把完整性约束建进表里
💡 动手实验:在
course库里建 student、course、sc 三张表,把本讲全部约束写进 DDL:sqlCREATE TABLE student ( sno CHAR(10) PRIMARY KEY, -- 实体完整性 sname VARCHAR(20) NOT NULL, ssex CHAR(2) CHECK (ssex IN ('男','女')), -- 用户定义 sage INT CHECK (sage BETWEEN 14 AND 45) ); CREATE TABLE course ( cno CHAR(6) PRIMARY KEY, cname VARCHAR(30) NOT NULL UNIQUE, credit INT DEFAULT 2 ); CREATE TABLE sc ( sno CHAR(10), cno CHAR(6), grade INT CHECK (grade BETWEEN 0 AND 100), PRIMARY KEY (sno, cno), -- 表级主键:复合候选键 FOREIGN KEY (sno) REFERENCES student(sno) ON DELETE CASCADE -- 参照完整性:级联删除 ); -- 验证约束确实在工作: INSERT INTO sc VALUES ('9999', 'C01', 90); -- 报错!外键 9999 不在 student 中 INSERT INTO student VALUES ('2026002', '李四', '男', 200); -- 报错!CHECK 违反看到两条 INSERT 都被拒绝,说明完整性约束不是文档,是数据库替你执法的规则——这就是"数据库比文件强"在第二层的体现(第一层是统一查询)。
小结
- 关系 = 笛卡尔积的子集;元组 = 行,属性 = 列,域 = 取值范围
- 候选键:唯一 + 最小;主键:选中的候选键;主属性 = 候选键里的属性
- 三类完整性:实体(主键非空唯一)、参照(外键存在或为 NULL)、用户定义
- 外键删除三策略:RESTRICT / CASCADE / SET NULL
- 关系代数五基本:选择(行)、投影(列)、并、差、笛卡尔积;自然连接 = 等值连接 − 重复列
下一讲进入主战场:用 SQL 把这些查询全部写出来——SQL 查询。