Ch1 数据库系统概论

原目录:数据库系统概论

查看语雀原文

数据库系统概论.xmind




Ch2 关系模型

原目录:数据库系统概论

查看语雀原文

1. 基本结构

  • 属性(attribute):数据表列
  • 元组(tuple):数据表行
  • 域(domin):属性允许的取值集合



2. 数据库模式⭐

对比一般语言和SQL:

  • 关系-->变量
  • 关系模式(relation schema)-->变量类型
  • 关系实例-->变量的值

代数角度理解:

属性:

关系模式:

:

关系r为域笛卡尔积子集:

关系实例由当前实际数据表决定

大学数据库的department表为例

属性

dept_name, building, budget

关系模式

department(dept_name, building, budget)

关系实例



3. 数据表理论性质

image.png



4. 关系查询语言

(Relational Query Languages)

元组选择

列选择

笛卡尔积

并运算

差运算

交运算

自然连接

除运算⭐

参考链接: 关系代数中的除法运算

R÷S,RX的每个x对应像集Y包含S中Y属性的所有值


Ch3/4/6 SQL & 关系代数

原目录:数据库系统概论

查看语雀原文

SQL

1. 基本查询结构


image.png

尽管典型的查询语句为SFW顺序,真正的理解顺序:

  1. from:对m个关系求笛卡尔积,产生候选元组集合
  2. where:依据谓词P对候选元组选择,只有使P为true时,将元组t加入结果关系(当省略P时,P默认为true)
  3. select:对结果关系进行指定属性的投影

2. 附加的基本运算

更多见: mid-term _Review

字符串操作

结果排序



3. 聚集函数⭐

基本

SQL提供五个基本聚集函数:

  • avg
  • max
  • min
  • sum
  • count

聚集函数不能直接出现在where语句中(可以在嵌套查询中使用):where salary > max(salary)

group by

group by语句通常使用在聚集函数后,对查询结果进行分组

  • 出现在select子句后的非聚集函数属性必须也在group by后出现,但group by后的属性不必都在select后出现

having

having通常在group by使用,非单独子句,用于筛选分组结果


4. 嵌套子查询

(Nested Subqueries)

4.1 嵌套查询

in/

not in

先进行内查询,将结果视为集合常量与外表连接,再进行外查询

exists/

not exists

外表元组集合做for循环,依次带入内表查询,查询结果非空时返回true

相关子查询
(correlated)

当外层的查询名称可以用在where子句的查询中,称为相关子查询

4.2 集合比较

some

至少有一个满足就成立

  • =some等价于in
  • <>some不等价于not in,不存在逻辑关系

all

 

 

 

 

所有都要满足

  • =all不等价于in
  • 当子句是标量子查询(scalar subquery),当一般等号使用
  • 当子句返回集合,=all()的结果集为NULL
  • <>等价于not in

最值问题

  • 使用>=all()<=all()进行内外查询比较
  • 内查询使用max()/min()找出最值,外查询使用=比对

with子句

with提供了定义临时关系的方法,当嵌套查询过于复杂时,可提前使用with在查询开始定义关系

4.3 集合包含问题⭐

(空关系测试)

使用not exitst语句测试子查询结果集中是否不存在元组:

\(\\ \begin{align} &\quad关系A包含关系B\\ &\Rightarrow B\subseteq A\\ &\Rightarrow B-A= \varnothing\\ &\Rightarrow not \ exists(B\ except\ A) \end{align}\)


image.png

5. 数据库修改

5.1 删除

  • 标准语句:
delete from where
  • 关于delete执行顺序:
delete from instructor
where salary < (select avg(salary) from instructor);

执行中,avg(salary)在delete元组前就已经计算得到,不会因为删除和查询同时对于instructor而冲突

5.2 插入

  • 标准语句:
// 形式一:自行输入插入数据
insert into table T values (r1, r2, r3);

// 形式二:从已有数据中选取插入数据 insert into table T select r1, r2, r3 from B;

5.3 更新

  • 标准语句
update T set r1 = r1';

image.png



6. 连接表达式

6.1 连接

连接类型

连接条件

  • 内连接inner join: 最常用,默认的常规连接
  • 左外连接left outer join: 对左侧失配字段,右侧用null填充
  • 右外连接right outer join: 对右侧失配字段, 左侧用null填充
  • 全外联结full outer join: 对两侧失配字段都保留
  • 自然连接 natural join:认对共有字段连接,重复字段只显示一次,失配字段丢失
  • 条件连接 on:条件复杂时,using可接限制子句
  • 条件连接 using:条件简单时,可能是指定某同名属性

例题

给定关系

自然()连接:course natural join prereq中左侧CS-315发生失配,要想不丢掉数据,需要使用:

course left outer join prereq on

course.course_id = prereq.course_id

image.png

6.2 连续连接

在SQL中,from语句允许一般化为以下格式

select A1, A2 … An
from E1, E2, … ,En
where P;

其中Ei可以是单独关系模式R,也可以是自然连接语句,R1 natural join R2, 因此SQL中from中可以有三种搭配:

  • 纯笛卡尔积: from R1, R2, R3
  • 纯自然连接: from R1 natural join R2 natural join R3
  • 混合: from R1 natural join R2, R3(不推荐)

但是对于给定关系模式,不同的连接结果可能不同,给定

  • course(course_id, title, dept_name, credits)
  • instructor(ID, name, dept_name ,salary)
  • teaches(ID, course_id, sec_id, semester, year)

有以下两种选择:

// 1
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
natural join course;

结果不同,intructor与teaches自然连接后--(ID, name, dept_name, salary, course_id, sec_id, semester, year)

  • 如果与course自然连接,需要满足属性集(course_id, dept_name)的完全匹配(不能只有一个属性相等)
  • 如果使用where限定的笛卡尔积只用满足course_id上的相等即可被选出

