3.8 SQL中的表
注意:在本节中,提到“表”一词我指的都是表值(即SQL表值),而不是表变量(就是CREATE TABLE和CREATE VIEW创建的那个)。第5章会讨论表变量。
第2章说过,SQL中实际上根本没有什么东西能类比于关系的关系类型;相反,一个SQL表只是某种类型的行的集合(一般是行的包而未必是集合)。所以,尽管从第2章可知SQL支持其他类型生成器(包括ROW、ARRAY和MULTISET),但SQL还真没什么能类比于RELATION类型生成器。不过,SQL有表值构造器可以基本类比于关系选择器,示例如下:
VALUES ( 1 , 2 ), ( 2 , 1 ), ( 1 , 1 ), ( 1 , 2 )
此表达式(实际上是表字面值,尽管SQL没用这个词)得到一个有4个(不是3个)行和2个列的表。而且,这些列没有名字。我说过,SQL表的列是自左至右有序的;所以,这些列可以(有的时候是必须的)使用排序位置而不是名字来识别。
再来考量下述的表值构造器调用:
VALUES ( 'S1' , 'Smith' , 20 , 'London' ) ,
( 'S2' , 'Jones' , 10 , 'Paris' ) ,
( 'S3' , 'Blake' , 30 , 'Paris' ) ,
( 'S4' , 'Clark' , 20 , 'London') ,
( 'S5' , 'Adams' , 30 , 'Athens')
注意,为了能让这个表达式基本贴近其在关系模型中的类比项(如图1.3所示代表关系的关系字面值,而所代表的关系为关系变量S的当前取值),就必须:
- 对于VALUES表达式所指定的表列,确保所有值都是类型贴切的。(尤其是,如果某行的确定位置对应于关系相对项的属性A的话,那么我们必须确保所有这些行的相同位置都对应于同一属性A。)
- 确保没有两次指定相同的行。
注意:如你所知,关系模型中的标题是属性的集合。相反,因为SQL中的列具有自左至右的排序,所以在SQL中将标题看作属性(或列)的序列而非集合更为正确。不过,如果遵循本书的建议,这点逻辑区别基本上可以忽略。
表复制和比较运算符又是怎样的呢?表赋值是一个很大的主题,第5章会详细论述。SQL并不直接支持表比较(甚至对相等性比较的支持都没有)注9,但是有变通方案。比如,下面是与Tutorial D中的比较S{CITY }=P{CITY }相对应的SQL项。
NOT EXISTS ( SELECT CITY FROM S
EXCEPT
SELECT CITY FROM P )
AND
NOT EXISTS ( SELECT CITY FROM P
EXCEPT
SELECT CITY FROM S )
而下面是与Tutorial D中的比较S{SNO}※SP{SNO}对应的部分:
EXISTS ( SELECT SNO FROM S
EXCEPT
SELECT SNO FROM SP )
AND
NOT EXISTS ( SELECT SNO FROM SP
EXCEPT
SELECT SNO FROM S )
时间: 2024-09-20 09:11:25