53
第第第第 第第第第第第 Associative Object Access 第第第第第第 GOM 第第第第第第第第第第 第第第第第第 第第第第第第第第 ,一 第第第第第第第 第 O-O DBMS 第 第第第 第第第第第第第第第 ,一 Select 第第第第第 GOM 第第第第第第第第 GOMql GOMsql 第第 GOMql 第第第第第第第 QUEL 第第第第第第第第第 GOMsql 第 SQL 第第第第第第第第第 第第第第第第第第第第 第第第第 (Type Extention) 第第 第第第第第第第第第第第

第十四章 关联对象访问 Associative Object Access

  • Upload
    wayne

  • View
    150

  • Download
    5

Embed Size (px)

DESCRIPTION

第十四章 关联对象访问 Associative Object Access. 本章重点讲述 GOM 对关联对象查询的支持,即如何实现一个查询和如何描述用户的查询要求 在 O-O DBMS 中,实现一个查询是通过多态的 Select 函数来实现的 GOM 支持二种查询语言 GOMql 、 GOMsql 其中 GOMql 是基于关系语言 QUEL 在面向对象上的扩展 GOMsql 是 SQL 在面向对象上的扩展 关联查询的操作对象为:类型范围 (Type Extention) ,用户定义的集合对象和表对象. 多态的关联选择操作定义及其实现. - PowerPoint PPT Presentation

Citation preview

Page 1: 第十四章 关联对象访问 Associative Object Access

第十四章 关联对象访问Associative Object Access

• 本章重点讲述 GOM 对关联对象查询的支持,即如何实现一个查询和如何描述用户的查询要求

• 在 O-O DBMS 中,实现一个查询是通过多态的 Select 函数来实现的

• GOM 支持二种查询语言 GOMql 、 GOMsql– 其中 GOMql 是基于关系语言 QUEL 在面向对象上的

扩展– GOMsql 是 SQL 在面向对象上的扩展

• 关联查询的操作对象为:类型范围 (Type Extention) ,用户定义的集合对象和表对象

Page 2: 第十四章 关联对象访问 Associative Object Access

多态的关联选择操作定义及其实现

• 关联选择操作需要一个操作对象说明—在某个对象实例集合上,需要一个条件表达式作为选择的依据—选择谓词

• 当定义一个多态的选择操作时,选择谓词将以函数变元的方式作为操作变元

• 当选择谓词本身需要参数时,该参数必须在选择操作的参数表中说明

• 多态的选择操作的共同名字为 Select

Page 3: 第十四章 关联对象访问 Associative Object Access

无参数的选择谓词—简单的布尔函数

• 多态选择操作说明为Polymorph overload select (\t1<={\t2}) : \t1 || ( \t2 || -> bool ) -> \t1

Code selectNoParam

• 语义为– 类型 \t1 ,是一个集合类型,其元素类型为 \t2– Select 操作有两个变元:接受者类型为 \t1 ,

另一个变元是一个布尔函数,它对类型为 \t2的对象进行选择,返回一个布尔型结果

– Select 语义对 t1 的元素用布尔函数进行筛选;

Page 4: 第十四章 关联对象访问 Associative Object Access

多态选择操作的实现 define selectNoParam(selPred) is var result: \t1; candidate: \t2; begin result.create; !! 生成空结果集 foreach (candidate in self) if candidate.selPred then result.insert(candidate); return result; end define selectNoParam

Page 5: 第十四章 关联对象访问 Associative Object Access

应用举例• 在立方体实例库中,查找某一个顶点是原点的立

方体• 分析:其选择谓词需要顺次检查一个立方体的 8

个点,是否有一个点的 x 、 y 、 z 坐标值为 0 ,0±ε —— inOrigin 操作

• 其结果应当是下面二个集合的交集:– 包含在立方体实例集合中的实例—— myCuboid 所引

用– 满足谓词 inOrigin 的实例

• 多态的 Select 操作可以应用于任何一个集合类型

Page 6: 第十四章 关联对象访问 Associative Object Access

• inOrigin 定义declare inOrigin: Cuboid || bool;

define inOrigin is !!判断任何一个顶点是否处于坐标原点 return (( self.v1.x=0.0 ±ε and self.v1.y=0.0 ±ε and self.v1.z=0.0 ±ε) OR … ( self.v8.x=0.0 ±ε and self.v8.y=0.0 ±ε and self.v8.z=0.0 ±ε));

