数据库系统原理与实践 笔记 #1
这次会把《数据库系统原理与实践》这门课的笔记发在这个系列的博客当中,可能有一些错误,也可能不太全,希望各位谅解。
关系模型介绍
关系的例子
- 关系模型是目前广泛应用的一种数据模型
- 关系数据库由表的集合构成
关系模式的表示
元组与属性
- 元组:表中的一行,元组顺序无所谓
- 属性:必须是原子的,空值(null)是一个特殊的值,表示该属性未知或不存在
- 属性域:属性的取值范围
关系模式可以表示为 R ( A 1 , A 2 , . . . , A n ) R(A_1, A_2, ..., A_n) R(A1,A2,...,An)
- R R R表示关系名,例如后面的instructor就是一个关系名,而 A 1 , A 2 , . . . , A n A_1,A_2,...,A_n A1,A2,...,An表示属性,如后面的ID,name等等都是instructor关系的属性
- 例如:instructor(ID, name, dept_name, salary)
- 在关系模式中,使用相同属性可将不同关系的元组联系起来(貌似跟外键引用Foreign Key有关系)
关系模式与关系实例
-
关系模式:关系的逻辑设计
-
关系实例:给定时刻关系中数据的一个快照
-
一般来说,关系模式不常变化,关系实例常常变化
Keys(键、码)
- K能唯一标识关系r®中的一个元组,则称K为关系r®的超码(Superkey)
- 超码K是一个或多个属性的集合, K ⊆ R K\subseteq R K⊆R
- 例:{ID}和{ID, name}是instructor的超码
- 超码可能包含无关紧要的属性
- K的任意超集也是超码
候选码(candidate key)和主码(primary key)
- 任何真子集都不能称为超码的最小超码称为候选码
- 例:{ID}是instructor的候选码
外码(foreign key)
-
一个关系模式( r 1 r_1 r1)在其属性上包含另一个关系模式( r 2 r_2 r2)的主码,此属性在 r 1 r_1 r1上称为引用 r 2 r_2 r2的外码, r 1 r_1 r1称为外码依赖的引用关系, r 2 r_2 r2称为外码的被引用关系
-
参照关系的任意元组在特定属性(如外码)上的取值,必须等于被引用关系的某个元组在该特定属性上的取值,这种约束要求称之为引用完整性约束
模式图
- 一个含有主码和外码依赖的数据库模式可用模式图来表示
- 每一个关系模式用一个矩形来表示
- 主码属性用下划线标注
- 外码约束(依赖)用从参照关系的外码到被引用关系的主码之间的箭头来表示
- 不要与E-R图混淆
关系查询语言
- 命令式/过程化查询语言
- 函数式查询语言
- 声明式/非过程化语言
纯查询语言
- 关系代数(函数式):SQL的理论基础
- 元组关系演算、域关系演算(声明式)
- 实践中查询语言(如SQL)会同时包括命令式、函数式、声明式方法的元素
SQL
SQL查询语言概述
- 商业系统提供了绝大部分的SQL标准功能(即使不是全部的SQL-92),再加上从后来的标准和特殊额专有功能(可能是非SQL标准)提供的不同功能集合
SQL数据定义
SQL的数据定义语言能够定义每个关系的信息,包括:
- 关系的模式
- 属性的取值类型、取值范围(属性域)
- 完整性约束(主外码)
- 关系的安全性与权限信息
- 还包括其他信息如:每个关系维护的索引集合、每个关系在磁盘上的物理存储结构
SQL的基本类型
- char(n):固定长度的字符串,用户指定长度为n
- varchar(n):可变长度字符串,用户指定最大长度n
- int: 整数类型(4字节)
- smallint: 小整数(2字节)
- numeric(p, d): 定点数,精度由用于指定。这个数有p位数字,其中,d位数字在小数点右边
- real, double precision:浮点数与双精度浮点数,精度与机器相关
- float(n):精度至少为n位的浮点数
基本关系模式定义
create table r( A1 D1,
...,
An Dn,
<完整性约束1>,
...,
<完整性约束k>
); (分号结束)
- r是关系名, A i A_i Ai是关系r模式中的一个属性名, D i D_i Di是属性 A i A_i Ai的域(即取值类型、范围)
Create Table中的完整性约束
- not null
- primary key( A 1 , . . . , A n A_1, ..., A_n A1,...,An)
- foreign key( A m , . . . , A n A_m, ..., A_n Am,...,An) references r( A p , . . . , A q A_p, ..., A_q Ap,...,Aq);
SQL禁止破坏完整性约束的数据库更新,例如:
- 新插入的元组主码属性为空值、或取值与关系中的另一元组主码属性相同
- 新插入的student元组所在的dept_name未出现在department关系中,破坏外码约束
删除和修改表
- drop table student 删除整个student表
- delete from student 删除表里的内容,但是保留表本身
- alter table 增加、删除属性:
alter table r add A D
-- 其中A为要被添加到关系r的属性的名称,并且D是A的域
-- 关系中所有元组使用null作为新的属性值
alter table r drop A
-- 其中,A是关系r的属性的名称
-- 许多数据库都不支持删除属性,但支持drop整个表
SQL查询的基本结构
select语句的基本结构
- 典型的SQL查询语句的形式:
select A1, A2, ..., An
from r1, r2, ..., rm,
where P1 and (or, not) Pn;
- A i A_i Ai代表一个属性
select子句
- 选择字句列出的是查询语句所需要的属性
- 对应关系代数中的投影操作(属性的选择)
- SQL在查询结果和干洗中默认允许重复
- 为了强制消除重复,可以在select后加上关键字distinct
- 例如找出所有教师所在的系名,并且结果中没有重复的名称:
select distinct dept_name
from instructor;
- 关键字all表示允许重复
- "*"在select子句中表示“所有属性”
select *
from instructor;
- select子句中可以包含算是表达式,算术表达式中可以有+,-,*,/运算符和对常量和属性的操作:
select ID, name, salary/12
from instructor;
- select子句还可以包含其他一些特殊的数据类型,如日期以及算术函数等等
where子句
- where子句表示结果必须满足的限定条件
- 对应关系代数的选择操作(元组的选择)
- 例如:找出Comp. Sci.系中公子大于80000的教师的姓名
select name
from instructor
where dept_name = 'Comp. Sci.' and salary > 80000;
- where子句中可以包含逻辑运算符and, or, not
- 逻辑运算符的运算对象可以是包含比较运算符>, >=, <, <=, =和<> 的表达式
- 允许使用比较运算符来比较字符串、算术表达式以及日期类型等等
from分句
-
from分句中列出了查询中用到的关系
-
对应关系代数中笛卡尔积的操作
-
笛卡尔积instructor × \times × teaches
select *
from instructor, teaches;
-
生成每一个可能的instructor-teaches对,所有属性来自两个表
-
理解为一个迭代(多重循环) 的过程
-
经常结合where子句使用(关系代数中的选择操作)
-
如果多关系中存在相同属性,则再select、where子句中须作区分,例如:instructor.ID, teaches.ID
连接
- 对所有上课的教师,查询他们的姓名及课程ID:
select name, course_id
from instrctor, teaches
where instructor.ID = teaches.ID;
- 查询Comp. Sci.开的每一门课course ID, semester, year, title
select section.course_ID, semester, year, title
from section, course
where section.course_ID = course.course_ID and dept_name = 'Comp. Sci.';
SQL查询语句
通常来说,一个SQL查询的含义可以理解如下:
- 1.为from子句中列出的关系产生笛卡尔积
- 2.在步骤1的结果上应用where子句中指定的为此
- 3.对于步骤2结果中的每个元组,输出select子句中指定的属性(或表达式的结果)
上述过程不是SQL查询语句的执行顺序,实际SQL查询语言的执行是经过查询优化
- 如果省略where子句,则谓词P为true
- 与关系代数表达式不同,在SQL的查询结果中可以包含很多重复的元组
自然连接
- 自然连接会匹配两个关系中所有共同属性的相同值的元组,去除重复属性列
- 自然连接结果 = 共同属性+第一个关系属性+第二个关系属性+…
- 例如:
select *
from insturctor natural join teaches;
- natural join是自然连接关键字
select name, course_id
from instructor natural join teaches;
-- Or --
select name, course_id
from instructor, teaches
where instructor.ID = teaches.ID;
- 危险的自然连接:谨防无关的属性具有相同的名字
- 列出老师的姓名,教师所教的课程的名称
- 错误做法:
select name, title
from instructor natural join teaches natural join course;
- 正确做法:
select name, title
from instructor natural join teaches, course
where teaches.course_ID = course.course_ID;
- 正确做法2:
select name, title
from (instructor natural join teaches)
join course using(course_id);
-- 这个join using是做什么的?
select name, title
from (instructor join teaches using(ID))
join course using(course_id);