2.关系型模型简介

2.1 关系数据库的结构

关系数据库由一组表【table】组成,每个表【table】都分配了一个唯一的名称。

通常,表【table】中的一行【row】表示一组值之间的关系【relationship 】。 由于表【table】是此类关系【relationships】的集合,因此表【table】的概念与关系的数学概念之间存在着密切的对应关系,关系型数据模型【relational data model】的名称也由此而来。 在数学术语中,元组【tuple】只是值的序列(或列表)。 n 个值之间的关系在数学上由值的 n 元组表示,即具有 n 个值的元组,它对应于表【table】中的一行【row】。


因此,在关系模型【relational model】中,术语关系【relation 】用于指代表【table】,而术语元组【tuple】用于指代行【row】。 同样,术语属性【attribute】指的是表的列【column】。

图 2-1 instructor 关系

我们使用术语关系实例【relation instance】来指代关系【relation】的特定实例,即包含一组特定的行。图2.1中所示的 instructor 实例有 12 个元组,对应于 12 个讲师。

元组【tuple】在关系【relation】中出现的顺序无关紧要,因为关系【relation】是关于元组【tuple】的集合【set】。

对于关系【relation】的每个属性【 attribute】,都有一组允许的值,称为该属性【attribute】的域【domain】。 因此,instructor 关系的 salary 属性的域是所有可能的 salary 值的集合,而 name 属性的域是所有可能的 instructor 的名字的集合。

我们要求,对于所有关系【relation】 r,r 的所有属性【attribute】的域都应该是原子【atomic】的。 如果域中的元素被认为是不可分割的单元,则域是原子【atomic】的。 例如,假设 instructor 表有一个属性 phone number ,它可以存储一组与教师对应的电话号码的集合,那么
phone number  域就不会是原子的,因为该域的一个元素是一组电话号码的集合,并且它还有子部分,即集合中的各个电话号码。


 

重要的问题不是域本身是什么,而是我们如何在数据库中使用域中元素。假设现在 phone number 属性只存储了一个电话号码。即使这样,如果我们将电话号码属性的值拆分为国家代码、地区代码和本地号码,我们也会认为它是非原子的。如果我们将每个电话号码视为一个不可分割的单元,那么属性 phone_number 将具有原子域。

空值【null value】是一个特殊值,表示该值未知或不存在。 例如,我们在 instructor 关系中包含属性 phone_number。 可能是讲师根本没有电话号码,或者电话号码未列出。 然后我们将不得不使用空值来表示该值未知或不存在。 稍后我们将看到,当我们访问或更新数据库时,空值会导致许多困难,因此应尽可能消除它们。 

2.2 Database Schema

当我们谈论数据库时,我们必须区分数据库模式【database schema】(数据库的逻辑设计)和数据库实例【database instance】(数据库中数据在给定时刻的快照)。


关系【relation】的概念对应于编程语言中变量【variable】的概念,而关系模式【relation schema】的概念对应于编程语言中类型定义【type definition】的概念。


通常,关系模式【relation schema】由属性【attributes】列表及其对应的域组成。 

关系实例【relation instance】的概念对应于编程语言中变量的值【value of a variable】的概念。 给定变量【variable】的值可能随时间而变化;类似的,关系实例【relation instance】的内容也可能随着关系【relation】的更新而变化。


相反,关系模式【relation schema】通常不会改变。 尽管了解关系模式【relation schema】和关系实例【relation instance】之间的区别很重要,但我们经常使用相同的名称(例如 instructor)来指代模式【schema】和实例【instance】。 

在关系模式中使用公共属性【common attributes】是关联不同关系【relation】的元组【tuple】的一种方式。

2.3 keys

我们必须有一种方法来指定如何区分给定关系中的元组。 这是通过它们的属性来表达的。 也就是说,元组的属性值的取值必须能够唯一标识该元组。 换句话说,不允许关系中的两个元组的所有属性具有完全相同的值。 


超键【superkey】是一个或多个属性的集合,这些属性集中在一起,使我们能够唯一地标识关系【relation】中的元组【tuple】。 例如,关系 instructor 中的 ID 属性足以将一个 instructor 元组与另一个区分开来。 因此,ID 是一个超键【superkey】。 另一方面,instructor 的 name 属性不是超级键,因为多位讲师可能有相同的名字。