• 变量定义和引用var myCuboids, theCuboidsInOrigin:CuboidSet;

……theCuboidsInOrigin:=myCuboids.select(inOrigin);

Page 7: 第十四章 关联对象访问 Associative Object Access

示例 2—— 查询退休职员

declare isRetired: Employee || bool;

var retiredEmps: EmployeeSet;

retiredEmps:=ext(Employee).select(isRetired);

Page 8: 第十四章 关联对象访问 Associative Object Access

示例 3—— 无名的选择谓词的使用

• 当布尔选择谓词比较简单,则可以 λ 符号来实现操作过程的传递

• 示例:选择红色苹果的选择操作Ⅰ. 选择谓词用命名 isRed 表达

declare isRed: Apple ||bool;

define isRed is

Ⅱ. 选择谓词用 λ 表达——直接传递过程redApples:=myApples.select (λ x: x.color = “red”)

GoldCuboid=mycuboid.select (λ x: x.met.name = “gold”)

Page 9: 第十四章 关联对象访问 Associative Object Access

带参数的选择谓词• 该参数是为选择谓词服务的,所以需要在

谓词函数中说明• 由于在引用时,显然需要由 Select 来引用,

因此,在 Select 的参数表中也要说明,规则如下:

poly overload select (\t1<={\t2}):\t1||(\t2||\t3 -> bool), \t3 -> \t1

• 语义:其中类型 \t3可以是任何类型,它的约束条件是 Select的第三个参数类型 \t3,必须与选择谓词所需一个参数类型一致

Page 10: 第十四章 关联对象访问 Associative Object Access

Select 的重载• Select 函数不但是多态的,而且是重载的,

它可以根据选择谓词的需要,设定多个参数

• 编译器根据重载规则,从参数的个数,寻找到正确的实现版本

• 其约束条件为:在哑、实结合时, Select的参数个数和各自类型必须与选择谓词的参数个数、类型完全一致

Page 11: 第十四章 关联对象访问 Associative Object Access

示例 1—— 一个参数的选择谓词• 对 Cuboid 定义一个选择谓词 bigCuboid ,

它能选择体积大于某个阈值的立方体对象– 定义

declare bigCuboid: Cuboid || float -> bool

code bigCuboidCode; define bigCuboidCode(threshold) is

return(self.volume > threshold);– 引用

var myCuboids, myBigCuboids: CuboidSet; …… myBigCuboids:= myCuboids.select(bigCuboid, 200.0);

Page 12: 第十四章 关联对象访问 Associative Object Access

示例 2—— 二个参数的选择谓词• 选择体积在一个范围 ( 上限 high ,下限为 l

ow) 的立方体declare volumeRange: Cuboid || float, float -> bool;

define volumeRange(low, high) is

return (self.volume<=high and self.volume >=low);

Page 13: 第十四章 关联对象访问 Associative Object Access

迭代 Iterators• 可以在筛选的基础上利用循环进行各种进一步的操

作• 例如:求符合体积要求的 Cylinders 的体积累加值

declare bigCyl: Cylinder || float -> boolcode bigCylCode;

define bigCylCode(threshold)return(self.volume>= threshold);

…… var c: Cylinder;

myCylinders: CylinderSet;bigCylindersTotalWeight: float:=0.0;

……foreach (c in myCylinders.select(bigCyl, 20.0))

bigCylindersTotalWeight:=bigCylindersTotalWeight + c.weight;

Page 14: 第十四章 关联对象访问 Associative Object Access

说明性查询语言 GOMql

• 多态选择函数只是一个关联查询实现的基础,对于复杂的嵌套查询及其优化,表达力度不够,需要通过定义相关的查询语言来实现

• 查询优化有两个方面解决– 关系代数的优化:编译时进行– 物理查询路径的优化:执行时进行

• 下面的内容从用户角度出发,如何查询需求正确地用相应的查询语言序列来表达

• GOMql 是基于 QUEL 的扩展

Page 15: 第十四章 关联对象访问 Associative Object Access

一个对象实例库• 类型定义

Type Emp is

{name:string ; working:Dept; salary:int;} type Dept is {name:string; mgr:Manager; profit:int;};

Type Manager

Supertype Emp is [cars:{Car};];

type Car is [license:string; make:string; horsepower:int;];

