目录
数据库系统
一、引言
- 数据库管理系统(DBMS) 由一个相互关联的数据的集合和一组用以访问这些数据的程序组成,这个数据集合通常称作数据库(database) ,其中包括了关于某个企业的信息。
- DBMS的基本目标是要提供一个可以方便、有效地 存取数据库信息的环境。
- 设计数据库系统的目的是为了管理大量信息。对数据的管理即涉及到信息存储结构的定义,又涉及信息操作机制的提供。另外,数据库系统还必须提供存储信息的安全性保证。
1、文件处理系统弊端
- 数据冗余和不一致
- 数据访问困难
- 数据孤立
- 完整性问题
- 原子性问题
- 并发访问异常
- 安全性问题
2、数据视图
数据库系统是一些相互关联的数据以及一组使得用户可以访问和修改这些数据的程序的集合。数据库系统的一个主要的目的是给用户提供数据的抽象视图, 也就是说,系统隐藏关于数据存储和维护的某些细节。
-
数据抽象
为了高效地检索数据在数据库系统中设计使用复杂的数据结构来表示数据,并简化用户与系统的交互,将其分为几个层次:
1. 物理层
最低层次的抽象,描述数据实际上是怎么存储的,屋里层详细描述复杂的底层数据结构
2. 逻辑层
比物理层稍高的抽象,描述数据中存储什么数据及这些数据间的关系。虽然逻辑层的简单结构的实现可能涉及复杂的物理层结构,但逻辑层的用户不必知道这样的复杂性。这被称作物理数据独立性 。
3. 视图层
最高层次的抽象,值描述整个数据库的某个部分。
关系图如下:
-
实例与模式
特定时刻存储在数据库中的信息的集合称作数据库的一个实例(instance)。而数据库的总体设计称作数据库模式。数据库模式即是发生变化,也不频繁。
根据之前讨论的不同的抽象层次,数据库系统可以分为几种不同的模式。- 物理模式:在物理层描述数据库的设计
- 逻辑模式:在逻辑层描述数据库的设计
- 子模式:在视图层描述数据库
-
数据模型
数据库结构的基础是数据模型(data model) 。数据模型是一个描述数据、数据联系、数据语义以及一致性约束的概念工具的集合。数据模型提供了一种描述物理层、逻辑层及视图层数据库设计的方式- 关系模型
关系模型是用表的集合来表示数据和数据间的联系。每个表有多少个列,每列有唯一的列名。关系模型是基于记录的一种模型。 - 实体-联系模型
实体-联系(E-R)数据模型基于现实世界的一种认知:现实世界由一组称作实体的基本对象以及这些对象间的联系构成。 - 基于对象的数据模型
面向对象的程序设计(特别是java、C++或C#)以及占据主导地位。面向对象的数据模型可以看做是E-R模型增加了封装、方法和对象标识等概念后的扩展。对象关系模型结合了面向对象的数据模型和关系数据模型的特征。 - 半结构化数据模型
半结构化数据模型允许那些想同类型的数据项含有不同的属性集的数据定义。**可扩展标记语言(xml)**被广泛用来表示半结构化数据。
- 关系模型
3、数据库语言
数据库系统提供数据定义语言 来定义数据库模式,以及数据操纵语言来表达数据库的查询和更新。
-
数据操纵语言
数据操纵语言(DML),它使得用户可以访问或操纵那些按照某种适当的数据模型组织起来的数据。有以下访问类型:- 对存储在数据库中的信息进行检索
- 对数据库中插入新的信息
- 从数据库中删除信息
- 修改数据库中存储的信息
通常有两种基本的数据操纵语言:
- 过程化DML 要求用户指定需要什么数据以及如何获取这些数据
- 声明式DML ,也被称为非过程化DML,只要求用户指定需要什么数据,而不指定如何获取这些数据
-
数据定义语言
数据库模式是一系列定义来说明的,这些定义有一种称作数据定义语言(DDL)的特殊语言来表达。DDL也可用于定义数据的其他特征。
存储在数据库中的数据值必须满足某些一致性约束 :- 域约束
每个属性都必须对应一个所有可能的取值构成的域(例如:整数型,字符型,日期/时间型)。域约束是完整性约束的最基本形式。 - 参照完整性。
一个关系中给定属性上的取值也在另一关系的某一属性集的取值中出现(参照完整性) - 断言
一个断言就是数据库需要时刻满足的某一条件。域约束和参照完整性约束是断言的特殊形式。 - 授权
我们也许相对勇士加以区别,对于不同的用户在数据库中的不同数据值上允许不同的访问类型。这些区别以授权 来表达,最常见的是:读权限(允许读取数据,但不能进行修改),插入权限(允许插入数据,但不允许修改),更新权限(运行修改,但不能删除)
- 域约束
4、关系数据库
关系数据库基于关系模型,使用一系列表来表达数据以及这些数据直接的联系。关系数据库也包括DML和DDL。
- 表
每个表有多个列,每个列有唯一的名字。 - 数据操纵语言
SQL查询语言是非过程化的。它以几个表作为输入(也可能只有一个),总是仅返回一个表 - 数据定义语言
SQL提供了一个丰富的DDL语言,通过它,我们可以定义表、完整性约束、断言,等等。
5、数据库设计
数据库系统被设计用来管理大量的信息。这些大量的信息并不是孤立存在的,而是企业行为的一部分;企业的终端产品可以是从数据库中得到的信息,或者是某种设备或服务,数据库对它们起到支持的作用。
数据库设计的主要内容是数据库模式的设计。
- 设计过程
- 大学机构的数据库设计
- 实体-联系模型
- 规范化
6、数据存储与查询
-
存储管理器
存储管理器是数据库系统中负责在数据库中存储的低层数据与应用程序以及向系统提交的查询之间的提供接口的部件。存储管理器负责与文件管理器进行交互。原始数据通过操作系统提供的文件系统存储在磁盘上。存储管理器将各种DML语言翻译成底层文件系统命令。因此、存储管理器负责数据库中数据的存储、检索和更新。
存储管理部件包括:
1. 权限及完整性管理器
它检测是否满足完整性约束,并检查试图访问数据的用户的权限
2. 事务管理器
它保证即使发生了故障,数据库也保持在一致的(正确的)状态,并保证并发事务的执行不发生冲突
3. 文件管理器
它管理磁盘存储空间的分配,管理用于表示磁盘上所存储信息的数据结构
4. 缓冲区管理器
它负责将数据从磁盘取到内存区,并决定哪些数据被缓冲存储到内存中。缓冲区管理器是数据库系统的一个关键部分,因为它使数据库可以处理比内存更大的数据
5. 数据文件
存储数据库本身
6. 数据字典
存储关于数据库结构的元数据,尤其是数据库模式
7. 索引
提供对数据项的快速访问 -
查询处理器
查询处理器组件包括:- DDL解释器,
它解释DDL语句并将这些定义记录在数据字典中 - DML编译器
将查询语句中的DML语句翻译为一个执行方案,包括一系列查询执行引擎能理解的低级指令
一个查询通常可被翻译成多种等价的具有结果的执行方案的一种。DML编译器还进行查询优化,也就是从几种选择中选出代价最小的一种 - 查询执行引擎
执行由DML编译器产生的低级命令
- DDL解释器,
7、事务管理
事务是数据库应用中完成单一逻辑功能的操作集合。每一个事务是一个即具原子性又具一致性的单元。
原子性和持久性的保证是数据库系统自身的职责,确切的说,是恢复管理器的职责。
8、数据库体系结构
数据库系统各个部分以及它们之间联系的图,如下:
系统体系结构图。
9、数据挖掘与信息检索
数据挖掘这个术语指半自动化地分析大型数据库并从中找出有用的模式的过程。和人工智能中的知识发现(也称为机器学习)或者统计分析一样,数据挖掘视图从数据中寻找规律或模式。
10、特种数据库
数据库系统的一些应用领域受到关系型数据库模型的限制。其结果是,研究人员开发了几种数据模型来处理这些领域的应用,包括基于对象的数据模型和半结构化数据模型
11、数据库用户和管理员
数据库系统的一个主要目标是从数据库中检索信息和往数据库中存储新信息。使用数据库的人员可以分为数据库用户和数据库管理员
12、数据库系统的历史
--------------------------------- 关系数据库 ------------------------------------------
二、关系模型介绍
1、关系数据库的结构
关系数据库由表(table) 的集合构成,每个表有唯一的名字。
一般来说,表中一行代表了一组值之间的一种联系。由于一个表就是这种联系的一个集合,表这个概念和数学上的关系这个概念是密切相关的, 这也正是关系数据模型名称的由来。
在关系模型术语中,关系用来指代表,而元组用来指代行,属性用来指代表中的列
2、数据库模型
当我们谈论数据库时,我们必须区分数据库模型和数据库实例,前者是数据库的设计逻辑,后者是给定时刻数据库中数据的一种快照
关系的概念对应于程序设计语言中变量的概念,而关系模式的概念对应于程序设计语言中类型定义的概念
关系模式由属性序列及各属性对应域组成。关系实例的概念对应于程序设计语言中变量的值的概念
3、码
一个元组的属性值必须是能够唯一区分元组的。
超码是一个或者多个属性的集合,这些属性的组合可以使我们在一个关系中唯一地标识一个元组。
主码代表被数据库设计者选中的、主要用来在一个关系中区分不同分组的候选码。
外码,一个关系模式可能在它的属性中包括另一个关系模式的主码,这个属性就被称作外码。
4、模式图
一个含有主码和外码依赖关系的数据库模式可以用模式图来表示。
大学组织的模式图。每一个关系用一个矩形表示,关系的名字显示在矩形上方,矩形内列出各属性。主码属性用下划线标注。外码依赖用从参照关系的外码属性到被参照关系的主码属性直接的箭头来表示:
5、关系查询语言
查询语言是用户用来从数据库中请求获取信息的语言。
查询语言分为过程化的和非过程化的。在过程化语言中,用户指导系统对数据库执行一系列操作以计算出所需结果。在非过程化语言中,用户只需要描述所需信息,而不用给出获取该信息的具体过程
6、关系运算
所有的过程化关系查询语言都提供一组运算,这些运算要么施加于单个关系上,要么施加于一对关系上。这些运算具有一个很好的,并且也是所需要的性质:运算结果总是单个的关系。
---------------------------------------------------- SQL --------------------------------------------------------
三、SQL
1、SQL查询语言概览
SQL语言有以下几个部分:
- 数据定义语言(DDL)
SQL DDL提供定义关系模式、删除关系以及修改关系模式的命令 - 数据操纵语言(DML)
SQL DML提供从数据库中查询、以及在数据库中插入、删除、修改元组的能力 - 完整性
SQL DDL包括定义完整性约束的命令,保存在数据库中的数据必须满足所定义的完整性约束。破坏完整性约束的更新是不允许的。 - 视图定义
SQL DDL包括定义视图的命令 - 事务控制
SQL 包括定义事务的开始和结束的命令 - 嵌入式SQL和动态SQL
嵌入式和动态SQL定义SQL语句如何嵌入到通用编程语言,如C、C++和java中 - 授权
SQL DDL包括定义对关系和视图的访问权限命令
2、SQL数据定义
数据库中的关系集合必须由数据定义语言DDL指定给系统。SQL的DDL不仅能够定义一组关系,还能够定义每个关系的信息,包括:
- 每个关系的模式
- 每个属性的取值类型
- 完整性约束
- 每个关系维护的索引集合
- 每个关系的安全性和权限信息
- 每个关系在磁盘上的物理存储结构
-
基本类型
SQL标准支持多种固定类型,包括:
* char(n):固定长度的字符串,用户指定长度n。也可以使用全称 character
* varchar(n):可变长度的字符串,用户指定最大长度n,等价于全称 character varying
* int:整数类型(和机器相关的整数的有限子集),等价于全称integer
* smallint:小整数类型(和机器相关的整数类型的子集)
* numeric(p,d):定点数,精度由用户指定。这个数有p位数字(加上一个符号位),其中d位数字在小数点右边。所以在一个这种类型的字段上,**numeric(3,1)**可以精确存储44.5,但不能精确存储444.5或0.32这样的数
* real、double precision:浮点数与双精度浮点数,精度与机器相关
* float(n):精度至少为n位的浮点数 -
基本模式定义
我们用create table命令定义SQL关系。下面的命令在数据库中创建了一个department关系:
create table department
(dept_name varchar(20),
building varchar(15),
budget numeric(12,2),
primary key(dept_name));
上面创建的关系具有三个属性,dept_name 是最大长度为20的字符串building是最大长度为15的字符串,budget是一个12位的数字,其中2位数字在小数点后面。create table命令还声明了dept_name属性是department关系的主码
SQL支持许多不同的完整性约束,这里介绍几个:
- primary key(A1,A2,A3…):primay key 声明表示属性A1、A2、A3等构成关系的主码。主码属性必须是为空且唯一。
- foreign key(A1、A2、A3…)references声明表示关系中任意元组在属性(A1、A2、A3…)上的取值必须对应于关系x中某元组在主码属性上的取值
- not null:一个属性上的not null约束表明在该属性上不允许空值。
除Create table之外,还有insert命令将数据加载到关系中。delete命令从关系中删除元组。
3、SQL查询的基本结构
SQL查询的基本结构由三个字句组成:select、from 和 where。查询的输入是在from字句中列出的关系,在这些关系中进行where和select字句中指定的运算,然后产生一个关系作为结果。
- 单关系查询
select name from instructor
其结果是由属性名name的单个属性构成的关系。如果instructor关系
如果查询结果有重复,可以在select后面加入关键字distinct
select distinct dept_name from instructor
上述查询结果,每种属性最多只出现一次。
where字句允许我们只选出哪些在from字句的结果关系中满足特定谓词的元组。
select name from instructor
where dept_name = 'Comp' and salary>70000
- 多关系查询
select name ,instructor.dept_name,building
from instructor,department
where instructor.dept_name = department.dept_name
两个关系联合查询
- 自然连接
自然连接运算作用于两个关系,并产生一个关系作为结果。不同于两个关系上的笛卡尔积,它将第一个关系的每个元组与第二个关系的所有元组都进行连接。
select name,course_id
from instructor,teaches
where instructor.ID = teaches.ID
该查询可以用SQL的自然连接运算更简洁地写作:
select name,course_id
from instructor natural join teaches
自然连接运算的结果是关系(表)。from字句中的 “ instructor natural join teaches ” 表达式可以替换成执行该自然连接后所得到的关系。然后在该关系的基础上执行where和select字句。
在一个SQL查询的from字句中,可以用自然连接将多个关系结合在一起,如下所示:
select A1,A2、A3,…,A4
fromr1 natural join r2 natural join … natural join rm
where P;
为了发扬自然连接的优点,同时避免不必要的相等属性带来的危险,SQL提供了一种自然连接的构造形式,允许用户来指定需要哪些列相等。
select name,title
from (instructor natural join teaches)join course using(course_id)
join…using运算中需要给定一个属性名列表,其两个输入中都必须具有指定名称的属性。
4、附加的基本运算
-
更名运算
SQL提供了一个重命名结果关系中属性的方法,即使用如下形式的as字句:
table1 as t1
as 字句即可出现在select字句中,也可出现在from字句中
例如:如果我们想用名字instructor_name 替代属性名name,哦们可以重新上述查询:select name as instructor_name ,course_id from instructor,teaches where instructor.ID = teaches.ID
as子句在重命名关系时特别有用。重命名关系的一个原因就是把一个的关系名替换成短的,这样在查询的其他地方使用起来就更为方便。
select T.name,S.course_id from instructor as T,teaches as S where T.ID = S.DI
重命名关系的另一个原因是为了适用于需要比较同一关系中的元组的情况。如果同一关系比较,又不重命名的话,去不可能把一个元组与其他元组区分开来。
select distinct T.name from instructor as T,teaches as S where T.salary > S.salary and S.dept_name = 'Biology'
-
字符串运算
SQL使用一对单引号来表示字符串例如 ‘Computer。如果单引号是字符串的组成部分,那就用两个单引号字符来表示,如字符串 " it’s right" 可以表示为 " it’'s right"
在SQL标准中,字符串上的相等运算是大小写敏感的,所以表达式 “‘comp.sci.’ = ‘Comp.Sci’”的结果是假。
SQL还允许在字符串上有多种函数,例如串联(使用“||”)、提取子串、计算字符串长度、大小写转换(用upper(s) 的字符串s转换为大写或者用lower(s) 将字符串s转换为小写)、去掉字符串后面的空格(使用trim(s)),等等。在字符串上使用like操作符来实现模式匹配。我们使用两个特殊字符来描述模式:
- %(百分号):匹配任意子串
- _(下划线):匹配任意一个字符
模式是大小写敏感的,也就是说,大写字符与小写字符不匹配,反之亦然。为了说明模式匹配,考虑下列例子: - ‘Intro%’ 匹配 任何以 ‘Intro’大头的字符串
- ‘% Comp%’匹配任何包含“Comp”子串的字符串
- ‘___’匹配只含三个字符的字符串
- ‘___%’匹配至少含三个字符的字符串
考虑查询“找出所在建筑名称中包含子串 ‘Watson‘ 的所有名称”,该查询的写法如下:
select dept_name from department where building like '%Watson%'
为使模式中能够包含特殊模式的字符(即 % 和 _),SQL允许定义转义字符
# 匹配所有以 ab%cd开头的字符串 select * from table where name like 'ab\%cd%' escape '\' # 匹配所有以 ab\cd开头的字符串 select * from table where name like 'ab\\cd%' escape '\'
-
select 子句中的属性说明
星号’*'可以用在 select 子句中表示 “所有的属性”,因而,如下查询的 selelct 子句中使用 intructor.*select instructor.* from instructor,teaches where instructor.ID = teaches.ID
表示instructor中的所有属性都被选中。
-
排列元组的显示次序
SQL为用户提供了一些对关系中元组显示次序的控制。 order by 子句就可以让查询结果排序。
order by默认使用升序。我们可以用 desc表示降序,** asc** 表示升序。select * from instructor order by salary desc,name asc;
-
where 子句谓词
为了简化where子句,SQL提供了between 比较运算符了说明一个值是小于或等于某个值,同时大于或等于 另一个值的。select name from instructor where salary between 90000 and 100000;
它可以取代
select name from instructor where salary <= 100000 and salary >= 90000;
类似的,我们也可以使用 not between 比较运算符
5、集合运算
SQL的作用在关系上的 union、intersect 和 except运算对应数学集合论中的 ∩、∪ 和 - 运算。我们来构造包含这三种运算的查询。
- 并运算
与select子句不同,union 运算自动去除重复。如果我们想保留重复,就必须用union all 代替 union :(select id from table1 where name = 'fail' and year = 2009) union (select id from table2 where name = 'spring' and year = 2010);
(select id from table1 where name = 'fail' and year = 2009) union all (select id from table2 where name = 'spring' and year = 2010);
- 交运算
如果需要保留所有重复,就必须用intersect all 代替intersect(select * from table1 where name = 'fail' and year = 2009) intersect (select * from table2 where name = 'spring' and year = 2010);
(select * from table1 where name = 'fail' and year = 2009) intersect all (select * from table2 where name = 'spring' and year = 2010);
- 差运算
如果保留所有重复,必须用 except all代替except(select * from table1 where name = 'fail' and year = 2009) except (select * from table2 where name = 'spring' and year = 2010);
(select * from table where name = 'fail' and year = 2009) except all (select * from table where name = 'spring' and year = 2010);
6、空值
空值给关系运算带来了特殊的问题,包括算数运算、比较运算和集合运算
如果算数运算的任一输入值为空,则该算数表达式结果为空。
7、聚集函数
聚集函数 是以值的一个集合(集或多重集)为输入、返回单个值的函数。SQL提供了五个固有聚集函数:
-
平均值:avg
-
最小值:min
-
最大值:max
-
总和:sum
-
计数:count
sum和 avg 的输入必须是数字集,但其它运算符还可作用在非数字数据类型的集合上,如字符串 -
基本聚集
计算教师的平均工资:select avg(salary) as avg_salary from instructor where dept_name = 'Comp.Sci.';
计算平均值的时候,不能去重复。不然计算结果有误。
但是在某些情况下,如 计数 ,就必须要去重复,不然会重复计数,去重复的关键词是distinct ,以下是统计教授某一门科目的教师总数select count(distinct ID) from teaches where semester = 'Spring' and year = 2010;
我们经常使用聚集函数count 计算一个关系中的元组的个数。SQL中该函数的写法是count(*) ,因此,要找出course关系中的元组数,可写成:
select count(*) from course
注意:SQL不允许在用count(*)时,使用distinct。在用max和 min时使用时合法的,尽管结果并无差别。
-
分组聚集
有时候我们不仅希望将聚集函数作用在单个元组上,而且也希望将其作用在一组元组集上;在SQL中可用group by子句实现这个愿望。group by子句中给出的一个或者多个属性是用来构造分组的。
在group by 子句中的所有属性上取值相同的元组将被分在一个组中。select dept_name ,avg(salary) as avg_salary from instructor group by dept_name
注意:使用group by语句时,任何出现在select子句中,但没有被聚集的属性必须出现在group by中,否则查询被当做是错误的。
-
having 子句
有时候,对分组限定条件比对元组限定条件更有用。例如,我们只对教师平均工资超过42000 美元的系感兴趣。该条件并不针对单个元祖,而是针对group by子句构成的分组。为表达这样的查询,我们使用having子句。having子句中的谓词在形成分组后才起作用:select dept_name,avg(salary) as avg_salary from instructor group by dept_name having by (salary)>42000;
与select子句情况类型,任何出现在having子句中,但没有被聚集的属性必须出现在group by子句中,否则查询就被当做是错误的。
包含聚集、group by或having子句的查询的含义可通过下述操作序列来定义:
- 与不带聚集的查询情况类似,最先根据from 子句来计算出一个关系
- 如果出现了where子句,where子句中的谓词将应用到from子句的结果关系上
- 如果出现了group by 子句,满足where 谓词的分组通过group by 子句形成分组。如果没有group by子句,满足where谓词的整个元组被当做一个分组
- 如果出现了having子句,它将应用到每个分组上;不满足having子句谓词的分组将被抛弃
- select 子句利用剩下的分组产生出查询结果中的元组
-
对空值和布尔值的聚集
聚集函数根据以下原则处理空值:除了count(*) 外所有的聚集函数都忽略输出集合中的空值。由于空值被忽略,有可能造成参加函数运算的输入值集合为空值。规定空集的count运算为0,其他聚集运算在输入为空集的情况下返回一个空值。
8、嵌套子查询
SQL提供嵌套子查询机制。子查询是嵌套在另一个查询中的select-from-where表达式。子查询嵌套在where子句中,通常用于对集合的成员资格、集合的比较以及集合的基数进行检查。
-
集合成员资格
SQL允许测试元组在关系中的成员资格。连接词 in 测试元组是否是集合中的成员,集合是由 select 子句产生的一组值构成的。连接词 not in 则测试元组是否不是集合中的成员。select distinct course_id from section where semester = 'Fall' and year = 2009 and course_id in (select course_id from section where semester ='Spring' and year = 2010);
-
集合的比较
比如查询“找出满足某些条件的所有教师的姓名,他们的工资至少比中文系某一教师的工资要高”
一般写法:select name from instructor as T,instructor as S where T.salary > S.salary and S.dept_name = '中文系'
但SQL提供了另一种方式书写上面的查询。短语“至少比某一个要大”在SQL中用 > some 表示。所以我们可以重写上面的查询:
select name from instructor where salary > some (select salary from instructor where dept_name = '中文系');
子查询查出了中文系所有教师工资值的集合。当元组的salary值至少比中文系教师的所有工资值集合中某一成员高时,外层select 的where 子句中的 > some 的比较为真。
SQL还允许 < some , <= some, >= some, **= some **和 <> some 的比较。 -
空关系测试
SQL还有一个特性可检测一个子查询的结果中是否存在元组。 exists 结构在作为参数的子查询非空时返回true值。select id from table as T where name = 'Fall' and year = 2009 and exists( select * from table as B where name = 'Spring' and year = 2010 and T.id = B.id);
上述查询还说明了一个SQL特性,来自外层查询的一个相关名称(上述中的T)可以用在where 子句中的查询中。使用了来自外层查询相关名称的子查询被称为相关子查询
-
重复元组存在性测试
SQL提供了一个布尔函数,用于测试在一个子查询的结果中是否存在重复元组。如果作为参数的子查询结果中没有重复的元组。那么unique结果将返回true值。我们可以用unique结构书写查询 “找出所有在2009年最多开设次的课程”:select T.id from course as T where unique( select R.id from section as R where T.id= R.id and R.year = 2009);
-
from子句中的子查询
SQL允许在from子句中使用子查询表达式。在此采用的主要观点是:任何 select-from-where 表达式的结果都是关系,因而可以被插入到另一个select-from-where 中任何关系可以出现的位置。例如“找出系平均工资超过42000美元的那些系中教师的平均工资”:select dept_name,avg_salary from (select dept_name ,avg(salary) as avg_salary from instructor group by dept_name) where avg_salary > 42000);
-
with 子句
with子句提供定义临时关系的方法,这个定义只对包含with 子句的查询有效。考虑下面的查询,它找出具有最大预算值的系。with max_budget(value) as (select max(budget) from deptment) select budget from department,max_budget where department.budget = max_budget.value;
with子句定义了临时关系max_ budget ,此关系在随后的查询中马上就被使用了