因此,推荐使用using或者on语句,避免了自然连接与笛卡尔积混用,又保证了选择的有效性:

select name, title
from instructor natural join teaches join course using(course_id);



关系代数

1. 基本运算

参考链接: Ch2 关系查询语言

选择运算

对应语句where,用于选择元组,谓词可使用and(∩),or(∪),not(∽)合并

符号:小写sigma:σ

投影运算

对应语句select,用于列选择

符号:大写pi: Π

集合并

对应操作select r from T and select s from T

符号:Π1+Π2

为了使r∪s有意义:

  • rs同元,即属性数目相同
  • rs的属性域对应相同

集合差

对应操作select r from T except select s from T

符号:Π1-Π2

r-s意义:包含在r但不包含在s中的关系,有意义的条件和集合并相同

⭐笛卡尔积

对应语句select r from T, S

符号:Π(σ(T×S))
区分笛卡尔积和连接,如果使用join代替","就成了连接,非笛卡尔积

更名

对应语句E as x,x赋给表达式E做别名
符号:小写rho:ρx(E)



2. 附加运算

集合交

对应查询:找出既在2009秋开设也在2010年春开设的课程
符号:Π1∩Π2
关系代数表达式中没法直接实现交运算,而是使用r∩s=r-(r-s),∩只是方便表达,

自然连接

对应语句:natural join

符号:σ(rs)

当r与s没有任何相同属性时,rs=r×s

theta连接⭐

对应语句:join on

自然连接的扩展,可以将选择运算和笛卡尔积合并,考虑关系r(R)和s(S),设θ是R∪S属性上谓词,则

聚集函数

&

分组

  • 对于聚集函数,使用表示
  • 当考虑到避免重复时,使用count-distinct()
  • select后除聚集函数外的属性都要出现在group,因此遇到分组时,省略Π投影,直接将属性写在前面(参考上图)

Π投影选择需要的属性(),当不进行Π投影,表示属性全选,即整个元组,不要过分纠结于Π投影和G的内外,具体情况具体分析,比如某地当需要count(course_id)>5时的student_id,此时Π就需要在G外侧再次选择一次student_id,否则结果元组会带着count属性

除法运算

对应查询:集合包含问题
符号:σ(rs)

参考链接: 关系代数中的除法运算

S,RX的每个x对应的像集Y包含S中Y属性的所有值


mid-term _Review

原目录:数据库系统概论 / Ch3/4/6 SQL & 关系代数

查看语雀原文

复习题


week4(大学数据库)


第七题: Find the sections that had the maximum enrollment in Fall 2009.


--写法一
select sec_id
from takes
where semester = 'Fall' and year = 2009
group by sec_id
having count(ID) >= all (select count(ID)
                    from takes
                    where semester = 'Fall' and year = 2009
                    group by sec_id);

--写法二
select sec_id
from takes
where semester = 'Fall' and year = 2009
group by sec_id
having count(ID) = (select max(count)
                    from takes
                    where semester = 'Fall' and year = 2009
                    group by count(distinct sec_id));


集合比较


  • some:至少有一个满足
  • =some 等价于in
  • <>some 不等价于not in
  • all:所有都要满足
  • =all 不等价于in
  • 当子句是标量子查询(scalar subquery),相当于一般等号
  • 当子句返回集合,=all()的结果集为NULL
  • <>all 等价于not in


处理与最值有关的问题


  • 使用>=all()或<=all()进行内外查询的比较
  • 内查询使用max()/min()找出最值,外查询使用=比对

week5


第六题:Find the name and the SSN of everyone who works on all projects that his deparment is responsible for them.


select name, SSN
from employee as T
where not exists
(select pno
from project natural join department
where T.dno == department.dno)
except
(select pno
from (employee natural join hourlog) as S 
where T.ssn = S.ssn);


集合包含问题:A:某人从事的项目,B:其部门负责的项目,要求B包含于A->B-A=Ø

关系代数


\(\Pi_{name, ssn}((\Pi_{ssn,pno}(employee \bowtie hourlog)\div\Pi_{pno}(project \bowtie department))\bowtie employee) \)


含义:参考链接:https://www.cnblogs.com/yuanqi/p/4589967.html, R÷S表示R中每个X对应像集Y包含S中像集Y的所有值,本题RS÷S表示每个X,Y对应像集Z(x,y)中包含S中像集Y的所有值,


week6(大学数据库)


1(b):Delete all courses that have never been offered (that is, do not occur in the section relation).


delete from course
where course_id not in 
(select course_id
from course natural join section);


关于集合成员资格:

参考链接:https://blog.csdn.net/baidu_37107022/article/details/77278381


  • in/not in:先进行内查询,将结果集合与外表连接从而判断资格
  • 适合外表大,内表小的情况
  • 不适合内表记录有NULL情况,当内表结果有NULL时,内查询不返回记录
  • exists/not exists:对外表元组循环,带入内表查询


1(f):Enroll every student in the Comp. Sci. department in the section in Fall 2009, with sec_id of 1.


insert into takes
(select id, 'CS-001' as course_id,  '1' as sec_id, 'Fall' as semester, '2009' as year
from student 
where dept_name = 'Comp.Sci.');


两种insert


  • insert into table values(...):适合手动填充数据
  • insert into table select (...):适合填充查询后数据


1(i):Delete all takes tuples corresponding to any section of any course with the word "database" as a part of the title; ignore case when matching the word with the title.


delete from takes
where course_id in (select course_id
                    from course
                    where title like "%database%" or title like "Database");


模糊查找:like


  • postgreSQL使用ilike进行不区分大小写的模糊查找
  • 字符串处理:
  • "intro%":以intro开头
  • "%body%":字符串中含有body
  • "---":字符串长度为3
  • "---%":字符串长度至少为3

week7


1(1):查询书名中有“%”的书目信息