Page 16: 第十四章 关联对象访问 Associative Object Access

• 路径表达式为查找引用链的引用序列示例:

P≡ Emp.worksIn.mgr.cars.make

• 示例的类型定义中,关联对象的联接,仅仅采用一个进入点的方式

worksIn------------

mgr-----

cars---->

make--Emp Dept Manager Car string

EMPworkIn

Dept

N 1

Deptmgr

Manager

1 1

Managercars

Car

N M

Page 17: 第十四章 关联对象访问 Associative Object Access

GOMql 表达式• 单目标查询表达式

rang r1:s1,…,rm:sm

retrieve ri

where p(r1,…, rm)

• 多目标查询表达式rang r1:s1,…,rm:sm

retrieve a1:r1,…,aj:rj

where p(r1,…, rm)

• Range子句:范围说明子句其中: rj( 1≤j≤m)为范围变量表达式,它用于 range子句中

Page 18: 第十四章 关联对象访问 Associative Object Access

其中, sj( 1≤j≤m)必须是下列情况之一1. Sj 是一个类型扩展 EXT( 用类型名表达 )

2. 一个集合对象变量3. 一个列表对象变量4. 一个包含有集合结构的对象变量5. 一个包含有表结构的对象变量6. 一个计算一个集合结构对象的表达式7. 一个计算一个表结构对象的表达式

总之,变量 rj被约束到一个相应的聚集类型sj 的元素类型

Page 19: 第十四章 关联对象访问 Associative Object Access

• retrieve子句 查询说明子句– 简单形式:只有一个范围变量——单目标查询– 复杂形式:通过投影到多个范围变量,构造的

多元组——多目标查询– 实现方法:对目标的范围变量与相应的对象分别进行捆绑,并进行选择谓词查询

• Where子句:选择谓词中, P 的变元 (r1…rm)∈(s1xs2…xsm)(m个联接 )当目标 rj( 或者多目标 r1…rj)与某一对象捆绑,使 P (r1…rj) 为真,则该对象被选中

Page 20: 第十四章 关联对象访问 Associative Object Access

GOMql 查询示例 ( 一 )

• 简单选择谓词示例查询所有工资超过 100000 的 Empsrange e:Emp

retrieve ewhere e.salary>100000.0

查询结果为 {id3,id4,id8,id9,id10} • 上述查询需要输出姓名,则为:

range e:Empretrieve e.namewhere e.salary>100000.0

name

“LeMond”“Hinault”“Boss”

Page 21: 第十四章 关联对象访问 Associative Object Access

GOMql 查询示例 ( 二 )• 问题:找出其经理为驾驶 Jaguar汽车的 E

mps

• 该查询的路径表达式为:p=Emp.workIn.mgr.cars.make = “Jaguar”

• 查询表达式为:range e:Emp

retrieve e

where “Jaguar” in e.worksIn.mgr.cars.make

Page 22: 第十四章 关联对象访问 Associative Object Access

• 系统检测范围变量 e 的每个捆绑的对象,通过路径可以达到的串值是否为给定的“ Jaguar” ,若是,则该对象被选中

• 该选择查询代价巨大,它需要进行如下多个联接:Emp x Dept x Manager x Car

• 选择结果为 {id1,id2,id8}

Page 23: 第十四章 关联对象访问 Associative Object Access

更复杂的查询 ( 一 )

• 例 3 :找出选择的经理:他的部门亏损,但仍支付给至少一个雇员工资超过二十万元range e:Emp,m:Manager

retrieve m

where m=e.workIn.mgr and

e.salary>200000.0 and

e.workIn.profit<0.0• 这里, m=e.worksIn.mgr称为功能联接 (对象的“相等”操作子隐含地表示为“标识” )

Page 24: 第十四章 关联对象访问 Associative Object Access

• 例 3 的优化处理• 如果在 Dept 类型中增加一个关联属性 {Em

p} ,则例 3 可以表示为:range d:Dept,m:Manager

retrieve m

where m=d.mgr and

d.profit<0.0 and

d.Emp.salary>200000.0

Page 25: 第十四章 关联对象访问 Associative Object Access

更复杂的查询 ( 二 )

• 例 4 :查找这样的经理:他驾驶过贵重的汽车,而他管理的部门获利很低range d:Dept,m:Manager,c:Car

retrieve m