形式上,设 R 表示关系 r 的模式中的属性集。 如果我们说 R 的子集 K 是关系 r 的超键,我们将考虑限制在关系 r 的实例中,其中没有两个不同的元组在 K 中的所有属性上具有相同的值。也就是说,如果 t1 和 t2 在 r 且 t1 ≠ t2,则 t1.K ≠ t2.K

超键【superkey】可能包含无关的属性。 例如,ID 和 name 的组合是关系 instructor 的超键。 如果 K 是超键,那么 K 的任何超集也是。我们通常对没有适当子集是超键的超键更感兴趣。 这种最小的超键【superkey】称为候选键【candidate keys】。

候选键【candidate keys】依然存在多种可能。假设 name 和 dept_name 的组合足以区分 instructor 关系中的成员。那么,{ID} 和 {name, dept name} 都是候选键【candidate keys】。

我们将使用术语主键【primary key】来表示由数据库设计者选择的候选键【candidate key】,该候选键【candidate key】作为在关系中标识元组的主要手段。键【key】(无论是主键、候选键还是超级键)是整个关系的属性【property】,而不是单个元组的属性【property】。关系中的任何两个独立元组都不能同时在键属性【key attribute】上具有相同的值。键的指定表示正在被建模的现实世界企业中的约束。因此,主键【primary key】也被称为主键约束【primary key constraints.】。

通常将关系模式【relation schema】中的主键属性列在其他属性之前;并且主键属性也会带有下划线。

接下来,我们考虑另一种对关系内容的约束,称为外键约束【foreign-key constraints】。 考虑 instructor 关系的 dept name 属性。 instructor 中的元组 dept_name 与 department 关系中的部门不对应是没有意义的。 因此,在任何数据库实例中,给定来自 instructor 关系的任何元组,比如 ta,在 department 关系中必须有一些元组,比如 tb,使得 ta 的 dept_name 属性的值与 tb 的主键dept name 相同。

从关系 r1 的属性 A 到关系 r2 的主键 B 的外键约束表明,在任何数据库实例上,r1 中每个元组的 A 的值也必须是 r2 关系中某个元组的 B 的值。 属性集【Attribute set】 A 称为来自 r1 的外键,引用 r2。 关系 r1 也称为外键约束【foreign-key constraint】的引用关系【referencing relation】,r2  称为被引用关系【referenced relation】。

请注意,在外键约束中,被引用的属性必须是引用关系中的主键。 。更一般的情况是引用完整性约束【referential-integrity constraint】,它放宽了引用属性构成引用关系的主键的要求。通常,引用完整性约束【referential-integrity constraint】要求出现在引用关系【referencing relation】中任何元组的指定属性中的值也出现在被引用关系【referenced relation】中至少一个元组的指定属性中。

事实上,外键约束【foreign-key constraints 】是饮用完整性约束【referential-integrity constraint】的一个特例,其中被引用的属性【referenced attributes】构成被引用关系【referenced relation】的主键。 今天的数据库系统通常只支持外键约束,但它们不支持引用完整性约束。

2.4 Schema Diagrams

2.5 Relational Query Languages

查询语言【query language】是用户从数据库中请求信息的语言。 这些语言的级别通常高于标准编程语言。 查询语言可以分为命令式、函数式或声明式。 在命令式查询语言【imperative query language】中,用户指示系统对数据库执行特定的操作序列以计算出所需的结果; 这类语言通常有状态变量的概念,在计算过程中更新。

在函数式查询语言【functional query language】中,计算被表示为对可能对数据库中的数据或其他函数的结果进行操作的函数【function】的求值【evaluation】; 函数是无副作用【side-effect free】的,它们不会更新程序中的状态。在声明式查询语言【declarative query language】中,用户描述所需的信息【desired information】而无需给出获取该信息的特定步骤或函数调用顺序; 所需信息通常使用某种形式的数学逻辑【mathematical logic】来描述。至于弄清楚如何获取所需的信息,这是数据库系统的工作。