select *
from title
where name like "%\%%";


sql使用"\"作为转义符号


1(11):查询借阅图书本数超过2本的读者的读者号及借阅本数。


select memno, count(distinct book_id)
from member join book on borrowermemno = memno
group by memno
having count(distinct book_id) > 2;


关系代数


\(_{memno,}\mathcal{G}_{count\_disinct(book_id)>2}(\sigma_{borrowermemno = memno}(member \times book )) \)


或者theta连接


\(_{memno,}\mathcal{G}_{count\_disinct(book_id)>2}(member \bowtie_{borrowermemno = memno} book ) \)


2(1):按借阅图书本数,从高到低列出读者的姓名及其借阅本数。


select fname, count(callnumber)
from member join book on borrowermemno = memno
group by memno
order by count(callnumber) desc


结果排序:


  • 降序:order by ... desc
  • 升序:order by ... asc


2(2):查询借阅了123号读者和124号读者所借所有书目的读者的编号及姓名。


select memno, fname
from member as M
where not exists
(select memno
from member join book on borrowermemno = memno
where memno = 123 or memno = 124)
except
(select memno
from (member join book on borrowermemno = memno) as T
where M.memno = T.memno);


集合包含问题:A:123和124所有所有图书,B:某人所借所有图书,要求A包含于B,A-B=Ø

or的使用:前后需要为完整的boolean值,不能使用where memno = 123 or 124where memno = (123 or 124)


2(4):124号读者续借124号图书,请将预约归还日期延后一个月。


update book
set borrowerduedate = borrowduedate + interval '1 Month'
where book_id = 124;


postgreSQL时间间隔:使用interval关键字,可使用hour,month,minute等作为单位,参考链接:https://blog.csdn.net/zacry/article/details/42742509


2(5):读者归还了124号图书,请修改其状态。


update book
set borrowermemno = null, borrowduedate = null
where book_id = 124;

Ch7 E-R模型

原目录:数据库系统概论

查看语雀原文

1. E-R模型

image.png

  • 弱实体集

有时联系集是冗余的,但删除后又无法凸显联系,只好在某个实体集中删除属性,但剩余属性不足以标识唯一指定的实体,必须依赖于一个强实体集,将其主键作为外键,并与弱实体集合的分辨符组成一组属性作为弱实体集主键

大学数据库为例

实体

学生Shankar

弱实体集

实体集

所有学生

section

依赖的强实体集为course

分辨符sec_id, semester,year

联系

教师Katz和学生Shankar的联系advisor(导师)

联系集

instructor和student中的advisor关联



2. 约束

image.png


3. E-R图

image.png

  • 非二元联系

当联系集有不止一个箭头时

image.png

大学数据库为例

一对多关系

联系集上的基数约束

  • 错误理解:由图为instructor——>student,instructorstudent的多对一联系
  • 正确理解:一个student能参与一次advisor联系,一个instructor可参与多次,实际上是instructor<——student

弱实体集

复杂属性

  • composite attributes
  • name
  • address
  • street
  • multivalued attributes
  • phone_number
  • derived attributes
  • age()

角色(联系)

course ab的前置课,b是c的前置课,此时b具有两个角色

非二元联系

大学数据库完整ER图

image.png



4. E-R图->关系模式

转换.png


简单属性强实体集

student(ID, name, tot_cred)

复杂属性强实体集

instructor(ID, first_name, middle_initial, last_name

, street_number, street_name, apt_number, city, state, zip, date_of_birth)

只表示复合属性的子属性

不显式表示派生属性(函数)

为多值属性单独创建模式

多值属性

instructor_phone(ID, phone_number)
ID为多值属性所在关系模式的主码

弱实体集

section(ID, sec_id, semester, year[虚线])

联系集

角色: prereq(course_id, prereq_id)(多对多)

关系模式中对外码没有明确的标注, 但默认联系集中来自某一个实体主码的属性就是参照该实体的外码

弱实体集周围: teaches(ID, course_id, sec_id, semester, year)(多对多)



5. 关系模式的冗余

冗余&合并.png

合并举例

  • 双横线:表示全部参与
  • instructor和inst_dept合并
  • (ID, name, salary)=>(ID, name, salary, dept_name)
  • student和stud_dept合并
  • (ID, name, tot_cred)=>(ID, name, tot_cred, dept_name)



6. 设计问题

设计问题.png

设计举例

比较takes联系集和注册信息registration实体集

虽然registration集合也准确记录了信息,但略显冗余.
"学生上课",takes是直接发生于两个实体集间的关系,使用联系集更紧凑



7. 其他特性

其他特性.png

特化概化

聚集



8. E-R图标识总结

  • 实体集&联系集

image.png

  • 集合属性

image.png

  • 映射基数&概化特化

image.png

  • 其余可选表示

image.png

image.png


E-R建模例题

原目录:数据库系统概论 / Ch7 E-R模型

查看语雀原文

例1

image.png

E-R图

  • 箭头法标识实体在联系中可联系的另一个实体个数
  • 数字法标识实体在联系中可参与的次数

一种材料只能由一家提供,一家可提供多种材料,因此:

  • 箭头如图
  • 数字:Material 1..1 Supplier 0 .. *

关系模式: 实体集 联系集 弱实体集 外码参照

Project (ID, name, money, class, start_time, end_time)

Employee (ID, name, gender, title, birthday)

Takes (Employee_ID, Project_ID)[Employee_ID, Project_ID分别参照Employee, Project]

Manager (ID, name, gender, title, birthday)

Manages (Manager_ID, Project_ID) [Manager_ID, Project_ID分别参照Manager, Project]

Material (ID, name, kind, price)

uses (Project_ID, Material_ID) [Project_ID, Material_ID分别参照Employee, Project]

Supplier (Material_ID, name, phone, city)

根据 弱实体集 :

