本文将介绍关系数据库的相关理论。
文章目录
前备知识
**关系:**在关系模型中,实体及实体间的各种联系称为关系
**域:**具有相同数据类型的值的集合
关系有三种类型:基本关系(基本表、基表)、查询表、视图表
关系代数
下文将会以如下两个关系R和S具为例进行说明,R和S有相同的目即二者具有相同的属性,且相应属性取自同一个域:
R:
S:
传统的集合运算
并
R ∪ S R \cup S R∪S:由属于R或属于S的元组组成。
交
R ∩ S R \cap S R∩S:由属于R且属于S的元组组成。
差
R − S R-S R−S:由属于R但不属于S的元组组成。
笛卡尔积
R × S R\times S R×S:
- R中的每一行和S中的每一行进行组合,组成新的行;
- 假设R有n个属性,S有m个属性,则 R × S R\times S R×S的结果应该有m+n个属性,即m+n列;
- 假设R有x行,S有y行,则 R × S R\times S R×S由xy行;
专门的关系运算
选择
KaTeX parse error: Expected '}', got '\and' at position 24: …F(R)={t|r\in R \̲a̲n̲d̲ ̲F(t)=真}
F(t)表示选择条件,是一个逻辑表达式,取逻辑值"真"或"假",逻辑表达式中可用的运算符如下表所示:
比如:
σ S d e p t = ′ I S ′ ( S t u d e n t ) \sigma_{Sdept='IS'}(Student) σSdept=′IS′(Student)
上式中F为 S d e p t = ′ I S ′ Sdept='IS' Sdept=′IS′, R=Student,表示从Student表中选择出满足条件 S d e p t = ′ I S ′ Sdept='IS' Sdept=′IS′的数据项。
投影
关系R上的投影是指从R中选择若干列组成新的关系,记做:
∏
A
(
R
)
=
{
t
[
A
]
∣
t
∈
R
}
\prod\ _A(R)=\{t[A]|t \in R\}
∏ A(R)={t[A]∣t∈R}
比如:
关系R中有如下列:{Sname,Sdept,Sage},则:
∏
S
n
a
m
e
,
S
d
e
p
t
(
R
)
=
{
S
n
a
m
e
,
S
d
e
p
t
}
\prod\ _{Sname,Sdept}(R)=\{Sname,Sdept\}
∏ Sname,Sdept(R)={Sname,Sdept}
连接
其中 A θ B A \theta B AθB中的 θ \theta θ表示比较运算符,连接运算的计算流程是这样的:
- 计算R和S的笛卡尔积 U = R × S U=R \times S U=R×S
- 从U中选取R.A属性和S.B属性满足比较运算符 θ \theta θ的元组
连接运算中有两种最常用的连接类型:
- **等值连接(内连接):**当 θ \theta θ为等号即 = = =的时候,对应连接为等值连接,记做 R ⋈ A = B S R\bowtie_{A = B}^{} S R⋈A=BS
- 自然连接:在等值连接的基础上,如果R.A和S.B是同名的属性组,并且在结果中把重复的属性去掉,对应的连接就称自然连接,即自然连接表示的是两个关系R和S选取在公共属性上值相等的元组进而构成新的关系,记做 R ⋈ S R\bowtie S R⋈S
我们以一个例子作为说明,比如有以下两个关系R和S:
R:
S:
其做自然连接后的结果应该为 R ⋈ S R\bowtie S R⋈S:
我们可以发现,在R和S做了等值连接之后,R和S中都有个别行消失了,比如R中的第3行(a1,b3,8),S中的第3行(b5,2),这是因为这两个行中不存在公共属性(B)上值相等的元组,所以被舍弃了,如果不舍弃,则应该是:
我们将像上图中最后2行的这种元组称为悬浮元组,将像上图这样将不存在值的地方填上NULL而不舍弃的连接称为外连接,记做,如果只保留左边关系R中的悬浮元组,称为左外连接,记作:
如果只保留右边关系S中的悬浮元组,称为右外连接,记做:
在实际的生产中我们一般是使用join关键字进行连接查询,举几个例子:
内连接(等值连接):
select * from A inner join B on A.name = B.name;
左外连接:
select * from A left join B on A.name = B.name;
或:
select * from A left outer join B on A.name = B.name;
我们之前还提到了笛卡尔积,其实,在数据库的实际编程中,笛卡尔积又叫交叉连接,关键字为cross join,在 MySQL(仅限于 MySQL) 中 CROSS JOIN
与 INNER JOIN
的表现是一样的,在不指定 ON 条件得到的结果都是笛卡尔积。
INNER JOIN
与 CROSS JOIN
可以省略 INNER
或 CROSS
关键字,因此下面的 SQL 效果是一样的:
... FROM table1 INNER JOIN table2
... FROM table1 CROSS JOIN table2
... FROM table1 JOIN table2
除运算
R ÷ S R \div S R÷S
表示所有包含在R但不包含在S中的属性及其值,也就是说,除运算是在行和列两个维度都有要求,具体地,计算 T = R ÷ S T=R \div S T=R÷S运算结果的步骤为:
- 列级别:使用R中的属性减去S中的属性,即使用R原有的属性集减去与S中相同的属性集,比如R中的属性集为{A,B,C},S中的属性集为{B,C,D},那么结果T的属性集为 A , B , C − B , C , D = A {A,B,C}-{B,C,D}={A} A,B,C−B,C,D=A
- 行级别:假设R的属性集为{A,B,C},R和S共同的属性集为{B,C},从1中我们知道最终T只有一列即A,T.A的值应该是KaTeX parse error: Expected 'EOF', got '\and' at position 19: …=\{R.A|R.B=S.B \̲a̲n̲d̲ ̲R.C=S.C\}
以一个实例进行说明,有关系R和S:
R:
S:
则其除运算的结果是:
alpha语言
alpha语言主要有get、put、hold、update、delete、drop六条语句,语句的基本格式为:
操
作
语
句
工
作
空
间
名
(
表
达
式
)
:
操
作
条
件
操作语句 工作空间名(表达式):操作条件
操作语句工作空间名(表达式):操作条件
检索
检索操作主要使用get语句实现。
简单检索(不带条件的检索)
查询所有学生的数据:
g
e
t
W
(
S
t
u
d
e
n
t
)
get \space W(Student)
get W(Student)
W表示工作空间名,这里的条件为空。
限定的检索(带条件的检索)
查询信息系(IS)中年龄小于20岁的学生的学号和年龄:
KaTeX parse error: Expected 'EOF', got '\and' at position 59: …ent.Sdept='IS' \̲a̲n̲d̲ ̲Student.Sage=20…
带排序的查询
查询信息系(IS)中年龄小于20岁的学生的学号和年龄,结果按年龄降序排序:
KaTeX parse error: Expected 'EOF', got '\and' at position 59: …ent.Sdept='IS' \̲a̲n̲d̲ ̲Student.Sage=20…
其中down表示降序排序,up表示升序排序。
指定返回的结果的条数
取出一个信息系学生的学号:
g
e
t
W
(
1
)
(
S
t
u
d
e
n
t
.
S
n
o
)
:
S
t
u
d
e
n
t
.
S
d
e
p
t
=
′
I
S
′
get \space W(1)(Student.Sno):Student.Sdept='IS'
get W(1)(Student.Sno):Student.Sdept=′IS′
用元组变量的检索
两种情况下需要使用元组变量:
- 关系名太复杂时可用元组变量达到简化关系名的目的
- 操作条件中使用量词时必须使用元组变量,这里的量词指的是存在量词、全称量词等。
比如:
r
a
n
g
e
S
t
u
d
e
n
t
X
g
e
t
W
(
X
.
S
n
a
m
e
)
:
X
.
S
d
e
p
t
=
′
I
S
′
range\space Student \space X\space get \space W(X.Sname) :X.Sdept='IS'
range Student X get W(X.Sname):X.Sdept=′IS′
其中X表示Student的别名,这样可以简化变量名。
用存在量词的检索
查询选修2号课程的学生名字:
KaTeX parse error: Expected 'EOF', got '\and' at position 99: …dent.Sno \space\̲a̲n̲d̲ ̲\space X.cno='2…
注意这里使用了存在量词,所以存在符号后面一定要使用元组变量即
∃
X
\exists X
∃X。
带有多个关系的表达式的检索
上面的例子中表达式中即查询结果只涉及一个关系,事实上查询结果中可以有多个关系。
查询成绩为90分以上的学生名字和课程名字:
KaTeX parse error: Expected 'EOF', got '\and' at position 112: …Grade>90 \space\̲a̲n̲d̲ ̲\\\space scX.Sn…
使用全称量词的检索
查询不选1号课程的学生姓名:
KaTeX parse error: Expected 'EOF', got '\or' at position 130: …dent.Sno\space \̲o̲r̲\space scX.Cno\…
本例也可以使用存在量词解决:
KaTeX parse error: Expected 'EOF', got '\and' at position 104: …dent.Sno\space \̲a̲n̲d̲\space scX.Cno=…
用两种量词的检索
查询选修了全部课程的学生姓名:
KaTeX parse error: Expected 'EOF', got '\and' at position 146: …nt.Sno\space \\\̲a̲n̲d̲\space scX.Cno=…
用蕴含的检索
查询最少选修了122号学生所选课程的学生学号。
KaTeX parse error: Expected 'EOF', got '\and' at position 138: …X.Sno='122' \\ \̲a̲n̲d̲ ̲scX.Cno=sX.Cno)…
聚集函数
聚集函数有以下几个:
查询信息系学生的平均年龄:
g
e
t
W
(
c
o
u
n
t
(
S
t
u
d
e
n
t
.
S
a
g
e
)
:
S
t
u
d
e
n
t
.
S
d
e
p
t
=
′
I
S
′
)
get\space W(count(Student.Sage):Student.Sdept='IS')
get W(count(Student.Sage):Student.Sdept=′IS′)
更新
修改操作
修改操作用update语句实现,步骤为:
- 用hold语句将要修改的元组从数据库中读到工作空间中
- 用宿主语言修改工作空间中元组的属性值
- 用update语句将修改后的元组送回数据库中
注意,单纯检索的话使用get关键字即可,但为修改而数据而读元组的话必须使用hold语句,hold语句是加上并发控制的get语句。
把127号学生的专业改为信息系:
h
o
l
d
W
(
S
t
u
d
e
n
t
.
S
n
o
,
S
t
u
d
e
n
t
.
S
d
e
p
t
)
:
S
t
u
d
e
n
t
.
S
n
p
=
′
12
7
′
(
从
S
t
u
d
e
n
t
中
选
出
需
要
修
改
的
内
容
)
m
o
v
e
′
I
S
′
t
o
W
.
S
d
e
p
t
(
修
改
元
组
的
属
性
值
)
u
p
d
a
t
e
W
(
将
修
改
后
的
元
组
送
回
数
据
库
)
hold\space W(Student.Sno,Student.Sdept) :Student.Snp='127'(从Student中选出需要修改的内容)\\ move\space 'IS'\space to\space W.Sdept(修改元组的属性值)\\ update\space W(将修改后的元组送回数据库)
hold W(Student.Sno,Student.Sdept):Student.Snp=′127′(从Student中选出需要修改的内容)move ′IS′ to W.Sdept(修改元组的属性值)update W(将修改后的元组送回数据库)
注意:
- 如果修改涉及两个关系的话,就应该执行两次hold-move-update的过程
- alpha语言不允许修改主码,要修改主码,应该先删除原来的元组,然后增加新的元组
插入操作
插入操作使用put关键字,步骤如下:
- 用宿主语言建立新元组
- 用put与局部将建立的元组存入指定的关系中
比如:
move '8' to W.Cno
move '计算机基础' to W.Cname
move '2' to W.Ccredit
put W(Course)
注意,put语句只能对单个关系操作
删除操作
删除操作使用delete关键字,步骤如下:
- 用hold语句将要删除的元组读到工作空间中
- 用delete语句删除该元组
删除第230号学生:
hold W(Student):Student.Sno='230'
delete W