关系模型
关系模型和对象关系模型是这门课的重点。
CAP数据库
之所以叫做CAP数据库是因为这是关系模型的一个经典例子,customers, agents, products以及订单表构成的数据库。
数据库术语
术语对应关系
关系模型 | 数据库 |
---|---|
relation | table |
attribute | column |
tuple | row |
schema | table heading |
- 数据库:表的集合
- 数据独立性:数据库程序中的查询语句与表的内容无关,仅与列有关。
- 列类型:指的是某一列中存放的数据的数据类型。对数据进行比较的时候,必须确保列类型是一致的。
- Domain域:指的是一列中的数据的取值范围。
- 笛卡尔乘积:类似于离散数学中集合与集合的笛卡尔积,所有关系都是笛卡尔积的子集。
关系规则
- 第一范式规则。即一行某一列不能有多值域。表格中的每一个方格内都必须是单一元素,不能出现某一行的一个属性处有多个属性对应。
- 唯一性规则:即表中不能有两个完全相同的行。因为表的所有行应该构成集合。
- 只能根据内容存取行的内容:这一个规则包含两点:既不能通过索引来访问行,比如不能直接说要访问第三行,因为行之间都是并列的,不存在顺序的先后关系;也不能在程序中构建相应的指针指向特定的行,来方便后续的访问。
键,超键,空值
键:是可以唯一区分每一行的属性集合,包含至少一个属性。
超键:包含某个键的属性的集合。
概念辨析:键一定是超键,如果一个超键的属性集合中不能找到更小的真子集也能唯一确定某一行,则这个超键是键。
举例:
A | B | C | D |
---|---|---|---|
a1 | b1 | c1 | d1 |
a1 | b2 | c2 | d1 |
a2 | b2 | c1 | d1 |
a2 | b1 | c2 | d1 |
上面的这个表格中,ABCD分别是该表格的四个不同的属性。可以看出,这个表格中并不存在那个属性可以自己单独作为键出现,因为ABCD属性下的属性在所有行中都有重复出现的属性。
但是我们仍然可以找到一些组合起来的属性构成的键:AB,BC,AC就是三个键。同时他们也是超键。但是其他的超键,像ABC,ABD,ACD,BCD就仅仅是超键,因为我们能够找到他们还有一些真子集的组合也能区分每一行。
空值,出现在还未确定的属性处。如果这个属性是表格制定者规定的主要键,那么这一个行还暂时不能填入表格。
候选键,主键
候选键:由数据库管理员定义的键为候选键
主键:被数据库设计者指定的候选键,具有以下特征:
- 作为该表中行的唯一标识符,如cid
- 这个标识符通常作为其他表对这个表中行的引用,如在Orders表中通过cid引用Customers
定理:每个表都至少有一个键。
空值
未知或尚未定义的属性处使用空值。空值往往被特殊处理,而且不参与通常的数据筛选。
空值所在的行,不会被任何查询表格的函数返回。
实体完整性:表T的所有行在主键列都不允许为空值。
关系代数
储存在表中的信息在关系代数的作用下得到表形式的查询结果。
关系代数分为两类操作:集合论的运算和自然关系的运算。
集合论运算
相容表
又叫做兼容表。如果表R和表S具有相同的表头,即Head(R)=Head(S)(与属性列排列的顺序无关),而且所有的属性具有相同的域(Domain)和相同的含义,那么就称R和S相容(兼容)。
相容的条件是:
- 两个表有相同的列数
- 每个表中的任意列,在另外一张表中能找到具有相同含义的列。换句话说,有相同名称的列。
- 上述一对列具有相同的域(字符、整数等)
并,交差运算
仅当两个表相容的时候才可以进行并和交和差运算。相当于对两个表行的集合进行集合运算。其中交运算可以用并和差进行替代表示。
赋值
又叫做别名。
对于表R,Head(R)={A1,A2,…,An}。现在定义一个新表S,Head(S)={B1,B2,…,Bn},表头属性列可以与R相同也可以不同,但是属性列的含义和域和R的列对应相同。同时S的所有内容和R完全相同。这时可以把构建S的行为成为赋值,用:=表示。
换句话说,就是给表起一个新的名字。这种方法可以更为方便地表示计算的中间结果。
例如:T:=R-S
乘积
以两张任意的表的列并列排列(注意:即使存在相同的属性也全部予以保留),得到一张新表。将原来两张表的所有行按照求笛卡尔积的方式组合形成新表的行。新表称为原来两张表的乘积。
如果R有Cr列,S有Cs列,那么R*S有(Cr+Cs)列。
如果R有Nr行,S有Ns行,那么R*S有(Nr*Ns)行。
自然关系运算
投影π 选择δ 连接∞ 除法÷
投影
记为R[Ai1,Ai2,…,Ain],其中这些是R中存在的列。也可以记作πAi1,…,Ain(R)
作用是只保留这些列,将原来的表精简成一个新的表。用于筛选列。
注意:投影结果相同的行将只保留一个。
选择
记作S where c 或者 δc(S),其中c为选择行的条件。用于筛选出满足条件的行组成新表。
关于筛选条件:既可以是行中两个属性之间的关系,也可以是行的一个属性和给定常数之间的关系。比如我们可以筛选出学生表中“家庭地址”和“上学地址”两个属性相同的行,也可以筛选出“家庭地址”是“北京”的行。不仅如此,条件之间也可以通过逻辑运算与或非组成新的条件。
所有查询都应该在不知道表的内容时达到能给出正确结果的要求,要避免查询指令形成内容依赖,否则在表的内容发生变化时,有可能出现意外。
连接运算∞
连接运算定义为:
如果有两个表R和S,Head(R)={A1,…,An,B1,…,Bn}, Head(S)={B1,…,Bn,C1,…,Cn},那么T:=(R∞S),则Head(T)={A1,…,An,B1,…,Bn,C1,…Cn}。T的行直观来看,就是将R和S中共有属性都完全一样的行挑出来相互组合连接而成,新的行在共有部分的属性和他的两个来源相同,而只存在R或S其中一个表的属性则继承来自那个表的行的属性。
例如:
R:
A | B1 | B2 |
---|---|---|
a1 | b1 | b1 |
a1 | b2 | b1 |
a2 | b1 | b2 |
S:
B1 | B2 | C |
---|---|---|
b1 | b1 | c1 |
b1 | b1 | c2 |
b1 | b2 | c3 |
b2 | b2 | c4 |
那么R∞C的计算如下:
先找到R和S共有的属性:B1和B2。然后比较两个表格中的B1,B2找到属性相同的行对:R的第一行和S的第一和第二行B1,B2属性一致,所以分别合并R的第一行和S的第一行,以及R的第一行和S的第二行,得到结果中的两个行。然后发现R中的第三行和S中的第三行也有相同的B1,B2属性,就将这一对也合并,得到结果的第三行。
R∞S:
A | B1 | B2 | C |
---|---|---|---|
a1 | b1 | b1 | c1 |
a1 | b1 | b1 | c2 |
a2 | b1 | b2 | c3 |
乘法和连接运算都符合交换律和结合律。
除法运算÷
有两个表R和S,除法的定义是:
R÷S,则能运算的条件是Head(S)是Head(R)的子集。T:=R÷S则Head(T)=Head(R)-Head(S)。T中的列:属于R但不属于S的列。T中的行这样得到:对S中的每个行,在R中找到和他们分别具有相同属性的行的集合,并且只留下这些行中属于T的列,然后对所有这些行的集合取交集,也就是挑出一致的那些作为T的行。
例如:R:
A | B | C |
---|---|---|
a1 | b1 | c1 |
a2 | b1 | c1 |
a1 | b2 | c1 |
a1 | b2 | c2 |
a2 | b1 | c2 |
a1 | b2 | c3 |
a1 | b2 | c4 |
a1 | b1 | c5 |
S:
C |
---|
c1 |
c2 |
那么计算R÷S的时候,先找出R中与S第一行属性一致的行,即第1,2,3行。找到与S中第二行属性一致的行,即第4,5行。然后不考虑C属性,发现{a1,b2}和{a2,b1}都有出现在这两个集合的行中,所以这是结果中的两行。
R÷S:
A | B |
---|---|
a1 | b2 |
a2 | b1 |
除法和乘法(笛卡尔积)的关系:
如果 T=R*S 那么 R=T÷S, S=T÷R。
如果 T=R÷S 那么 T*S是R的子集。
除法的意义在于,很容易找到诸如“买了所有产品的顾客cid”等有关“所有”的问题的答案。
优先级
综合集合论运算和自然关系运算,给如以下从高到低的运算优先级:
- 投影
- 选择
- 乘积
- 联结,除法
- 交
- 并,差
复杂查询
要做好复杂查询,就要综合运用所有这些集合运算和自然关系运算。主要讲解了一些例题,不再赘述。
关系运算技巧
“不是”,“仅”
带这个关键词的题目,很多可以用差操作简化和解决。
例如:仅提供p02商品的代理商的aid,那么可以在Order表中找到所有代理过其他商品的代理商aid,然后用所有出现过的aid减去这个结果即可。
“并且”,“或者”
带这个关键词的通常会用到并,交操作。
“所有”
带这个关键词的有时候会用到除法操作。例如求参加过所有项目的员工。
“两个及以上”
比如说求参加过两个及以上项目的员工,就可以通过自己和自己笛卡尔积,再筛选出员工号相等但是项目号不等的行,这些行中的员工就参与了多个项目。同理,这个结果再做差可以求得“仅一个”的。
妙用连接操作
连接操作不仅能够实现跨表格的信息沟通,还能用来在一个表格中筛选出“某个属性符合几个选择之一”的行,类似python中in关键词的感觉。例如筛选出客户ID为a01、a02或a03的订单,可以用订单表和仅有这三个aid属性的表进行连接得到。连接操作也可以当做一种选择来使用。
避免连接操作
有些时候一些看起来能用连接操作的,实际上不能使用。比如两张表中有两列虽然意义相同但是列名不同,不能直接连接。可以使用先笛卡尔积再选择出列值相同的行,起到连接相同的作用,避免无法进行的连接。
求最值的技巧
一般可以分为三步(以查询有最大折扣的客户为例):
- 找到所有客户的aid,即R1:=C[cid].
- 找到那些折扣比任何一个其他的客户小的客户(这种客户的折扣一定不是最大)。可以通过和自己的笛卡尔积加上选择运算实现。S:=C; R2:=((C*S)where C.discnt<S.discnt)[C.cid];
- 用所有客户减去2中运算得到的客户。就找到了:折扣大于等于所有客户的客户,即最大折扣的客户。T:=R1-R2.
其他关系运算
外连接,左外连接,右外连接,笛卡尔连接
在R∞S中:
左外连接是指,选取R的所有行,和S进行连接。对于一个R中的行,如果在S中能够找到有相同公共属性的行,那么正常连接两行。否则,用Null空值填充S中特有的属性来构建结果的行。左外连接的结果中可以重构出R整张表。
右外连接指的是选S的行和R进行连接,和左外连接类似。右外连接的结果中可以重构出S整张表。
外连接则是左外连接和右外连接的并集,外连接的结果中可以构建R和S。也叫作全外连接。
笛卡尔连接:其实就是笛卡尔积。
θ连接
连接带有一个选择条件。
其实就完全等同于先对两个表做笛卡尔积然后使用这个条件对结果再进行行的选择。