supplier没有足够的属性表示唯一的供应商实体,即使每个supplier都唯一,不同material实体也会有相同的供应商实体,此时将supplies视为特使的联系集,只提供唯一标识Supplier实体的Material_ID,即弱实体集



例2

image.png

E-R

关系模式: 实体集 联系集 弱实体集 外码参照

brand (id, name, country)

model (id, name, price)

option (id, name, price)

car (VIN, price)

dealer (id, name)

customer (id, name)

belong (brand_id, model_id) [外码brand_id, model_id参照brand, model]

manufactured (VIN, model_id, option_id, time) [外码model_id, option_id参照model, option]

sell (dealer_id, VIN, time) [外码dealer_id参照dealer]

purchase (customer_id, VIN, time) [外码customer_id参照customer]


Ch8 关系数据库设计

原目录:数据库系统概论

查看语雀原文

1. 好的关系设计

1.1 函数依赖

(functional dependency)

前提:关系模式的表示法

  • 使用希腊字母表示属性集(α,β...)
  • 使用大小写组合指示关系模式(r(R)),此时r表示关系r,R表示属性集合,当关系名称不重要时,只用R
  • 如employee(id, name),简化(id, name)
  • 当属性集是超码(一个或多个属性的集合,课区分唯一实体),用K表示,K是r(R)的超码
  • 有时关系或关系的实例可仅用小写字母表示,如r

场景:分析关系模式

给定关系inst_dept

image.png

  • 如果此时要求:每个系对应一个预算
  • 需要:设计者在dept_name非当前模式主码情况下也能规定"一个dept_name对应一个budget"
  • 等价于:如果有模式(dept_name, budget),则dept_name可以做主码,表示如下,即为函数依赖

\(dept\_name \rightarrow budget\\\)

  • 通过该依赖可以发现inst_dept关系产生了大量重复记录,需要拆分为instructor, departmet

函数依赖

给定r(R)的实例,当实例满足函数依赖α->β的条件:
实例中所有元组对t1t2,t1[α]=t2[α],t1[β]=t2[β]

作用

函数依赖帮助设计者发现模式是否冗余,需要拆分

个人理解

函数依赖是关系模式中属性或属性集间需要遵循的约束,由函数的角度可以视为不同属性间的映射f:α->β,函数具有单值的性质,函数依赖也类似,不允许出现在R中属性集α可以对应多个β

1.2 关系模式的分解

  • 给定关系模式:

employee(ID, name, street, city, salary) 按左图分解,右侧关系中可以知道某个(street, city, salary)下有个Kim,对于某大学中两个Kim,自然连接后产生4个结果,无法确定哪个是有意义的,称为有损分解

  • 分解:
  • 有损分解: lossy decomposition
  • 无损分解: lossless decomposition



2. 原子域和第一范式

(atomic domain & first normal form)

参考链接: 范式理解与判断

概念引入:设计者根据函数依赖和其他数据依赖定义范式,再通过设计满足适当范式的模式来避免关系模式的冗余

函数依赖/数据依赖---->设计范式---->避免冗余

原子域

关系模式中,域指属性可取值的集合,而原子域的元素都是不可分的单元

第一范式

关系模式R的所有属性的域都是原子的

非原子域
非第一范式

employee(id, name, children)中children是多值属性,children取值可分,则关系具有非原子域,模式不属于第一范式



3. 使用函数依赖分解

3.1 码和函数依赖

函数依赖定义超码

如果函数依赖K->R在r(R)上成立,Kr(R)超码:

对在r(R)的每个合法实例,实例中的每个元组对t1,t2,t1[K]=t2[K]总有t1[R]=t2[R](t1=t2),K是一个超码

函数依赖表示无法用超码表示的约束

对前文inst_dept(ID, name, salary, dept_name, building, budget)要求dept_name->budget成立,
(ID, dept_name)构成inst_dept的一个超码,记为

ID, dept_name->name, salary, building, budget

3.2 函数依赖的使用

  • 判定关系的实例是否满足给定函数依赖集F(被多个函数依赖约束)
  • 说明合法关系集上的约束

举例

左侧关系r下:
满足函数依赖A->C
不满足函数依赖C->A

平凡(trivial)依赖:在所有关系都满足的依赖
如:A->
A,AB->A
若βα,则形如α->β的都是平凡依赖

依赖闭包(closure):集合闭包F+是根据F可推导出的所有函数依赖

:给定r(A,B,C)F:A->B,B->Cr上成立,A->C一定成立,此时A->B,B->C,A->C共同构成F+

3.3 BC范式

(BCNF-Boyce-Codd Normal Form)

BCNF

具有函数依赖集F的关系模式R属于BCNF的条件:F+中所有形如α->β的函数依赖R且βR),下面至少一项成立

  • α->β是平凡依赖α)
  • α是模式R的一个超码

一个数据库设计属于BCNF的条件即设计的关系模式集中每个模式都属于BCNF

举例

inst_deptBCNF,设计时要求"-办公楼和预算"一一对应 inst_dept(ID, name, salary, dept_name, building, budget)F+中有dept_name->budget, building,dept_name本身非超码,因此模式中有冗余,需要拆分为instructor, department
这两个关系是BCNF:因为设计要求的F+中α->β形依赖,除去平凡依赖,其余α都是超码:

dept_name->budget, building

非BCNF分解⭐

设R为非BCNF的一个模式,即存在至少一个非平凡α->β,使用以下两种模式取代R:

  • (α∪β),eg:(dept_name, budget, building)
  • (R-(β-α)),eg:(ID, name, dept_name, salary)

分解非BCNF后,产生的子模式可能依旧有一个或多个非BCNF,需要继续分解,最终结果为BCNF模式集合


4. 第三范式

4.1 BCNF的局限

给定以下联系集

image.png

要求

  • 一个教师只能在一个系担任教师
  • 给定一个系,一个学生最多一个导师