where m=d.mgr and

d.profit<100000.0 and

c in m.cars and

(c.horsepower>150 or c.make=“Jaguar”)

Page 26: 第十四章 关联对象访问 Associative Object Access

量词的使用(一)• ( 一 ) 全称量词表达式

for all rj in sj p语义为:若集合 sj 中所有成员 rj均满足选择谓词 p(r

j) ,则表达式为真,否则为假示例:查询其经理只开宝马车的雇员range e: Emps,c: Char

retrieve ewhere forall c in e.worksIn.mgr.cars

(c.make=”BMW”)

Page 27: 第十四章 关联对象访问 Associative Object Access

量词的使用(二)• ( 二 )存在量词表达式 EXIST rj IN sj P(rj)语义为:若在集合 S 中至少有一个成员 rj 满足 P(rj) ,

则表达式为真 , 否则为假示例:查询其经理所用额轿车中有一辆为美洲虎的雇员

range e: Emps,c: Carretrieve ewhere exists c in e.worksIn.mgr.cars

(c.make=”Jaguar”)

Page 28: 第十四章 关联对象访问 Associative Object Access

嵌套查询• 在任何一个集合可以出现的地方,都可以

使用 range-retrive-where 表达式,因此,Gomql允许表达式嵌套

• 表达式嵌套可以发生在三个子句的任何一个中,因为三个子句本身均要求一个集合表达式

• 示例:查询那些只驾驶美洲虎牌或宝马牌,或马力 >200 的汽车经理

Page 29: 第十四章 关联对象访问 Associative Object Access

range m: Manager , c: Carretrieve mwhere forall c in m.cars

(c in (range v: Car

retrieve vwhere v.horsePower>200 or

v.make=”Jaguar” or v.make=”BMW”))

Page 30: 第十四章 关联对象访问 Associative Object Access

查询表达式中聚集函数和类型操作的使用

• 关系查询语言 QUEL仅提供少量的聚集函数如 count , sum , min , max , avg等

• Gomql允许类型操作作为函数使用。其约束条件为:类型操作不会改变对象的状态,且应当返回一个值

• 函数的范围:在 where子句和 retrieve子句中都可以使用

• 由于类型操作含有子类型的继承,因此,在执行时,每个对象实例仍然需要动态捆绑相应精化的操作

Page 31: 第十四章 关联对象访问 Associative Object Access

示例• 示例 1 :查许体积大于 150.0 的圆柱体range c: Cylinder

retrieve c

where c.volume>150.0• 示例 2 :查询所有金子做的几何体的总重量range g: GeometricPrimitive

retrieve sum(g.weight)

where g.mat.name=”Gold”

Page 32: 第十四章 关联对象访问 Associative Object Access

基于 SQL 的对象查询语言 GOMsql

• GOMsql 是 O2SQL 的一个子集,它是针对 Gom 的 ODL设计的查询语言

• GOMsql 的目标是向用户以供基于 SQL 的声明和面向集合的查询接口

• 面向对象的基于 SQL 的查询语言强调的是对象类型,而对象-关系的 SQL 扩展( SQL-99)强调的仍然是关系,即如何通过关系模型的扩展将对象和类引入

• 其他的面向对象的查询语言 --OQL。它是针对 ODL 设计的查询语言,而 ODL 是 IDL( 接口描述语言) --CORBA的一个组件的扩展。

*CORBA 是分布式面向对象的计算的一种标准

Page 33: 第十四章 关联对象访问 Associative Object Access

• 示例数据库--边界标识的几何体数据库

type BRep with extension isbody

[name: string; weight: float; faces: FaceSet;];

…end type BRep;

type FaceSet is body

{Face}…

end type FaceSet;

type EdgeSet isbody

{Edge}…

end type EdgeSet;• 查找引用链

type Face is body

[surface: float; edegs: EdgeSet;];

…end type Face;type VertexSet is

body {Vertex}

…end type VertexSet;type Edge is

body [length: float; vertices: VertexSet;];

…end type Edge;type Vertex is

body[x,y,z: float;];

…end type Vertex;

Page 34: 第十四章 关联对象访问 Associative Object Access

GOMsql 的基本查询结构• GOMsql 的基本结构为: select-from-where--记为 SFW 表达式

• 示例– select b.weight

from b in BRepwhere b.name = “cubo#5”

