SQL与关系数据库理论
最初模式的一个回顾
最初的模型有3个主要的组成部分:结构,完整性和操作。
结构特性
关系是定义在类型上(也可以称之为域),一个类型基本上是值的概念池,从这个池中实际的关系的属性可以获取它们的值。
一个n元关系可以描述为一个具有n个列的表;
关系模式支持各种各样的关键字。每个关系至少都有一个候选的关键字。一个候选的关键字是一个唯一的标识;换句话说,它是一个属性的集合,但常常不只是一个只有一个属性的集合。
一个主关键字是指那些可以用某种方法经过特殊处理被选出来的侯选的关键字。外键是指一个关系上的一个属性集,他们的值需要与别的关系(也可能是同一个关系)的侯选关键字的值匹配。
模式(第一个意义)是用户必须知道的。
实现是用户不必知道的。
数据模式是一些特殊企业数据(特别是那些永久数据)的模式。
完整性特性
最初形成的关系模式中包含两类一般的完整性限制,一个是主键,一个是外键。
实体完整性规则:主键属性不允许为空。
参考完整性规则:一定不能没有匹配的外键值。
外键的值可以被认为是相应侯选关键字同样的值的元组的参考。因此,有效的规则是:如果B参考A,那么A必须存在。空值是一个标志不知道的值(关键的是,它不是值本身,只是一个标记。)
操作特性
限制:返回一个关系,它包含所有的来自于某个特定的关系的满足某人特定条件的元组。
投影:返回一个关系,它包含一个特定的关系的所有元组,而这个关系是某些特定的属性已经被除掉了。
积:
交:返回一个关系,它的元组出现在这两个特定的关系中(交是一种特殊的连接)。
合并:返回一个关系,它包含所有这些出现在每一个关系中的元组。
差:返回一个关系,它的元组全部被第一个关系包含但没有被第二个关系包含。
连接
关系的特性
1. 每个关系都有一个关系头和关系体。
2. 头是一序列的属性(属性是一个属性名字/类型名字对)。
3. 关系体是指一序列的元组,这些元组都遵循这个关系头。
关系并不真正包含元组,它包含关系体,关系体依次包含这些元组。
l 关系头中的属性的个数称之为维度(arity)。
l 关系体中元组的个数称之为势。
l 关系不包含重复的元组:关系体被定义为一个元组的集合,而数学上集合是不包含重复的元素的。SQL是不遵循这个规则的。
l SQL表允许包含重复的行,因此总地来说就不是关系。
l 关系的操作也一直产生没有重复元组的结果。
l 关系中元组从上到下是没有顺序的(关系体被定义为一个集合,而集合中的元素是没有顺序的)。
l 关系的元组没有顺序并不意味着查询不能包含order by排序规范,但这样的查询的确可能产生的结果不是一个关系。它并不是一个关系操作。
l 关系的属性也是无序的,从左到右,因为关系头也是一个数学意义上的集合。
1FN:每一个关系的每一个元组在每一个属性的位置只能包含某个类型的一个值。
基础关系和产生关系
1. 关系系统提供了某种手段来首先定义基础关系。在SQL中,这个任务是通过create table语句(SQL提供的这个基础关系配对物自然是基表)来完成的。
2. 基础关系是需要命名的。
3. 一个视图(也叫做虚拟关系)是一个命名的关系,在一个给定时间t时的值是这个时间t时对于某个关系表达式计算的结果。
关系模式不关注物理实现。
Create table t
T 不是一个表,而是一个变量,一个表变量或者一个关系变量。它们的值也是关系(不同时间有不同的关系)。
在某个特殊的时间存在于这个数据库中的关系的值。
Delete s where city = ‘athens’
S := S where not (city = ‘athens’)
值是逻辑学家称之为单独的常量的东西。值没有时间和空间上的位置。
变量是值的表示的占有者。变量在时间和空间上有位置。变量不同于值,它是可以被更新的。换句话说,变量当前的值是可以被另一个值替换的。
类型和域
关系应该定义在域上,而不是类型上。
在关系模式中两个值都来自于同一个域的情况下才可以比较是否相等。
元组与关系、列和表
元组的准确定义:
假设T1,T2,…Tn(n>=0)是类型名,而且不必完全相同。给每一个Ti一个不同的属性名,Ai;这样n个属性名/类型名的组合中每一个都是一个属性。n个属性/值的组合中的每一个都是一个分量。这样就给出了所有n个分量的集合的定义,称之为t,它是一个元组值(简称元组),拥有属性A1,A2,…,An。值n是t的基数。基数是1的元组是一元组,基数是2的元组是二元的,基数是3的元组是三元的,…,基数是n的元组是n元的。所有属性的集合是t的关系头。
一个元组是一个值,和所有的值一样,它是有类型的。和其他类型一样,它是有名字的。
名字的格式TUPLE{H},这里{H}就是关系头。
TUPLE{SNO CHAR, SNAME CHAR, STATUS INTEGER, CITY CHAR}
这里指定的属性的顺序是任意的。
元组是一个值。和所有其他的值一样,它是应该可以被选择调用的。(如果值是元组,那么元组选择调用就是很自然的)。
TUPLE{SNO ’s1’, SNAME ’smith’, STATUS 20, CITY ‘London’}
(这里被指定的分量的顺序也是任意的)。
这里关键字TUPLE起到了两个作用,一是用作元组选择调用的连接符;二是用作元组的类型名。
每个分量只是一个属性名/表达式对,而且这里的表达式只表示了对应的属性值,而没有指定属性的类型。之所以这么做,是因为类型是可以从表达式中推断出来的。
SQL与逻辑
简单和复合的命题
一个命题就是一个无条件地求值为真或者为假的声明.
连接词
连接词Not, And, Or, If...then…(也称为implies或者=>) if and only if
P IMPLIES Q(等价于IF p then q)逻辑上等价于命题(Not p) OR q-只有在命题p的求值为真并且命题q求值为假的情况下整个命题求值为假。
连接词AND和OR都是可以交换的;也就说,复合命题p And q与q and p逻辑上都是等价的,并且复合命题p OR q与q OR p逻辑上也是等价的。这样的结果是你永远不要写出这样的违反p将在q之前求值或者相反求值方式的命题。
简单和复合的谓词
一个谓词是一个参数的集合。当它被调用的时候,实参替换这个形参;形参被替换成实参能有效地把一个谓词转换成一个命题。并且只有这个命题为真的情况下我们才能说这个参数满足这个谓词。
在逻辑中EXISTS x和FORALL x这样的表达式使用的术语是量词。
让我们假定p(x)是一个单一的谓词,那么这个表达式
EXISTS x(p(x))是一个命题,并且它的意思是:”至少存在一个对应于形参x的实参值使得p(a)求值为真”.
表达式 FORALL x(p(x))是一个命题,并且它的意思是”对应于形参x的所有可能的实参都使得p(a)求值为真”。
通过单独的量化可以从一个n阶谓词获得一个命题,必须对每一个形参都量化。更一般地,如果在m个形参上量化的话(m<=n),我们可以获得一个k阶谓词,这里k=n-m。
使用逻辑来形式化SQL表达式
l 隐含规律If p then q ≡ (not p) or q
l 双重否定规律 not (not p) ≡ p
l 笛摩根规律
l not (p and q) ≡ (not q) or (not q)
l not (p or q) ≡ (not p) and (not q)
l 交换定律
l P and (q or r) ≡ (p and q) or (p and r)
l P or ( q and r) ≡ (p or q) and (p or r)
l 限定规律
l Forall x(p(x) ≡ not Exists x(not p(x))
Not (p and not q) ≡ (not p) or q
(not p) or q ≡ not (p and not q)
If color = ‘red’ then city = ‘London’
(not (Color = ‘Red’)) or city = ‘Lodon’
Forall px(If color = ‘red’ then city = ‘London’)
Not Exists px (not (If color = ‘red’ then city = ‘London’))
SELECT SIC FROM T1 WHERE [NOT] EXISTS (SELECT * FROM T2 WHERE T2.C = T1.C AND BX)
EXISTS X(P) ≡ COUNT(X where p) > 0
Forall x(p) ≡ count(x where p) = count(x)
Unique x(p) ≡ count(x where p) = 1
闭包:每一个关系操作的结果都是一个关系。反之,产生的结果是不关系的,任何操作符定义上都不是关系运算符。
反之,产生的结果不是关系的,任何操作符定义上都不是关系操作符。例如,任何产生排序结果的操作符都不是关系操作符。
特别地在SQL中,任何可以重复的行,或者从左都右的列,或者产生空值,匿名的列,或者重复的列名字的操作符都不是关系操作符。
对于连接,输出的标题是所有输入的标题的联合。
定义:假设r是一个关系,并且A是这个关系的一个属性。那么r RENAME(A As B)的命名具有(a)关系的标题都类似于这个关系r的标题,除了标题中属性A被重命名为B之外,关系体都类似于r的关系体。
S Rename (City as SCity) select sno, sname, status, s.city as scity from s
Select p.pno, p.pname, p.color, p.weight,p.city /*s.city*/,s.sno,s.sname, s.status from p, s where p.city = s.city
Select p.pno, p.pname, p.color, p.weight,p.city /*s.city*/,s.sno,s.sname, s.status from p join s on p.city = s.city
Select p.pno, p.pname, p.color, p.weight,p.city /*s.city*/,s.sno,s.sname, s.status from p join s using (city)
Select p.pno, p.pname, p.color, p.weight,p.city /*s.city*/,s.sno,s.sname, s.status from p natural join s.
约束:
定义:假设r是一个关系,并且假设bx是一个布尔表达式,在这个表达式中,每一个属性引用都表示r的某个属性,并且没有任何关系变量的引用。那么bx就是一个约束条件,并且这个r依据bx的约束 r where bx是一个关系,它具有1.与关系r具有相同的标题;2,它的关系体由所有那些关系r的使得bx为真的元组组成。
P WHERE WEIGHT < 17.5
SELECT * FROM P WHERE WEIGHT < 17.5
投影
定义:假设r是一个关系,并且假设A,B,..C都是r的属性。那么r在这些属性上的投影r{A,B,…,C}是一个关系,它具有1.它的标题是{A,B,…,C}并且2.它的关系体是所有这样的元组x的集合,这个x满足:关系r中存在某个元组t的A属性上的值x元组中属性A的值,并且这个元组t在B属性上的值等于x元组中属性B的值…….并且这个元组t在C属性上的值等于X元组中属性C的值。
P{color, city} select distinct color, city from p
P{COLOR, CITY} 和P{ALL BUT PNO, PNAME, WEIGHT}
在具体的语法中,投影操作有更高的优先级。
S JOIN P {PNO}
其意义等同于
S JOIN(P{PNO})
连接
关系r和r2是可以连接的只有在它们具有同样名字和同样类型的属性前提下。等价地,只有它们的标题的并集本身是一个合法的标题时,才可以连接。
定义:假设r1和r2都是可连接的。那么它们的自然连接(或者缩写为连接),r1 join r2是一个具有如下特性的关系:1.其标题是r1和r2标题的集合理论上的并集.2,其关系体是所有的这些元组t的集合,这个元组t的集合r1的一个元组和r2的一个元组的联合。
P join s => Select p.pno, p.pname, p.color, p.weight,p.city s.sno,s.sname, s.status from p, s where p.city = s.city
Select * from P natutal join s
关系r1和关系r2的笛卡尔集(缩写为积)r1 TIMES r2,这里r1和r2没有共同的属性的名字,这个积是一个具有如下特性的关系:1.其标题是r1和r2标题的并集;2其关系体是r1中每一个元组和r2中每一个元组的并集。
(p rename (city as pcity) times (s rename(city as sctiy))
=> Select p.pno, p.pname, p.color, p.weight,p.city s.sno,s.sname, s.status from p, s
Join {r1, r2, …, rn}
Join {}
并
定义:假设关系r1和关系r2都是同样的类型;那么它们的并r1 union r2 是一个同样类型的关系,它们的关系体由所有这些出现在r1或r2或者同时出现在r1或r2中的元组组成。
P{status, city}union s{city, status}=>
Select status, city from p union corresponding select city, status from s
\
S{city} D_UNION P{CITY}