依赖

对应dept_advisor(s_id, i_id, dept_name)一定有以下函数依赖

  • 依赖一: i_id->dept_name
  • 依赖二: dept_name, s_id->i_id

问题

依赖一,i_id非超码(一个导师在某个系内可带多个学生)

依赖二,成立

分解

(i_id, dept_name)和(s_id, i_id)

根据依赖一分解后均为BCNF(任何二属性关系模式都是BCNF),但无法保持依赖二

不足

有时的设计使得保持依赖(dependency preserving)很困难,需要一种BCNF约束要弱的范式,设计的同时保持依赖--第三范式

4.2 3NF

具有依赖集F的关系模式R属于3NF的条件,F+中所有形如α->β的函数依赖R且βR),下面至少一项成立

  • α->β是平凡依赖
  • α是R的一个超码
  • β中每个属性A都包含于R的一个候选码(最小超码)(β-α中每个属性A可以包含于不同候选码,无需同时在一个中满足)

根据定义,3NF一定非BCNF

举例⭐

依赖一: i_id->dept_name

α=i_id,

β=dept_name

dept_name-i_id = dept_name

在无法满足BCNF情况下: 为了保持依赖二成立,又(dept_name,s_id)是一个候选码,包含dept_name,因此该模式为3NF

依赖二: dept_name, s_id->i_id



5. 函数依赖理论

5.1 函数依赖集的闭包F+

逻辑蕴含

对r(R),给定依赖集F,当r(R)每一个满足F的实例也满足f,fr上依赖集F逻辑蕴含(logically imply)

离散数学中的蕴含关系p->q,只有p真q假时为假.依赖集F->f即当所有实例满足F,则一定满足f

依赖集闭包

根据逻辑蕴含定义,F+就是被F逻辑蕴含的所有函数依赖的集合

armstrong公理系统

使用下列规则可寻找逻辑蕴涵的函数依赖:

  • 自反律(reflexivity rule):若βα,则α->β成立
  • 增补律(augmentation rule):若α->β成立且γ也为属性集,则γα->γβ成立
  • 传递律(transitivity rule):若α->β且β->γ,则α->γ
  • 合并律(union rule): α->β和α->γ成立,作为α->βγ
  • 分解律(decomposition): 若α->βγ成立,则α->β和α->γ成立
  • 伪传递律(pseudotransitivity rule):若α->β和γβ->ξ成立,则αγ->ξ成立

滚雪球算法

算法可结束:
对n元素的集合,2n个子集,对形如α->β的依赖,左右都为子集,则共有2n*2n=22n个依赖,除了最后一次,每次迭代repeat中至少新加了一个f,则算法一定可以结束


(滚雪球求,F+很少用,计算量巨大)

5.2 属性集闭包⭐

函数确定

若α->B(非β,只是单个属性B),则称属性B被α函数确定(functionally determine)

属性集闭包⭐

将给定依赖集F下被α函数确定的所有属性的集合称为F下α的闭包α+

判断超码

若要判断α是否为超码

  • 计算F+,找出所有形如α->β的f,合并右半部分-->开销大
  • 属性闭包算法

属性闭包算法

例题⭐

对r(A,B,C,G,H,I),F如下

(AG)+

result=AG
A->B
中:Aresult,result=result∪B =AGB

A->C中:A⊆result,result=ABCG

同理对CG->H,CG->I,B->H
最终result=ABCGHI即(AG)+,(AG)是超码

算法作用⭐

判断α是否为超码

α+=R,R中每个属性都可由α确定为超码

通过检查是否βα+,检查α->β是否成立

当βα+,说明α可以在给定F下确定β

计算F+:
对任意γR,找出F可确定的所有属性,组成闭包γ+ 再对任意Sγ+,输出函数依赖γ->S,因为γ->SF约束下确定的依赖,则也一定是F+中一个函数依赖,同理γ->γ+也是F+中一个依赖 (作为5.6 保持依赖算法算法二依据)

使用上面例题:
(AG)
+=ABCGHI,则有:
AG->A,AG->B,
AG->C,AG->G,AG->H,AG->I,
AG->ABCGHI
都是F+中的依赖

5.3 正则覆盖

(canonical cover)

检测

F下的关系模式r(R),必须保证用户更新数据库后依旧满足F,这就需要检测,当检测不满足F,回滚该操作
简化方法:通过测试与给定F具有相同依赖闭包的简化集的方式减少检测开销 原理:简化集和原集闭包相同,满足简化集的数据库一定也满足原集

无关属性⭐

PDF221

去除函数依赖集中某个依赖的一个属性,不改变依赖集的闭包,(此依赖中的)该属性无关(extraneous):
考虑F和F中的函数依赖f:α->β

  • 如果A∈αF逻辑蕴涵(F-{α->β})∪{(α-A)->β},则属性A在α中无关

