CH2 关系模型介绍
2.1 关系数据库的结构
2.1.1 关系实例
关系数据库由表(table)的集合构成,每个表有唯一的名字。
表的一行代表一组值之间的一种联系。表是联系的集合,也是实体的集合。
n个值之间的联系在数学上可以用这些值的一个n元组来表示,换言之,n元组可以对应表中的一行。
于是,在关系模型中,关系用来指代表,元组用来指代行。
关系是元组的集合,所以元组在关系中出现的顺序是无关紧要的。
2.1.2 属性类型
-
域 domain:关系的每个属性,都存在一个允许取值的集合,称为该属性的域。
-
属性值一般要求是原子性 atomic的,不可再分的。
非 原 子 性 { 多 值 属 性 复 合 属 性 非原子性 \begin{cases} 多值属性\\ 复合属性\\ \end{cases} 非原子性{多值属性复合属性 -
null值是每个域的成员
n u l l 值 出 现 的 情 况 { 值 不 知 道 值 不 存 在 null值出现的情况 \begin{cases} 值不知道\\ 值不存在 \end{cases} null值出现的情况{值不知道值不存在
null值导致很多操作的定义变得复杂。要尽量避免使用空值。
2.2 数据库模式
数据库模式 database schema:数据库的逻辑设计
数据库实例 database instance:数据库中数据的一个快照
-
关系模式 relation schema<—>程序设计语言中的类型
R = ( A 1 , A 2 , . . . , A n ) R = (A_1,A_2,...,A_n) R=(A1,A2,...,An),其中 A i A_i Ai是列名(属性名),是一个关系模式。关系模式由属性序列和属性对应的域组成。
i n s t r u c t o r = ( I D , n a m e , d e p t n a m e , s a l a r y ) instructor = (ID,name,dept_name,salary) instructor=(ID,name,deptname,salary)是一个关系模式
要区别:instructor模式和Instructor实例。
同时,在关系模式中使用相同的属性是将不同关系的元组联系起来的一种办法。比如下面的department关系实例中的dept_name就将两个表格联系了起来。
关系 relation instance<—>程序设计语言中的变量
2.3 码
需求:要有一种能区分给定关系中的不同元组的方法。
一个元组的属性值必须是能够唯一区分元组的<==>一个关系中没有两个元组在所有属性取值上都相同。
-
超码
超码是一个或多个属性的集合。这些属性的集合能使我们在一个关系中唯一地标识一个元组。
比如instructor的ID足以将不同的教师区分开来,因为ID是一个超码。另外,instructor的name属性不是一个超码,因为不同的教师可能重名。
-
候选码
如果一个超码,他的任意真子集都不是超码,那么这样的最小超码称为候选码。
有可能多个属性集都能做候选码。
-
主码
数据库设计者选中的,主要用来在一个关系中区分不同元组的候选码。
主码的选择需要慎重,应选择值从不或极少变化的属性。
主码一般列在所有属性的前面。
-
外码
一个关系模式( 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 r2 r2称为外码的被依赖参照关系。
2.4 模式图
模式图可以表示主码和外码关系。
2.5 关系查询语言
查询语言:用户用来从数据库中请求获取信息的语言。
查
询
语
言
{
过
程
化
语
言
:
用
户
指
导
数
据
库
执
行
一
系
列
操
作
以
计
算
出
所
需
结
果
非
过
程
化
语
言
:
用
户
只
描
述
所
需
信
息
,
而
不
用
给
出
获
取
信
息
的
具
体
过
程
。
查询语言\begin{cases} 过程化语言:用户指导数据库执行一系列操作以计算出所需结果\\ 非过程化语言:用户只描述所需信息,而不用给出获取信息的具体过程。 \end{cases}
查询语言{过程化语言:用户指导数据库执行一系列操作以计算出所需结果非过程化语言:用户只描述所需信息,而不用给出获取信息的具体过程。
实际使用的查询语言既包括过程化的成分,又包括非过程化的成分。
2.6 关系运算
逻辑代数是一种过程化语言。
过程化语言提供了一组运算:
- 要么施加于单个关系上,要么施加于一对关系上
- 运算的结果总是单个的关系
基础的操作有:
- s e l e c t : σ select : \sigma select:σ 选择
- p r o j e c t : π project : \pi project:π 投影
- u n i o n : ∪ union : ∪ union:∪ 合并
- s e t d i f f e r e n c e : − set\quad difference : - setdifference:− 集合差
- C a r t e s i a n p r o d u c t : × Cartesian\quad product : \times Cartesianproduct:× 笛卡尔乘积
- r e n a m e : ρ rename : \rho rename:ρ 重命名
这些操作的操作对象和结果都是关系:可以在结果上继续施加运算。
2.6.1 选择
符号: σ p ( r ) \sigma_p(r) σp(r)
p:选择谓语 selection predicate(选择的条件)
r:选择的关系表
p的形式是一个谓词公式,用∧(and),∨(or),¬(not)
比如:
σ
d
e
p
t
_
n
a
m
e
=
"
P
h
y
s
i
c
s
"
(
i
n
s
t
r
u
c
t
o
r
)
σ
(
A
=
B
)
∧
(
D
>
5
)
(
r
)
\sigma_{dept\_name="Physics"}(instructor)\\ \sigma_{(A=B)∧(D>5)}(r)
σdept_name="Physics"(instructor)σ(A=B)∧(D>5)(r)
2.6.2 投影
符号: ∏ A 1 , A 2 , . . . , A k ( r ) \prod_{A_1,A_2,...,A_k}(r) ∏A1,A2,...,Ak(r)
A 1 , A 2 , . . . , A k A_1,A_2,...,A_k A1,A2,...,Ak是属性名,表示显示关系表r中的这些属性,其他属性不显示。
这不是一个原地操作。
不显示某些属性可能会造成重复行,所以投影操作中会把重复的行去除,只留下单一的一行。
比如:
∏
I
D
,
n
a
m
e
,
s
a
l
a
r
y
(
i
n
s
t
r
u
c
t
o
r
)
\prod\ _{ID,name,salary}(instructor)
∏ ID,name,salary(instructor)
2.6.3 合并
符号: r ∪ s r∪s r∪s
合并有下面的要求:
- r , s r,s r,s必须同元:属性相同
- 属性的域相同
2.6.4 集合差
符号: r − s r-s r−s
表示去掉r中含有的s的部分
r
−
s
=
{
t
∣
t
∈
r
a
n
d
t
∉
s
}
r-s=\{t|t∈r\quad and\quad t∉ s\}
r−s={t∣t∈randt∈/s}
要求:
- r和s必须同元 have the same arity
- 元的域相同
2.6.5 Cartrsian-Product Operation
符号: r × s r\times s r×s
如果无相加属性,那么直接做笛卡尔乘积。
如果有属性相交,那么需要重命名
2.6.5 Rename Operation
把关系改名:E改为x
ρ
x
(
E
)
\rho_x(E)
ρx(E)
关系改名的同时改属性名:E改为x的同时,属性名改为
A
1
,
A
2
,
.
.
.
,
A
n
A_1,A_2,...,A_n
A1,A2,...,An
ρ
x
(
A
1
,
A
2
,
.
.
.
,
A
n
)
(
E
)
\rho_{x(A_1,A_2,...,A_n)}(E)
ρx(A1,A2,...,An)(E)
2.6.6 集合笛卡尔乘积和重命名的联合
关系r和关系s如下:
关系r:
A | B |
---|---|
α \alpha α | 1 |
β \beta β | 2 |
关系s:
C | D | E |
---|---|---|
α \alpha α | 10 | a |
β \beta β | 10 | a |
β \beta β | 20 | b |
γ \gamma γ | 10 | b |
2.6.7 查询范例
Example1
找到最大的balance:
先找到非最大的,然后减法:
∏
b
a
l
a
n
c
e
(
a
c
c
o
u
n
t
)
−
∏
A
.
b
a
l
a
n
c
e
(
σ
A
.
b
a
l
a
n
c
e
<
B
.
b
a
l
a
n
c
e
(
ρ
A
(
b
a
l
a
n
c
e
)
×
ρ
B
(
b
a
l
a
n
c
e
)
)
)
\prod \ _{balance}(account) - \prod \ _{A.balance}(\sigma_{A.balance<B.balance}(\rho_{A}(balance)\times\rho_B(balance)))
∏ balance(account)−∏ A.balance(σA.balance<B.balance(ρA(balance)×ρB(balance)))
从这个例子说明:
- 表与自身做笛卡尔乘积需要重命名,同时属性的名字会自动改为:new_name.attribute。(即改了表名,没有特别需要的话不需要再次更改属性名)
- 提供思路:如何查找最大的和最小的?
Example 2
Find the loan number for each loan of an amount greater than $1200.
$$ \prod \ _{loan\_number}(\sigma_{amount>1200}(loan)) $$ 除了特别需要,写查询表达式时不需要写出结果集。Example 3
Find the customers name who have at least one deposit of a balance greater than $700.
表达式 1:
∏
c
u
s
t
o
m
e
r
_
n
a
m
e
(
σ
(
d
e
p
o
s
i
t
o
r
.
a
c
c
o
u
n
t
_
n
u
m
b
e
r
=
a
c
c
o
u
n
t
.
a
c
c
o
u
n
t
_
n
u
m
b
e
r
)
∧
(
a
c
c
o
u
n
t
.
a
c
c
o
u
n
t
_
n
u
m
b
e
r
>
700
)
(
a
c
c
o
u
n
t
×
d
e
p
o
s
i
t
o
r
)
)
\prod \ _{customer\_name}(\sigma_{(depositor.account\_ number=account.account\_number)∧(account.account\_number>700)}(account\times depositor))
∏ customer_name(σ(depositor.account_number=account.account_number)∧(account.account_number>700)(account×depositor))
表达式 2:
∏
c
u
s
t
o
m
e
r
_
n
a
m
e
(
σ
x
.
a
c
c
o
u
n
t
_
n
u
m
b
e
r
=
d
e
p
o
s
i
t
o
r
.
n
u
m
b
e
r
(
ρ
x
(
σ
a
c
c
o
u
n
t
.
b
a
l
a
n
c
e
>
700
(
a
c
c
o
u
n
t
)
)
×
d
e
p
o
s
i
t
o
r
)
)
)
\prod \ _{customer\_name}(\sigma_{x.account\_number=depositor.number}(\rho_x(\sigma_{account.balance>700}(account))\times depositor)))
∏ customer_name(σx.account_number=depositor.number(ρx(σaccount.balance>700(account))×depositor)))
Example 4
Find all customers who have at least two deposits.
∏
c
u
s
t
m
o
r
_
n
a
m
e
(
σ
D
1.
c
n
a
m
e
=
D
2.
c
n
a
m
e
∧
D
1.
a
n
u
m
<
>
D
2.
a
n
u
m
(
ρ
D
1
(
c
n
a
m
e
,
a
n
u
m
)
(
d
e
p
o
s
i
t
o
r
)
×
ρ
D
2
(
c
n
a
m
e
,
a
n
u
m
)
(
d
e
p
o
s
i
t
o
r
)
)
)
\prod \ _{custmor\_name}(\sigma_{D1.cname=D2.cname∧D1.anum<>D2.anum}(\rho_{D1(cname,anum)}(depositor)\times\rho_{D2(cname,anum)}(depositor)))
∏ custmor_name(σD1.cname=D2.cname∧D1.anum<>D2.anum(ρD1(cname,anum)(depositor)×ρD2(cname,anum)(depositor)))
不等于的写法!
<
>
<>
<>
2.7 Additional Operations
2.7.1 集合交 Intersection Operation
符号:r∩s
r ∩ s = r − ( r − s ) r∩s = r-(r-s) r∩s=r−(r−s)
Find the names of all customers who have a loan and an account at bank。
π
c
u
s
t
o
m
e
r
_
n
a
m
e
(
b
o
r
r
o
w
e
r
)
∩
π
c
u
s
t
o
m
e
r
_
n
a
m
e
(
d
e
p
o
s
i
t
o
r
)
\pi_{customer\_name}(borrower)∩\pi_{customer\_name}(depositor)
πcustomer_name(borrower)∩πcustomer_name(depositor)
2.7.2 Joined Relations
θ − \theta- θ−连接
θ
−
\theta-
θ−连接是一个比较通用的连接,他不需要两个操作的关系有相同的属性,并且连接条件可以是任何比较操作符。
R
t
i
m
e
s
S
W
H
E
R
E
F
R\quad times\quad S\quad WHERE\quad F
RtimesSWHEREF
等值连接是另一种连接,他的合并条件是相等操作。
Natural join operation 自然连接
Notion:$r\Join s $
R的模式: ( A , B , C , D ) (A,B,C,D) (A,B,C,D);S的模式: ( E , B , D ) (E,B,D) (E,B,D)
R ⋈ S R\Join S R⋈S的模式: ( A , B , C , D , E ) (A,B,C,D,E) (A,B,C,D,E)
r ⋈ s r\Join s r⋈s被定义为:
π r . A , r . B , r . C , r . D , s . E ( σ r . B = s . B ∧ r . D = s . D ( r × s ) ) \pi_{r.A,r.B,r.C,r.D,s.E}(\sigma_{r.B=s.B\wedge r.D = s.D}(r\times s)) πr.A,r.B,r.C,r.D,s.E(σr.B=s.B∧r.D=s.D(r×s))
自然连接的原表会有损失
自然连接举例:
Outer Join
外连接避免了信息的丢失。使用null值替换不存在的项目。
- 左外连接
左表为主表。
- 右外连接
右表为主表。
- 全连接
例 1
例1给出2.6.7的example的表达式三:直接使用自然连接,可以不写笛卡尔乘积后的筛选条件了。
π
c
u
s
t
o
m
e
r
_
n
a
m
e
(
σ
b
a
l
a
n
c
e
>
′
70
0
′
(
a
c
c
o
u
n
t
⋈
d
e
p
o
s
i
t
o
r
)
)
\pi_{customer\_name}(\sigma_{balance>'700'}(account\Join depositor))
πcustomer_name(σbalance>′700′(account⋈depositor))
例2:
2.7.3 Division Operation 除
适用于包含短语for all的语句
假设关系r和关系s的模式R和S分别为:
R
=
(
A
1
,
A
2
,
.
.
.
,
A
m
,
B
1
,
.
.
.
,
B
n
)
S
=
(
B
1
,
.
.
.
,
B
n
)
R=(A_1,A_2,...,A_m,B_1,...,B_n)\\ S = (B_1,...,B_n)
R=(A1,A2,...,Am,B1,...,Bn)S=(B1,...,Bn)
那么r÷s的模式为:
R
÷
S
=
(
A
1
,
A
2
,
.
.
.
,
A
m
)
R÷S= (A_1,A_2,...,A_m)
R÷S=(A1,A2,...,Am)