• 在 Select子句中,可以引入类型操作函数• 在 from子句中,给出了一个显式定义的范围变量

b , b属于 BRep 类型的对象实例集• 在 where子句中, b 的名字要等于 cubo#5

Page 35: 第十四章 关联对象访问 Associative Object Access

与 GOMsql等价的 SQL 查询表达式(1) select weight

from BRepwhere name = “cubo#5”

(2) select b.weightfrom BRep as bwhere b.name = “cubo#5”

• 范围变量在 SQL 中被称为别名( aliases)– 方式( 1)没有显式的范围变量– 方式( 2)通过别名,定义了一个显式的范围变量 b

Page 36: 第十四章 关联对象访问 Associative Object Access

GOMsql 与 SQL 的主要区别• SQL : From子句中范围变量必须约束到一个已存在的,旦已被命名的元组赋值的对象集合上,即捆绑到一个关系或一个已建立的 视图上– 结论: SQL 的 From子句中不允许嵌套 SFW 的结构

• GOMsql : From子句中的范围变量可以定义在任何的对象集合上。即无论是持久的命名集合,还是一个临时建立的对象集合,即允许捆绑到另一个 SFW 表达式上。– 结论: GOMsql 的 From子句支持 SFW 结构的嵌套– ∆ 范围变量在 From子句中必须显式说明

Page 37: 第十四章 关联对象访问 Associative Object Access

范围变量的形式化定义• GOMsql 中,范围变量被捆绑到 From子句中的对象集合上

• 形式化描述为:– <form-clause>::

from<rangeVar>in<objectCollection>

{ , <rangeVar> in < objectCollection >}– < objectCollection >::=(<SFW>)|<Set>|<List

>

Page 38: 第十四章 关联对象访问 Associative Object Access

嵌套查询表达式• 示例:查找重量大于 1000 的几何体中表面积大

于 10 的表面集合。• 方法:先查找重量大于 1000 的几何体,再从中挑出表面积大于 10 的子集

• Select fForm f in

(select b.facesfrom b in Brepwhere b.weight>1000)

where f.surface>10

Page 39: 第十四章 关联对象访问 Associative Object Access

• 这里,外层范围变量 f被限定在内部的 SFW表达式所返回的 Face 对象集合上。

• 需要注意的约束条件是:保证范围变量必须有一个唯一的类型,这个类型可以在编译时推导出来

• 一个嵌套查询表达了查询的路径表达式是

faces

• 更广泛地,一个范围变量不仅被限定在通过路径表达式检索的对象集合上,而且可以捆绑在任何一个集合上。

Brep Face

Page 40: 第十四章 关联对象访问 Associative Object Access

示例 2• 查询重量在 100- 1000之间的几何体• 笨办法:先找出重量大于 100 的几何体,再从

中挑出小于 1000 的来• select b2.name

form b2 in(select b1from b1 in Brepwhere b1.weight>100)

where b2.weight<1000• 优化的结果• select b.name

form b in Brepwhere b.weight<1000 and b.weight>100

Page 41: 第十四章 关联对象访问 Associative Object Access

范围变量可以限定到实例集合的属性域上

• 示例:查询立方体 cubo#5 的 8 个顶点坐标。select v.x, v.y, v.z

from v in( select e.vertices from e in

( select f.edges from f in

( select b.faces from b in BRep where b.name="cubo#5" ) ) )

Page 42: 第十四章 关联对象访问 Associative Object Access

• 从最内层的 SFW开始( 7-9句): b被限定在 BRep 的类型扩展上

• 谓词 b.name=Cubo#5 将 b 限定到满足谓词的BRep 的一个子集上,返回每个几何体的 6 个面 f1-f6。

• 5- 6 行的 SFW 接受由内层返回的 6 个面,并计算它们的边的并集:

产生 12 个不同的 edge 对象

• 语句 3- 4产生 24 个点的并集--为 8 个不同的点