α->β,判断A在α中无关,要求依赖闭包在剔除A后不变,A的存在为了推出β: 只需说明F->{(F-f)∪((α-A)->β)},由公理,只需证F->{(α-A)->β},即β的推出和A本身无关: 为此,计算F+,(α-A)->β)F+,A在α中无关

  • 如果Aβ依赖集(F-{α->β})∪{(α->(β-A)}逻辑蕴涵F,则属性A在β中无关

α->β,判断A在β中无关,要求依赖闭包在剔除A后不变,A的存在为了维持β,进而维持F:
只需说明{(α->(β-A))∪(F-f)}->F,即F只用(α->(β-A))(F-f)就能得到,与β中A无关:

为此,计算F下的闭包((α->(β-A))∪(F-f))+,当F((α->(β-A))∪(F-f))+,则A在β中无关

  • 注意,上述两个蕴含关系在左右相反后恒成立

正则覆盖⭐

Fc是一个依赖集,使得F逻辑蕴涵Fc中所有依赖,并且Fc逻辑蕴含F中所有依赖.此外Fc必须有如下性质:

  • Fc中任何函数依赖都不含无关属性
  • Fc中函数依赖的左半部都是唯一的

F<->Fc,对应离散数学中的"当且仅当(充要条件)",因此检验Fc和检验F的真值表应该一模一样,Fc即为"简化集"

算法⭐

当遇到Fc=A->C,两侧都只有一个属性的属性集时,如果有一个无关属性,则这样空属性的函数依赖也要剔除

非唯一性⭐

    Fc初始化为F后,Fc中选取不同的依赖f进行无关性检验并删去后,最终的到的正则覆盖结果不唯一

例题

对下列F求正则覆盖

image.png

Fc初始化为F
合并:
Fc: A->BC,B->C,AB->C
检验Fc的无关属性:

AAB->C中无关

只需说明(B->C}能被Fc进一步推出: B->C就在Fc,A无关
Fc变为A->BC,B->C

CA->BC中无关

只需说明A->B可在Fc-f下进一步推出Fc: A->B和B->C可推出A->C,A->C和A->B可推出A->BC,则可推出Fc中所有依赖,C无关,Fc变为A->B,B->C

所以正则覆盖为:A->B, B->C


5.4 二元无损分解

(lossless decomposition)

无损分解

F是r(R)上的函数依赖集,令R1,R2为R的分解,若用r1(R2)r2(R2)替代r(R)时没有信息损失,则称分解是无损分解.

关系代数角度⭐

select * from

(select R1 from r) as r1

natural join

(select R2 from r) as r2

r投影到R1和R2,对投影结果自然连接,若结果与r相同,则为无损连接,否则有损连接,1.2 关系模式的分解中的例子,最后自然连接的结果为四个元组

函数依赖角度⭐

  • R1∩R2->R1
  • R1∩R2->R2
    以上依赖中至少一个在F+,R1,R2就为无损分解,R1∩R2R1R2的超码:采用属性闭包算法,(R1∩R2)+=R1R2即为无损分解

充分条件

满足二元分解测试->证明是无损连接 但只有所有的约束都是函数依赖时才能说明: 满足无损连接->二元分解测试成立

5.5 保持依赖

保持依赖

上文BCNF局限中的分解问题遇到了无法保持依赖的问题:
当有RF中有f1,f2成立,f1满足BCNF要求,f2不满足,从而分解,再次判定f2满足,但没有Ri满足出现f1所有属性 实际上,对于Ri,F中所有α->β依旧保持,下面是证明

限定:Fi

令F为模式R上的依赖集,R1,R2...Rn为R的分解.F在Ri上的限定是F+中所有只包含Ri中属性的函数依赖集合Fi.由于一个限定中的所有函数依赖只涉及一个R中的属性,因此判定这种依赖是否满足可以只检查一个关系Ri.

Ri是全体属性R中的部分属性,FiF中只与这些属性有关的函数依赖

限定的并集:F'

根据限定的定义,F1,F2...Fn的集合就成为可以高效检查的依赖集.令F'=F1∪F2∪...∪Fn,F'是R上一个依赖集,通常F'≠F,但可能有F'+=F+
如果后者成立,F中所有依赖都被F'逻辑蕴含,只要证明满足F',就满足了F,称具有F'+=F+的分解为保持依赖的分解(dependency-preserving decomposition)

F'+=F+成立,F+F'+,又FF+,则FF'+,根据属性闭包算法,F'->F,如果所有依赖满足F'即满足F

5.6 保持依赖验证算法

算法

思想

输入:D(R1,R2...Rn)R的依赖集F

F+求出所有限定Fi并取所有限定,F'计算F'+比较F'+F+


👹弊端: 要计算F+,开销大

算法的根本目标:证明模式R中所有F下的α->β在分解R1,R2...Rn中依旧保持

算法依据:5.5 限定的并集F',只要保证α->βF'下保持

算法实现:计算F'下α的闭包,当βα+,根据5.2 属性闭包算法作用,α->β成立,即α->βF'中保持,当且仅当每一个α->β都保持,该分解是依赖保持的

F中每个α->β



此时属性闭包都是F下的:

  • 若result含有β所有属性,则α->β保持
  • 当且仅当F中所有α->β都保持时,所有分解Ri都保持依赖

算法的根本目标:同上

算法依据:5.2 属性闭包算法作用中作用三,对每个γRi:

  • γ作为R中属性:γ->γ+是F+中函数依赖
  • γ作为Ri中属性:γ->RiFi/F'函数依赖
  • γ->(γ+Ri)成为F+Ri上限定Fi/F'中的依赖

F+Ri上限定Fi中的依赖:指在Ri中依旧保持的F+中依赖,+Ri)是该依赖可确定的属性集

算法实现:result初始为α

while每次对一个Ri操作,验证F+中依赖在Fi中保持,result不变,相当于验证每个依赖在F'下保持

5.7 候选码求法--LRN法

FD属性分类

L类

仅在FD左边出现的属性

R类

仅在FD右边出现的属性

N类

FD两边均未出现的属性

LR类

在FD两边均出现的属性

定理

&

推论⭐

定理1

对给定R和F,当x∈R是L类属性,则x一定是候选码关键字成员

推论1

对给定RF,xRL类属性,且x+包含了R的所有属性,x唯一候选码

定理2

对给定RF,xRR类属性,x一定非候选码关键字成员

定理3

对给定RF,xRN类属性,x一定是候选码关键字成员

推论2

对给定RF,αRNL组成的属性集合,且α+包含R所有元素,则α是唯一候选码

步骤⭐

  1. 使用LRN法求出L,R,N,LR类属性集合
  2. 求L中元素闭包,L中属性()闭包等于R,则为唯一候选码[推论1],如果非R,则依次并入LR中元素,直到闭包满足R