有许多“纯”查询语言:

  • 我们在2.6节中描述的关系代数【relational algebra】是一种函数式查询语言,关系代数构成了 SQL 查询语言的理论基础。
  • tuple relational calculus和domain relational calculus 是声明式的。

实践中使用的查询语言,例如 SQL 查询语言,包括命令式、函数式和声明式方法的元素。

2.6 The Relational Algebra

关系代数由一组操作【operations】组成,这些操作【operations】以一个或两个关系【relation】作为输入,并产生一个新的关系【relation】作为结果。


其中一些操作,如选择【select】、映射【project】和重命名【rename】操作被称为一元操作,因为它们操作的是一个关系。其他运算,如并集【union】、笛卡尔积【Cartesian product】和差集【set difference】,都是对一对关系进行运算,因此被称为二元运算。


尽管关系代数操作【relational algebra operations】构成了广泛使用的 SQL 查询语言的基础,但数据库系统不允许用户使用关系代数编写查询。


在这里值得回顾的是,由于关系【relation】是关于元组【tuple】的集合【set】,关系【relation】中不能包含重复的元组【tuple】。但是,在实践中,数据库系统中的表【table】允许包含重复项【duplicates】,除非有特定的约束禁止它。但是,在讨论形式关系代数【formal relational algebra】时,我们要求消除重复项,这是由集合的数学定义所要求的。在第3章中,我们将讨论如何将关系代数扩展到多集【multisets】,即可以包含重复项的集合。

2.6.1 select

选择【select】操作选择满足给定谓词【predicate】的元组【tuple】。我们用小写的希腊字母 sigma (σ) 表示选择【select】。谓词【predicate】作为 σ 的下标出现。操作的参数-关系则出现在 σ 后面的括号中。因此,为了选择 instructor 关系中物理系的讲师的元组,我们写道:

\sigma_{depname = "Physics"} (instructor)

通常,我们允许在选择【select】的谓词中使用=、≠、<、≤、>和≥进行比较。此外,我们可以用连接词,比如和(∧)、或(∨)、否(¬),将几个谓词组合成一个更大的谓词。因此,为了找到年薪超过9万美元的物理教师,我们写道:

\sigma_{depname = "Physics" \wedge salary > 90000} (instructor)

选择【select】的谓词还可以包括两个属性之间的比较。比如要查找部门名称与其建筑物名称相同的所有部门,我们可以这样写:

\sigma_{depname = building} (department)

2.6.2 Project

假设我们想要列出所有教员的ID、name 和 salary,但我们不关心 dep_name。映射【Project】操作允许我们产生这种关系【relation】。映射操作是一个一元操作,返回它的参数中的关系【relation】,其中省略了某些属性。由于关系【relation】是一个集合【set】,因此消除了任何重复的行。映射【Projection】用大写的希腊字母 pi (Π) 表示。我们将希望出现在结果中的那些属性作为 Π 的下标列出。映射【Project】操作的参数-关系则出现在括号中。

我们编写查询来生成这样一个列表:

\Pi _{ID, name, salary}(instructor)

图 2.11 显示了此查询产生的关系:

图 2-11 

基础版本的映射【Project】操作符 ΠL(E) 只允许属性名出现在列表 L 中。通用版本的操作符允许涉及属性的表达式出现在列表 L 中。例如,我们可以得到每个教职工的月薪资:

\Pi _{ID,name,salary/12}(instructor)

2.6.3 组合关系操作

关系操作【relational operation】的结果本身就是一种关系【relation】,这一点很重要。考虑更复杂的查询,查找物理系所有教师的姓名,我们写道:

\Pi _{name}(\sigma_{depname = "Physics"} (instructor))

注意,我们在这里没有将关系【relation】的名称作为映射【project】操作的参数,而是给出了一个求值为关系的表达式【expression】。


通常,由于关系代数操作的结果与其输入参数具有相同的类型(关系),因此关系代数操作可以组合在一起组成关系代数表达式。将关系代数运算组合成关系代数表达式就像将算术运算(如+、−、∗和÷)组合成算术表达式一样。

2.6.4 Cartesian-Product Operation

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值