第1章 做好准备
原文摘录
关系代数中闭包性质,有了闭包性质,我们才能编写嵌套的关系表达式,因为每个运算符的输出都与输入属于同一类型,一个运算符的输出可以作为另一个运算符的输入。
由于模型和实现分离,我们才能获得物理数据的独立性。
属性的个数成为“度”(degree),有时也称为“元”(arity)。主体中元组的数目称为“基数”(cardinality)。
关系的元组是完全无序的,该性质成立时因为主体被定义成了一个集合,而数学上的集合的元素时无序的。同样,关系的属性页没有从左到右的顺序,因为标题也是数学集合。
元组的子集仍然是元组。标题的每个子集仍然时标题。标题是n个属性的集合。
关系代数的运算符可以让我们从某些给定的关系开始,然后用这些给定的关系获得更多的关系。这些给定的关系称为“基关系”(base relation),而那些获得的关系成为“导出关系”(derived relation)。SQL中与基关系相对应的是基表。
笔记思考
关系是数学意义上的无序元组集合,每个元组由一组属性(列)构成:
- 属性无顺序
- 元组无顺序
SQL与关系模型的差异:
- 重复行:SQL允许重复元组,违背关系模型的集合定义
- NULL值:SQL中的三值逻辑(true,false,unknown)破坏关系模型的二值逻辑
数学中,允许重复元素的集合称为多集合(multiset)。 例如:多集合{a,a,b,c}。
第2章 类型和域
原文摘录
关系模型要求任何类型都必须支持相等性。
本质上,类型是值的已命名的有限集合,即某种类别的所有可能值。
每个类型都关联着一个运算符集合,用于操作该类型的值和变量。关系有关系代数运算符,而且任何类型都有赋值运算符(:=)和相等比较运算符(=)。没有运算符的类型是没有意义的。
在计算领域,一个广泛认可的原则是应当尽量避免隐式类型转换,因为它们很容易出错。特别是在SQL中,允许隐式类型转换的一个怪异的后果就是某些并、交和差运算会产生任何运算元中都没有出现过的行。
postgres=# create table ta(x integer, y numeric(5,1));
CREATE TABLE
postgres=# create table tb(x numeric(5,1), y integer);
CREATE TABLE
postgres=# insert into ta values (0,1.0),(0,2.0);
INSERT 0 2
postgres=# select * from ta;
x | y
---+-----
0 | 1.0
0 | 2.0
(2 rows)
postgres=# insert into tb values (0.0,0),(0.0,1),(1.0,2);
INSERT 0 3
postgres=# select * from tb;
x | y
-----+---
0.0 | 0
0.0 | 1
1.0 | 2
(3 rows)
-- 不同的数据库实现可能结果不同
postgres=# select x,y from ta union select x,y from tb;
x | y
-----+-----
0.0 | 0
0 | 1.0
0 | 2.0
1.0 | 2
(4 rows)
对于任何给定的字符串: a) 它由关联的一组字符集构成 b) 有一个关联的字符序。字符序是与特定字符集相关的规则,也称核对序列。它决定了字符集中的字符串的比较规则。
笔记思考
- 标量:不可再分解,无结构,代表单个值,例如整数、浮点数等
- 非标量:由多个标量值组成的数据结构,具体内部结构,可分解为多个标量,例如数组、集合等
第3章 元组、关系、行、表
从数学的角度说,元组集合即为关系。关系的主体是一个集合(元组的集合)。
主体的所有子集仍然是主体,泛泛来说关系的每个子集仍然是关系。
第4章 不要重复,不要null
强烈建议:
- 每个基表的每一列都指定NOT NULL。
- 不要使用外连接。
第5章 基关系变量和基表
关系变量指的是可以取值为关系的变量。
候选键定义:设K是关系变量R的标题的子集。那么当且仅当K具有以下两条性质时,它才是R的候选键:
- 唯一性: R中不存在K值相同的两个不同的元组。
- 不可约性:不存在任何K的子集也具有唯一性。
强烈建议:在SQL中,不论任何基表,都应该使用UNIQUE或PRIMARY KEY规范来确保每个表都至少有一个键。
大多数其他模型都拥有一定的特殊性,而不像关系模型那般建立在集合理论和谓词逻辑的基础之上。
第6章 SQL和关系代数I:原始运算符
设r是一个关系,则:
- 在r的全部属性上的投影会返回r,这种投影称作恒等投影。
可连接性: 关系r1和关系r2是可连接的,当且仅当同名属性是相同的类型(即它们实际上是同一个属性),或者说当且仅当r1和r2的标题在集合论意义下进行并运算得到的结果本身是合法的标题。
先连接再限制总是可以变换为先限制再连接。在关系代数中,限制对于交、并和差都可分配。在大多数情况下,先做限制都是一个好注意,因为通常可以:
- 减少运算序列中下一步运算所需扫描的元组数量
- 减少下一步运算的输出元组数量
第7章 SQL和关系代数II:附加运算符
关系模型中聚集运算符是从某种关系的某个属性的值的“聚集”。
第8章 SQL与约束
完整性约束基本上就是指必须取值为TRUE的布尔表达式。本质上,这种约束可以分为两大类:类型约束和数据库约束。
- 类型约束定义了构成指定类型的值。
- 数据库约束进一步限制了可以在特定数据库中出现的值。
数据库应该是企业在某个方面的表现形式,这种表现形式应该尽可能真实,从而才能保证基于数据库内容的正确决策,而约束就是用来确保数据库表示尽可能真实的最佳工具。
我们在定义一个类型的时候所要做的一件事是指定构成该类型的取值,这其实就是类型约束所要做的事情。
事务ACID:
- 原子性:事务要么全有要么全无。
- 一致性:任何事务都是将数据库由一个一致性状态转换为另一个一致性状态,而不必在任何中间时刻保持一致性。注意当且仅当数据库状态满足所有已定义的约束时,数据库的状态才是一致的。
- 隔离性:任何事务的更新在事务提交之前对于其他事务而言都是隐藏的。
- 持久性:一旦事务提交成功,那么即使后来系统崩溃,事务的更新结果也会保存在数据库中。
语义优化,语义优化意味着使用约束来简化查询,从而提高性能。
第9章 SQL与视图
原文摘录
物理数据独立性:指的是我们可以更改数据的物理存储与存取方式,但并不会改变用户感知数据的方式。 逻辑数据独立性:指的是我们可以更改数据的逻辑存储方式和存取方式,但并不会改变用户感知数据的方式。而提供逻辑独立性的理应是视图。
对于数据仓库、分布式系统以及在很多其他情形下,快照很重要。在这些情形下,应用程序经常可以忍受(有时甚至会要求)数据从某个时间点后保持不变。报表和会计应用就是这样的情况。这些应用通常要求数据在某个时刻冻结,而快照就允许在不锁定其他应用的情况下产生这种冻结。
视图运算的实现方式应该是通过将其映射为适合底层关系变量的运算。
第10章 SQL与逻辑
什么是关系演算?本质上,它是针对关系型数据库定制的应用形式的谓词演算,也称为谓词逻辑。
关系完备性是一种语言表达能力的基本指标:如果一种语言是关系完备的,那么就意味着任意复杂的查询都可以不借助任何迭代循环或分支进行表述。
第11章 使用逻辑表述SQL表达式
限制可以在并、交、差上分配。 投影在并上可以分配,但在交和差上不可以分配。
第12章 关于SQL的其他主题
实现时定义特性是其语义在不同实现中可以不同,但至少在任何实现中都必须指定的特性。换句话说,实现可以自行决定它如何实现这个特性,但是决定的结果必须用文档说明。
应该避免使用SELECT *,因为*的含义在向已有表中添加新列的情况下会发生改变,建议通过名称明确指定相关列。
区间变元:关系模型中的区间变元就是覆盖某关系中特定元组的集合(用SQL术语说就是某个表中特定的行集合)的变量。
SQL中的子查询是由括号括起来的表表达式。子查询可以分为三大类:
- 表子查询:不是子查询或标量子查询的子查询。
- 行子查询:出现在本应出现行表达式位置的子查询。
- 标量子查询:出现在本应出现标量表达式位置的子查询。
相关子查询是一种特殊类型的表、行或标量子查询。具体来说,它是包含了“外层”表的引用的子查询。
空集合是不包含任何元素的集合。
笔记思考
视图的核心价值:逻辑数据独立性、简化查询、访问控制。
视图的可更新性:有些视图可更新,有些则不能,取决于视图的定义方式以及底层数据库管理系统的支持。
从关系数据库理论来看,一个视图要支持更新操作,必须满足一系列严格的条件,一个视图可更新的典型理论条件包括:
- 基于单个基表:视图的 FROM 子句中只包含一个基表(不包括连接多个表)。
- 包含候选键:视图的查询结果必须包含基表的主键(或其他候选键)。这是为了唯一标识要修改的行。
- 不包含聚合:不能使用 GROUP BY、HALLING 以及聚合函数(如 SUM, COUNT, AVG 等)。
- 不包含集合操作:不能使用 UNION、UNION ALL、INTERSECT、EXCEPT 等。
- 不包含 DISTINCT 关键字:确保行是唯一的且可追溯。
- 不包含计算列:如果视图的列是由表达式或函数计算得出的,通常无法直接更新。更新操作必须明确知道如何修改基表中的原始列
对于理论上不可更新的视图,目前数据库普遍采用:INSTEAD OF触发器 的方案。
原理:你可以在视图上定义一个触发器,告诉数据库当有人尝试对视图进行INSERT、UPDATE、DELETE操作时,应该执行那些自定义的SQL逻辑来代替默认操作。
附录A 关系模型
数据库必须是关系型。
换句话说,常见的非关系型数据库不过是特定于应用程序的数据存储罢了,甚至可以说它们根本称不上数据库。
用数学的术语准确来说,有序对的集合是二元关系。定义如下: 覆盖两个集合A和B的二元关系是A与B的笛卡尔积的子集。换句话说,二元关系是满足如下条件的有序对(a,b)的集合。第一个元素a来自A的值,第二个元素b来自B的值。
关系模型由5个组件组成:
- 一个可扩充的标量类型集合,尤其包括BOOLEN类型。
- 关系类型生成器以及对所生产对应类型的关系的预期解释。
- 用于定义上述生成关系类型的工具。
- 用于为上述关系变量赋予关系值的关系赋值运算符。
- 用于关系值推导、关系完备的通用关系运算符。
以下是科学的方法:
- 经验性地观察特定的现象
- 构造理论或假设解释现象
- 使用理论进行预测
- 检验预测性的准确性
- 根据检验的结果,精炼我们的理论
- 如此迭代下去
附录B SQL背离关系模型之处
- SQL常常不把视图当作表。
- SQL对视图更新的支持非常薄弱、特殊且不完备。
- SQL基于三值逻辑,而关系模型基于二值逻辑。
- …
附录C 处理信息丢失的关系方法
笔记思考
在SQL标准中处理信息缺失的主要方法是NULL值。优点是:简单直观、存储高效(不占用额外存储空间)、广泛支持;缺点是:三值逻辑复杂性(true, false, unknown使查询逻辑复杂)、语义模糊(无法区分未知、不适用等不同含义)。