6. 分解算法

6.1 BCNF判定

一般判定

参照5.2 属性闭包算法,即判断α+是否等于R,可以证明:

只要F中的依赖都满足BCNF,F+中的也都满足

分解后判定⭐

当有R的F中有依赖不满足BCNF,从而分解,再次判定,但当前没有依赖包含Ri中所有属性,无法准确判断

例子:分解后

F中没有依赖能够判定R2是否满足BCNF,不能简单认为这种情况下就默认满足,伪传递律可得到AC->D,R2不满足,有时需要一个来自F+而不在F中的依赖才能额外判断这种情况

改进判定

实战中非常重要的判定

6.2 BCNF分解算法

image.png

即第三部分3.3 BC范式:非BCNF的分解原理:R-β+α=>Ri-β
α->Ri不属于F+,这项要求保证了不会产生冗余的依赖,非常重要

结果

该算法产生无损的BCNF分解:

  • 使用(Ri-β)(α,β)取代模式Ri,依赖α->β成立,(Ri-β)(α,β)=α,参考无损分解的函数依赖角度,相当于(Ri-β)(α,β)->(α,β)属于F+,是无损分解
  • 若没有要求α∩β=Ø,那α∩β中的属性不会出现在(Ri-β),那α->β不再成立

6.3 3NF分解算法

3NF算法中有两点注意:

  • 若所有Rj都不含R的候选码时,就需要额外创建一个关系模式,其中属性就是R的任意候选码
  • 模式可能产生冗余:如R1(A,B)R2(A,B,C)这是就可以删除R1,令R2=R1

    算法证明
    :
    PDFP227

例题

4.1图dept_advisor(s_id, i_id, dept_name)为例, 要求满足的两个依赖为:

  • i_ID->dept_names_ID
  • dept_name->i_ID

而且恰好为Fc,则R1=(i_ID, dept_name),R2=(s_ID, dept_name, i_ID),又因为(s_ID, dept_name)就是候选码,无需创建新模式,但R1产生冗余,删去,最终产生保持依赖且无损的3NF,R(s_ID, dept_name, i_ID)

  • 3NF算法拓展⭐

3NF算法的结果可能属于BCNF,因此进行BCNF分解可以:
先使用3NF算法,对结果中不满足BCNF的进行分解,如果结果没有保持依赖,则只能恢复到3NF,否则就是BCNF

6.4 3NF对比BCNF

3NF

BCNF

优点

可以在无损且保持依赖的情况下得到设计

没有冗余

缺点

可能需要null占位保持某些联系,或者可能有冗余无法保持某些函数依赖

sql设计

大多数数据库系统在检查非主码约束的函数依赖很困难,因此3NF的妥协导致了设计时的困难

对于无法保持的依赖,使用物化视图计算被拆散的依赖,投影为αβ,利用unique(α)primary key(α)可以在物化视图上检查这些依赖

实际

在无法得到保持依赖的BCNF分解时,优先考虑使用物化视图的BCNF,而非3NF



7. 多值依赖和其余范式

教材

参考PDF228开始内容

知乎

关于函数依赖和范式的知乎回答: 如何解释关系数据库的第一第二第三范式? - 刘慰的回答 - 知乎



8. 数据库设计过程

得到r(R)的三种方式

  • 直接由ER图转换
  • r(R)开始包含所有属性,然后在规范化时不断分解
  • 即席设计,类似预算要求,直接分析得到

ER模型与规范化

如果ER图设计的好,应该无需过多的规范化,以大学数据库为例:

若在instructor中包含了属性dept_name和dept_address,且又有依赖dept_name->dept_address,就一定需要规范化
如果在ER设计时创建
department,instructor和二者间的联系集合,就无需额外规范化

注意,二元以上联系集可能使得模式不属于期望得范式

总结:规范化既可以在建模时靠分析实现,也可以对于现有模型进行规范化



规范化例题

原目录:数据库系统概论 / Ch8 关系数据库设计

查看语雀原文

例1

给定关系模式EMP_DEPT

1.“EmployeeNo”, “EmployeeName”, “BornDate” and “EmployeeAddress” represent the ID number, name, date of birth, and address of an employee.

2.“DepartmentNo”, “DepartmentName”, and “DepartmentAddress” represent the ID number, name, and address of a department.

3.“ProjectNo” and “ProjectName” represent the ID number and name of a project.

4.“WorkHours” represents the working hours of an employee in a project. 

一些设定:

 A department has more than one employee;

  Two employees maybe have the same name;

  An employee works in a unique department;

  An employee can take part in several projects;

  Two or more employees from different departments can take part in a same project;

  An employee can take part in more than one project;

  The working hours of an employee in different project may be different.

  1. Identify functional dependencies.

有以下函数依赖:

易错点:
认为employeeNo->projectNo,认真读题,"一个人一个部门,一个人多个项目,不同部门得多个人可以参加一个项目",则有一定有人不属于任一个部门,才能参加多个项目,因此二者没有必然依赖关系,只有employeeNo, departmentNo->projectNo

  1. Determine all candidate keys of the relational schema.

image.png

  1. Is the realtional schema in BCNF? Why? If not, bring it to a set of BCNF schemas, and identify their candidate keys and foreign keys

image.png



例2

考虑关系模式R = {A, B, C, D, E}, 函数依赖集FD = { A→C, B → D, AB → CD, E → B}

(1)求R的候选码。

(2)下列函数依赖哪些成立? a. E → D b. A → B c. AB → CE d. AE → CB

3R是否满足BCNF?请说明理由。若不满足,请将R规范化为一组BCNF关系模式。

  1. 参考:5.7 候选码求法--LRN法 首先排除R类属性BCD
    A
    +≠R且E+≠R
    (AE)
    +=R,则候选码是AE
  2. 参考:5.2 属性闭包算法作用