• 语句 1- 2产生 8 个点 x.y.z 值

},,{ 61

.f ff

edgesf

Page 43: 第十四章 关联对象访问 Associative Object Access

嵌套查询和路径表达式• 如下抽象的类型模式• type T0 is … type Tn-1 is type Tn is body body body

[… ; [… ; […]

A1: {T1} ; An: {Tn} ; … …] ; … ] ; end type Tn

… …

end type T0 end type Tn-1

• 即元组类型 Ti 通过它的属性 Ai+ 1产生对类型 Ti 的引用

Page 44: 第十四章 关联对象访问 Associative Object Access

• 一个嵌套查询的 SFW 表达式• 假如从引用链的始端 T0开始,到 Tn终止,查询

一个原子类型 SomeAttr 的值,那么它的查询如下:– select an.someAttr

from an in

( select an-1.An

from an-1 in

( select a1.A2

from a1 in

( select s.A1

from s in someSet ) )…)

• 利用路径表达式,其查询可以缩短为:– select an.someAttr

from an in someSet.A1.A2.….An

Page 45: 第十四章 关联对象访问 Associative Object Access

嵌套查询的数学表示• 数学上的表示:结果集合可以表示为并

集 Un ,其中 Ui被递归定义成:

11

.1

:

ii Ua

i n)ifor(1 Aia

0)if(i someSet

iu

Page 46: 第十四章 关联对象访问 Associative Object Access

不同的 Join 类型• 不同类型的联系

– 基于值的 Join :关系查询传统的 Join 操作– 标识 Join– 函数 Join

Page 47: 第十四章 关联对象访问 Associative Object Access

基于值的 Join

• 传统的连接操作,通过给定的 Join属性的值的比较来联系对象

• 示例:查询两个 BRep 对象,它们之间,第二个变量为第一个的两倍

• select b1.name,b2.name     from b1 in BRep,          b2 in BRep     where b1.weight * 2.0 = b2.weight+є

• 对象 b1 , b2之间通过变量值来关联

Page 48: 第十四章 关联对象访问 Associative Object Access

标识 Join-- 同一 Jion

• 标识 Join-- 基于对象的相等,而不是值相等,因此,是基于 OID 值相等的连接

• 示例 .– 谓词 O1= O2-- 表示 O1 与 O2OID 相等而不是 O

1 与 O2 的状态相等– 谓词 OЄ<Object>-- 当且仅当 O 是 Object 集

合中的一个对象实例时为真,而不是说 Object中有一个对象状态与 O 的状态相等

Page 49: 第十四章 关联对象访问 Associative Object Access

标识 Join 示例• 父,母,子三个对象类型及其实例库• type Man with extention is

      [name:  string;...;hasKids:{Child};]; type WOMan with extention is      [name:  string;...;hasKids:{Child};]; type Child with extention is      [name:  string;...;father:Man;mother:Woman;];

Page 50: 第十四章 关联对象访问 Associative Object Access

• 查询同一个父亲的两个孩子 C1 , C2

• select c1.name,c2.name    form c1 in child;c2 in child    where c1.father=c2.father and c1!=c2  

• 这里 c1.father= c2.father 是标识相等,而不是值相等

• 如果是这样的谓词Where c1.father.name=c2.father.name and

c1!=c2 -- 值相等查询

Page 51: 第十四章 关联对象访问 Associative Object Access

• 查询一个孩子的父母亲• select m.name,w.name,c.name

    from m in Man,w in Woman,c in Child    where c in m.hasKids and c in w.hasKids

• 利用重载操作,测试对于 woman 集合和 man集合,是否包含有同一个孩子的偶对。

• 也可以通过孩子类型的引用点来完成上述查询• select m.name,w.name,c.name

    from m in Man,w in Woman,c in Child    where c.father=m and c.mother=w

Page 52: 第十四章 关联对象访问 Associative Object Access

函数联接• 利用引用链建立两个对象集合间的联接• 当引用路径表达式中如果有集合属性,

则需要连接• 示例

select b.name,f.name   from b in BRep,        f in b.faces   where f.surface > 20

• 范围变量 b 与 BRep 类型对象集合捆绑,而 b.faces 寻找通过 faces属性与 b 相关联的 Face 类集合

Page 53: 第十四章 关联对象访问 Associative Object Access

总结 -- 面向对象的查询与关系查询的区别

(1) 查询对象集– 关系的元组– 对象集,包括了继承的子对象集

(2) 谓词表达:面向对象的查询在谓词里允许类型属性的引用链组成的路径表达式。

(3) 谓词表达式允许对象的操作作为表达式的一个因子

(4) 范围变量允许由中间结果产生的集合来说明,即在 From子句中允许嵌套 SFW 表达式

(5) 标识 Join(6) 函数 Join