关系模型与关系代数
1.关系模型
1.1 关系数据库的结构
关系数据库由表的集合构成,在关系模型中,关系用来指代表,元组用来指代行,属性用来指代列,关系实例表示一个关系的特定实例,也就是所包含的一组特定的行。
域(domain):每个属性允许取值的集合,如果域中元素被看作是不可再分的单元,则域是原子的。
例如表中有一个属性phone_number,存放一组电话号码,它就不是原子的,因为一组电话号码还可以被分为单个电话号码这样的子成分。
重要的问题不在于域本身是什么,而在于怎样在数据库中使用域中元素。例如,phone_number属性现在存放一个电话号码了,但我们仍然可以(如果需要的话),将电话号码拆分为国家编号,地区编号以及本地号码,那么它仍然是非原子值。如果我们把每个电话号码作为不可再分的单元,那么phone_number属性才会有原子的域。
1.2 码、键
-
超码(SuperKey)
K ⊆ R K\subseteq R K⊆R,如果 K K K的值能找到唯一一个元组,就称为超键。
E.g {instructor_id},{instructor_id,instructor_name} ,则{instructor_name}是超键,如果没有两个相同的名字
-
候选码(Candidate key)
包含属性最短的超键
-
主码(Primary key)
在候选码中挑一个
-
外键/外码(Foreigh 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也称为外码依赖的参照关系(referencing relation), r 2 r_2 r2叫做外码的被参照关系。
参照完整性约束:要求在参照关系中任意元组在特定属性上的取值必然等于被参照关系中某个元组在特定属性上的取值。
模式图:一个含有主码和外码依赖的数据库模式可以用模式图表示。
2.关系代数
2.1 关系查询语言
查询语言(query language) 是用户用来从数据库中请求获取信息的语言。
过程化语言:
关系代数
非过程化语言:
-
SQL(结构化查询语言)
-
元组关系演算
R − S = { t ∣ R ( t ) ∧ ⌉ S ( t ) } R-S=\{t|R(t)\wedge_\rceil S(t)\} R−S={t∣R(t)∧⌉S(t)}
-
域关系演算
{ < A , B , C > ∣ < A , B , C > ∈ S t u d e n t ∧ C = " M o n i t o r " } \{<A,B,C>|<A,B,C>\in Student \wedge C = "Monitor"\} {<A,B,C>∣<A,B,C>∈Student∧C="Monitor"}
2.2 关系运算
基本操作:
-
选择 σ \sigma σ:水平选择,选择行/元组
σ d e p t _ n a m e = " p h y s i c s " ∧ s a l a r y > 90 , 000 ( i n s t r u t o r ) \sigma_{dept\_name="physics"\wedge salary >90,000}(instrutor) σdept_name="physics"∧salary>90,000(instrutor)
-
投影 Π \Pi Π:垂直选择,选择列/属性
Π A 1 , A 2 , ⋯ , A n ( r ) \Pi_{A_1,A_2,\cdots,A_n(r)} ΠA1,A2,⋯,An(r),意为只取 A 1 , A 2 , ⋯ , A n A_1,A_2,\cdots,A_n A1,A2,⋯,An属性,其余属性不要,取完后可能需要合并(取部分信息)
-
集合并 ∪ \large \cup ∪
r , s r,s r,s必须是同元的(拥有相同数量的属性)
属性的域必须是相容的,同一列处理相同的属性
-
集合差
r − s r-s r−s,在 r r r中去除 s s s中的元素,两个集合也必须是同元的,相容的。
-
笛卡尔积
r ( R ) r(R) r(R)与 s ( S ) s(S) s(S)是不相交的,即 R ∩ S = ∅ R\cap S=\large\empty R∩S=∅。
如果相交,则必须重命名,例如,都含有 A A A这个属性,则需要更名为 A 1 , A 2 A_1,A_2 A1,A2之类的
-
重命名 ρ \rho ρ
ρ x ( A 1 , A 2 , ⋯ , A n ) ( E ) \rho_{x(A_1,A_2,\cdots,A_n)}(E) ρx(A1,A2,⋯,An)(E)把表达式 E E E的n个属性更名为 A 1 , A 2 , ⋯ , A n A_1,A_2,\cdots,A_n A1,A2,⋯,An
-
集合交 ∩ \cap ∩
r , s r,s r,s必须同元相容,取二者均有的元素, r ∩ s = r − ( r − s ) r\cap s=r-(r-s) r∩s=r−(r−s)
-
自然连接 ⋈ \Join ⋈
从两个输入关系输出这样的元组:它们在具有相同名字的所有属性上取值相同。
E.g., R = ( A , B , C , D ) , S = ( E , B , D ) R=(A,B,C,D),S=(E,B,D) R=(A,B,C,D),S=(E,B,D)
结果为 ( A , B , C , D , E ) (A,B,C,D,E) (A,B,C,D,E), r ⋈ s = Π r . A , r . B , r . C , r . D , r . E ( σ r . B = s . B ∧ r . D = s . D ( r × s ) ) r\Join s=\Pi_{r.A,r.B,r.C,r.D,r.E}(\sigma_{r.B=s.B\wedge r.D=s.D}(r\times s)) r⋈s=Πr.A,r.B,r.C,r.D,r.E(σr.B=s.B∧r.D=s.D(r×s))
就运算后的元素,要求在相同的属性上,取值相同,引入新属性。
-
外连接
计算连接,然后将一个关系与另一个关系中的元组不匹配的元组添加到连接的结果中
使用空值null,表示值未知或不存在,所有涉及null的比较从定义上来说都是false
-
除法 ÷ \div ÷
r , s r,s r,s是 R , S R,S R,S上的关系,有
R = ( A 1 , ⋯ , A m , B 1 , ⋯ , B n ) R=(A_1,\cdots,A_m,B_1,\cdots,B_n) R=(A1,⋯,Am,B1,⋯,Bn)S = ( B 1 , ⋯ , B n ) S=(B_1,\cdots,B_n) S=(B1,⋯,Bn)
则 r ÷ s r\div s r÷s的结果是表 R − S = ( A 1 , ⋯ , A m ) R-S=(A_1,\cdots,A_m) R−S=(A1,⋯,Am)上的一个关系,且
r ÷ s = { t ∣ t ∈ Π R − S ( r ) ∧ ∀ u ∈ s ( t u ∈ r ) } = Π R − S ( r ) − Π R − S ( ( Π R − S ( r ) × s ) − Π R − S ( r ) ) r\div s=\{t|t\in \Pi_{R-S}(r)\wedge \forall u\in s(tu\in r)\}=\Pi_{R-S}(r)-\Pi_{R-S}((\Pi_{R-S}(r)\times s)-\Pi_{R-S}(r)) r÷s={t∣t∈ΠR−S(r)∧∀u∈s(tu∈r)}=ΠR−S(r)−ΠR−S((ΠR−S(r)×s)−ΠR−S(r))
类似笛卡尔积的逆运算,即结果和 s s s做笛卡尔积,可以得到 r r r中的对应元素
-
赋值 ← \leftarrow ←
就是赋值,例如, r ÷ s : r\div s: r÷s:
t e m p 1 ← Π R − S ( r ) t e m p 2 ← Π R − S ( ( t e m p 1 × s ) − Π R − S ( r ) ) r e s u l t = t e m p 1 − t e m p 2 temp_1 \leftarrow \Pi_{R-S}(r)\\ temp_2\leftarrow \Pi_{R-S}((temp_1\times s)-\Pi_{R-S}(r))\\ result = temp_1-temp_2 temp1←ΠR−S(r)temp2←ΠR−S((temp1×s)−ΠR−S(r))result=temp1−temp2 -
广义投影
形如 Π F 1 , F 2 , ⋯ , F n ( E ) \Pi_{F_1,F_2,\cdots,F_n}(E) ΠF1,F2,⋯,Fn(E),其中 E E E是任何关系运算表达式, F i F_i Fi是一个算术表达式可包含常量和 E E E中的属性。
例如: Π c u s t o m e r _ n a m e , l i m i t − c r e d i t _ b a l a n c e ( c r e d i t _ i n f o ) \Pi_{customer\_name,limit-credit\_balance}(credit\_info) Πcustomer_name,limit−credit_balance(credit_info)
-
聚合函数
几个常用的函数:
— avg:平均值
— min:最小值
— max:最大值
— sum:求和
— count:值的个数
形如 G 1 , G 2 , ⋯ , G n g G_1,G_2,\cdots,G_n\Large g G1,G2,⋯,Gng F 1 ( A 1 ) , F 2 ( A 2 ) ⋯ F n ( A n ) ( E ) F_1(A_1),F_2(A_2)\cdots F_n(A_n)(E) F1(A1),F2(A2)⋯Fn(An)(E),其中 E E E是任何关系代数表达式, G G G表示一系列属性(组合,可为空), F F F是聚合函数, A A A代表属性名字
例如:
branch_name account-number balance Perryidge A-102 400 Perryidge A-201 900 Brighton A-217 750 Brighton A-215 750 Redwood A-222 700 则 b r a n c h _ n a m e g s u m ( b a l a n c e ) ( a c c o u n t ) branch\_name\ {\large g}\ _{sum(balance)}(account) branch_name g sum(balance)(account)为
branch_name balance Perryidge 1300 Brighton 1500 Redwood 700
注意:所有查询的输入输出都是一系列表,所有在输出的表中的数据都至少在一个输入的表中。
Query E.g:
1.找最大数(银行存款account 为例)
Π b a l a n c e ( a c c o u n t ) − Π a c c o u n t . b a l a n c e ( σ a c c o u n t . b a l a n c e < d . b a l a n c e ( a c c o u n t × ρ d ( a c c o u n t ) ) ) \Pi_{balance}(account)-\Pi_{account.balance}(\sigma_{account.balance<d.balance}(account\times \rho_d(account))) Πbalance(account)−Πaccount.balance(σaccount.balance<d.balance(account×ρd(account)))
就是先把account两两拼起来,然后取所有小的,然后减去,就是最大的。
2.找到所有至少在“Downtown”和“Uptown”分行拥有账户的客户
Π c u s t o m e r _ n a m e , b r a n c h _ n a m e ( d e p o s i t o r ⋈ a c c o u n t ) ÷ ρ t e m p ( b r a n c h _ n a m e ) ( { ( " D o w n t o w n " ) , ( " U p t o w n " ) } ) \Pi_{customer\_name,branch\_name}(depositor\Join account)\div\rho_{temp}(branch\_name)(\{("Downtown"),("Uptown")\}) Πcustomer_name,branch_name(depositor⋈account)÷ρtemp(branch_name)({("Downtown"),("Uptown")})
就是先对两个表格进行自然连接,然后只取客户名字和分行名字,最后除掉对应的两个分行,根据除法的定义,最后的结果就是对应的客户名称,或
Π C N ( σ B N = " D o w n t o w n " ( d e p o s i t o r ⋈ a c c o u n t ) ) ∩ Π C N ( σ B N = " U p t o w n " ( d e p o s i t o r ⋈ a c c o u n t ) ) \Pi_{CN}(\sigma_{BN="Downtown"}(depositor\Join account))\cap \Pi_{CN}(\sigma_{BN="Uptown"}(depositor\Join account)) ΠCN(σBN="Downtown"(depositor⋈account))∩ΠCN(σBN="Uptown"(depositor⋈account))
容易理解的,就是分别取在“Downtown”和“Uptown”中有账户的客户,再取交集
7