image.png

  1. 参考: 6.2 BCNF分解算法

易错点:
1. 使用AB->CD分解R:
分解算法是要在分解后产生一个无损BCNF关系,另一个不满足BCNF的时候在此继续分解;而不是为了分解而分解.使用AB->CD,第一步得到的R1R2都是非BCNF
2. 关于判定Ri中未显式表明的依赖是否满足BCNF:
如R4(ABE)中E->B成立,但不好直接说明是否符合BCNF,通过改进后的判定方法,R43个元素,对于8个子集,其中E+= BDE, 不满足"要么闭包不含有除本身外的其余任何属性,要么包含R中所有属性"这一调节,E->((E+-E)∩Ri)E->B不满足BCNF,需要分解


Ch14/15 事务管理

原目录:数据库系统概论

查看语雀原文

Ch14 事务

PDF P385

1. 并发控制

两种调度方式

串行

并行

串行(serial):同一事务的指令集中在一起执行

并发:可以间断的切换处理事务



2. 可串行化(serializable)

定义:将并发执行的调度等价为一种串行的调度(一组事务的调度包含该事务所有指令,不能中间插入)

2.1 冲突可串行化

对于read和write指令,调度S种分别属于事务i,j的指令,有以下组合

i=read, j=read

i, j次序无关紧要

i=read, j=write

write的先后决定了read的数据是否产生变化

i=write, j=read

同上

i=write, j=write

对于S的下一条read有影响,它只能read后write的值

因此,不同事务上对相同数据项的操作,其中至少有一个write指令时,i,j是冲突

2.2 冲突等价

i,j是调度S的两条连续指令,从属于不同事务且不冲突,则可以交换i,j得到新的调度S',S等价于S',因为i,j的顺序改变不会影响事务处理,常见的交换:

T1的read(A)<-->T2read(B)

T1read(A)<-->T2write(B)

T1write(A)<-->T2read(B)

T1read(A)<-->T2read(A)

2.3 可串行化判断

使用"优先图",G(V,E),V作为点集,每个顶点就是一个事务Ti,边集由满足下列条件的边Ti->Tj组成:(恰好对应三种矛盾)

Tj执行read(Q)前,Ti执行write(Q)

Tj执行write(Q)前,Ti执行read(Q)(Ti还未执行write(Q))

Tj执行write(Q)前,Ti执行write(Q)

举例

调度

优先图

T1所有的命令都先于T2执行,因此优先图就是两点一线


T2write(A)前执行了T1read(A),产生T1->T2,T1write(B)执行前,T2执行了read(B)因此有T2->T1,最终形成环

结论:只有优先图中无环的调度才能冲突串行化

2.4 串行化顺序确定

使用拓扑排序生成串行化顺序(不唯一)

👇下图可能的串行化顺序:Ti->Tj->Tk->TmTi->Tk->Tj->Tm


image.png

2.5 冲突等价与可串行化区别

  • 可串行化是一组事务的调度包含该事务所有指令,不能中间插入,一般表示为<T1,T2,...,Tn>
  • 冲突等价是针对不同事务指令的交换,一般使用图示



Ch15 并行控制

1. 基于锁的协议

1.1 两种锁

共享锁lock-s

Ti获得Q上的共享锁-->Ti只能读Q,不能写

排他锁lock-x

Ti获得Q上的排他锁-->Ti可以读,写Q

1.2 相容函数

如果T2请求Q上的锁B,但事先已有T1获得了Q上的锁A,如果此时T2能够立即获得锁,则称A,B锁是相容的,否则只能等T1解锁后T2才能获得,在此之前T2只能等待

  • lock-s与lock-x的相容矩阵Comp

image.png

1.3 两阶段锁协议

保证可串行性的一个协议是"两阶段封锁协议",分为两个阶段提出加速和解锁申请:
(两个阶段都是针对一个事务来说)

  • 增长阶段(growing phase):事务可获得锁,不能释放锁
  • 缩减阶段(shrinking phase):事务可释放锁,但不能获得锁

两阶段封锁可以保证可串行性,但无法保证避免死锁

  • 封锁点:对于任何事务,在调度中该事务获得其最后加锁的位置(增长阶段结束点)

多个事务根据封锁点排序,得到的顺序就是可串行化顺序

1.4 三类二阶段锁协议

分类

特点

一般

  • 两阶段封锁
  • 解锁不必非要再事务结束后,只需恪守两阶段定义,比如可以把unlock(B)放在lock-x(A),此时lock-x(A)恰好陈伟封锁点

严格(strict)

  • 两阶段封锁
  • 所有lock-x只能在事务提交后才能释放

严酷(rigorous)

  • 两阶段封锁
  • 任何锁在事务提交后才能释放

1.5 锁转换

定义

锁转换(lock conversion),提供一种lock-slock-x转化的方式,从而减少等待或饥饿,提高并发度

分类

  • 升级: lock-x lock-s,只能发生在增长阶段
  • 降级: lock-s lock-x,只能发生在缩减阶段

两阶段操作

  • 增长:接收lock-s\接收lock-x\升级
  • 缩减:释放lock-s\释放lock-x\降级

机制总结

  • 当T执行read(Q),系统产生lock-s(Q),read(Q)紧接
  • 当T执行write(Q),系统检查T是否已经持有lock-s(Q),若有:执行升级,write(Q)紧接,否则直接lock-x(Q),write(Q)紧接
  • 事务提交或中止,所有锁释放

举例

对左侧调度采用普通两阶段协议:
T8
read(a1)前请求lock-x(a1),对其余ai请求lock-s(ai),但是实际上只用在write(a1)前请求lock-x(a1),使其余事务可以读取a1,提高并发度.


使用锁转换:
T8中先对所有ai请求lock-s,write(a1),lock-s(a1)lock-x(a1)

忽略读写的调度: