1. 关系数据库

关系数据库:将数据组织成表格形式,为每张表赋予一个唯一名称

  • 表(table):每个表由行和列组成
  • 元祖(tuple):指代行,每一行代表一个数据记录
  • 属性(attribute):指代列,每一列代表一个数据字段

根据集合的定义,元组在关系中出现的顺序是无关紧要的

域(domain):每个属性允许取值的集合

性别属性的域是男和女
年龄属性的域是0-100的整数

原子的(atomic):一个域中的元素被认为是不可再分的单元

数量上:联系电话可以既填自己、父母和朋友等,是多个手机号码的集合
结构上:手机号可以拆分为国家编号、地区编号和通信公司编号等,是多个字段的组成

关系模式(schema):描述了关系的蓝图,定义了表的名称、属性、数据类型、域和约束

关系实例(instance):描述了关系的快照,存储了某时刻的数据集合,是具体的元组的集合

学生关系的模式:student(name,id,age,major,cardnum)
学生关系的实例:(dasi,22336218,20,cs,5201314)

2. 码

数据完整性(uniqueness)
  • 实体完整性:确保任一元组的所有属性值必须能唯一标识该元组,即一个关系中不能存在两个元组在所有属性值上都相同
  • 引用完整性/参照完整性:确保引用属性的值必须存在于其他表中
  • 域完整性:确保属性值符合域和数据结构
  • 用户自定义完整性:属性值符合特定业务的规则

超码(superkey):一个或多个属性的集合,超码可以在一个关系中唯一标识出一个元组

根据定义,超码的任意超集都是超码,因此可能存在很多超码

候选码(candidate key):任意真子集都不是超码的最小超码

候选码虽然是最小的,但是可以有多个候选码,如学生既可以用身份证唯一标识,也可以用学号唯一标识,还可以用“专业+毕业高中+年级+姓名”的组合来唯一标识

主码(primary key):由数据库设计者人为选中来作为在一个关系中区分不同元组的候选码

主码约束
  • 主码一定是候选码!主码一定是超码
  • 主码不是表的天然属性,是人根据数据库的使用目的来手动选择的!
  • 主码的选择必须是那些不变化或者极少变化的属性

习惯上,总是将主码属性放在其他属性之前,并加下划线:student(id,name,age)

外码(foreign key):当前表的外码属性是另一个表的主码属性

外码约束
  • 每个元组在表中的唯一性,代表每个外码引用的属性值也必须是唯一的,因此当前表的外码属性必须是其他表的主码
  • 外码约束确保两个表之间的引用完整性,维护了关系数据库的结构

外码约束不等于引用完整性约束!外码约束是引用完整性约束的子集,是其特殊情况!

3. 模式图

每个关系为一个框,关系名用灰色显示在顶部,在框内列出了各属性

图片

使用双箭头表示不是外码约束的引用完整性约束
数据库系统支持图形化用户界面的设计工具来创建数据库模式图

4. 关系查询语言

  • 命令式(imperative):用户指导系统在数据库上执行特定顺序的运算序列来查询
  • 函数式(functional):利用数据库给出的函数来查询
  • 声明式(declarative):只需要给出数学逻辑的描述信息来查询

关系代数是函数式查询语言,SQL是声明式查询语言

5. 关系代数

5.1 选择运算(select)

功能:选出满足给定谓词的元组,使用σ\sigma来表示,谓词写在σ\sigma的下标,关系写在σ\sigma后的括号内,并支持比较运算和逻辑连接词

查询月薪高于10000的老师:σsalary>10000(teacher)\sigma_{salary>10000}(teacher)
查询月薪高于10000的物理老师:σPhysicssalary>10000(teacher)\sigma_{“Physics”\land salary>10000}(teacher)
查询年龄大于40的老师:σage>40(teacher)\sigma_{age>40}(teacher)

5.2 投影运算(project)

功能:用于过滤掉属性从而只给出特定属性的关系,使用Π\Pi表示,希望显示的属性列表作为Π\Pi的下标,关系写在Π\Pi后的括号内,并支持在属性列表中使用算术运算

查询老师的名字、年龄和号码:Πname,age,id(teacher)\Pi_{name,age,id}(teacher)
查询老师的名字和减去税收100的月薪:Πname,salary100(teacher)\Pi_{name,salary-100}(teacher)

5.3 笛卡尔积运算(cartesian-product)

功能:将两个关系的元组拼接成单个元组,使用×\times表示,对于仅出现在一个关系的属性,通常删除关系名前缀

学生:student(id,name,major)student(id,name,major)
老师:teacher(name,course,salary)teacher(name,course,salary)
学生和老师的笛卡尔积:(id,student.name,major,teacher.name,course,salary)(id,student.name,major,teacher.name,course,salary)

5.4 连接运算(join)

功能:用于选择笛卡尔积中满足谓词的元组,用符号\bowtie表示,谓词作为\bowtie的下标,笛卡尔积放在\bowtie后的括号内

实际上连接运算等价于:rθs=σθ(r×s)r\bowtie_{\theta}s = \sigma_{\theta}(r \times s)

查询学生是2022级且老师课程是计算机的笛卡尔积:studentstudent.year=2022teacher.course=csteacherstudent\bowtie_{student.year=2022 \land teacher.course=cs}teacher

5.5 并运算(union)

功能:用于给出两个关系的并集,使用\cup表示。要求两个关系必须有相同数量的属性,且关系对应属性类型必须相同

查询2017年或2018年开设课程的id:Πcoureid(σyear=2017(section))Πcoureid(σyear=2018(section))\Pi_{coureid}(\sigma_{year=2017}(section))\cup\Pi_{coureid}(\sigma_{year=2018}(section))

5.6 交运算(intersection)

功能:用于给出两个关系的交集,使用\cap表示

查询2017年且2018年都开设课程的id:Πcoureid(σyear=2017(section))Πcoureid(σyear=2018(section))\Pi_{coureid}(\sigma_{year=2017}(section))\cap\Pi_{coureid}(\sigma_{year=2018}(section))

5.7 差运算(set-difference)

功能:用于给出两个关系的差集,使用-表示

查询2017年开设但2018年没有开设的课程id:Πcoureid(σyear=2017(section))Πcoureid(σyear=2018(section))\Pi_{coureid}(\sigma_{year=2017}(section))-\Pi_{coureid}(\sigma_{year=2018}(section))

5.8 赋值运算(assignment)

功能:将关系代数表达式的结果赋值给临时的关系变量,使用\leftarrow表示,左边是关系变量,右边是关系代数表达式

查询2017年且2018年都开设课程的id
course2017Πcoureid(σyear=2017(section))course_2017 \leftarrow \Pi_{coureid}(\sigma_{year=2017}(section))
course2018Πcoureid(σyear=2018(section))course_2018 \leftarrow \Pi_{coureid}(\sigma_{year=2018}(section))
$course_2017 \capcourse2018course_2018

5.9 更名运算(rename)

功能:给关系代数表达式的结果赋予一个名称,使用ρ\rho表示,下标是名称,后跟括号内是关系代数表达式

  • 给表达式E的结果命名为x:ρx(E)\rho_x(E)
  • 给表达式E的结果命名为x,并且将其属性重命名为A1,,AnA_1,···,A_nρx(A1,,An)(E)\rho_{x(A_1,···,A_n)}(E)

查询比ID为123的老师工资多的老师的姓名:Πi.name((σi.salary>w.salary(ρi(teacher)×σw.id=123(ρw(teacher)))))\Pi_{i.name}((\sigma_{i.salary>w.salary}(\rho_{i}(teacher)\times\sigma_{w.id=123}(\rho_{w}(teacher)))))