890 likes | 1.02k Views
全国计算机等级考试 二级教程 --- Visual FoxPro6.0 程序设计. 主 讲:李富星. 延安大学 计算中心. E-mail: yaydlfx@163.com. 第 5 章 关系数据库标准语言 SQL.
E N D
全国计算机等级考试二级教程---Visual FoxPro6.0程序设计 主 讲:李富星 延安大学 计算中心 E-mail: yaydlfx@163.com
第5章 关系数据库标准语言SQL SQL是Structured Query Language的缩写,即结构化查询语言。它是关系数据库的标准语言。查询是SQL语言的重要组成部分,SQL还包含数据定义、数据操作和数据控制功能等内容。SQL已经成为关系数据库的标准数据语言,所以现在所有的关系数据库管理系统都支持SQL。掌握SQL语法可以更加灵活地建立查询和视图。
5.1SQL语言概述 5.2 查询功能 5.3 操作功能 5.4 定义功能
SQL的定义和发展 SQL的特点 SQL的命令动词 5.1 SQL概述
1. SQL的定义和发展 (Structured Query Language)是结构化查询语言。 SQL语言来源于20世纪70年代IBM的一个被称为SEQUEL(Structured English Query Language)的研究项目。20世纪80年代,SQL由ANSI进行了标准化,它包括了定义和操作数据的指令。由于它具有功能丰富、使用方式灵活、语言简洁易学等突出特点,在计算机界深受广大用户欢迎,许多数据库生产厂家都相继推出各自支持SQL标准。1998年4月,ISO提出了具有完整性特征的SQL,并将其定为国际标准,推荐它为标准关系数据库语言。1990年,我国也颁布了《信息处理系统数据库语言SQL》,将其定为中国国家标准。
2.SQL的特点 • SQL是一种高度非过程化的语言,它无需一步一步地告诉计算机“如何去做”,而只需告诉计算机“做什么”。 • SQL是一种一体化的语言,包括了数据定义、数据查询、数据操纵、数据控制等方面的功能,它可以完成数据库活动中的全部工作。 • SQL语言非常简洁。 • SQL支持多种方式使用
数据库中的数据很多时侯是为了查询的,因此,数据查询是数据库的核心操作。而SQL的主要功能就是对数据表和视图的查询,特别是对于多个数据表或视图之间的数据查询。在SQL语言中,查询语言中有一条查询命令,即SELECT查询语句来完成。数据库中的数据很多时侯是为了查询的,因此,数据查询是数据库的核心操作。而SQL的主要功能就是对数据表和视图的查询,特别是对于多个数据表或视图之间的数据查询。在SQL语言中,查询语言中有一条查询命令,即SELECT查询语句来完成。 一个查询文件中就是包含一条SELECT语句,它也可以放到程序中。 在“查询设计器中”通过查询的设置,系统转化为一条SELECT语句写到查询文件中(.QPR)。
5.2.1 简单查询 5.2.2 简单的联接查询 5.2.3 嵌套查询 5.2.4 几个特殊的运算符 5.2.5 排序 5.2.6 简单的计算查询 5.2.7 分组与计算查询 5.2.8 利用空值查询 5.2 查询功能 • 5.2.9 别名与自联接查询 • 5.2.10 内外层互相关嵌套 • 查询 • 5.2.11 使用量词和谓词的 • 查询 • 5.2.12 超联接查询 • 5.2.13 集合的并运算 • 5.2.14 VFP 中SQL SELECT的几个特殊选项
SQL语法格式: SELECT [ALL|DISTINCT][ TOP〈表达式〉 ][ 〈别名〉 ] 〈Select表达式〉 [AS 〈列名〉 ][, [ 〈别名〉 ]〈Select表达式〉 [AS 〈列名〉 ]…] FORM[ 〈数据库名〉 !] 〈表名〉 [[AS]Local_Alias] [[INNER | LEFT [OUTER] | RIGHT [OUTER] | FULL [OUTER]JOIN[ 〈数据库名〉 !] 〈表名〉 [[AS]Local_Alias][ON〈联接条件〉 ]] [INTO 〈查询结果〉 |TO FILE 〈文件名〉 [ADDITIVE] | TO PRINTER [PROMPT] | TO SCREEN] [PREFERENCE PreferenceName][NOCONSOLE][PLAIN][NOWAIT][WHERE 〈联接条件1〉 [AND 〈联接条件2〉…][AND | OR 〈筛选条件〉 …]][GROUP BY 〈组表达式〉 ][, 〈组表达式〉 …]][HAVING]〈筛选条件〉 ] [UNION[ALL] 〈SELECT命令〉 ][ORDER BY 〈关键字表达式〉 [ASC |DESC] [, 〈关键字表达式〉ASC |DESC]…]] 说明:SELECT-SQL命令的格式包括三个基本子句:SELECT子句、FROM子句、WHERE子句,还包括操作子句:ORDER子句、GROUP子句、UNION子句以及其他一些选项。
1.SELECT子句 • SELECT子句用来指定查询结果中的数据。其中: • ALL选项:表示选出的记录中包括重复记录,这时缺省值;DISTINCT则表示选出的记录中不包括重复记录。 • TOP〈表达式〉选项:表示在符合条件的记录中,选取指定数量或百分比(〈表达式〉)记录。[〈别名〉]〈Select表达式〉[AS〈列名〉]选项中的别名是字段所在的表名;〈Select表达式〉,可以是字段名或字段表达式;〈列名〉用于指定输出时使用的列标题,可以不同于字段名。 • 〈Select表达式〉用一个*号来表示时,指定所有的字段。
2.FROM子句 • 用于指定查询的表与联接类型。其中: • JOIN关键字用于联接其左右两个〈表名〉所指定的表。INNER | LEFT[OUTER] | RIGHT[OUTER] | FULL[OUTER]选项,指定两表联接时的联接类型,联接类型有4种,如表13.2所示。其中的OUTER选项,表示外部联接,即允许满足联接条件的记录,又允许不满足联接条件的记录。若省略OUTER选项,效果不变。
———————————————————————————————————————————————————————————————————— • 联接类型 意义 • —————————————————————————————————— • Inner Join(内部联接) 只有满足联接条件的记录包含在结果中 • Left Outer Join(左联接) 左表某记录与右表所有记录比较字段值,若有满足联接条件的,则产生一个真实记录;若都有满足,则产生一个含.NULL值的记录。直到右表所有记录都比较完 • Right Outer Join(右联接) 右表某记录与左表所有记录比较字段值,若有满足联接条件的,则产生一个真实记录;若都不满足,则产生一个含.NULL值的记录。直到右表所有记录都比较完 • Full Jion(完全联接) 先按右联接比较字段值,再按左联接比较字段值。不列入重复记录 • ————————————————————————————————————— • ON选项:用于指定联接条件。 • INTO与TO选项:用于指定查询结果的输出去向,默认查询结果显示在浏览窗口中。INTO选项中的 〈查询结果〉 有3种。
———————————————————— • 目标 输出形式 • ————————————————————— • ARRAY〈数组〉 查询结果输出到数组 • CURSOR〈临时表〉 查询结果输出到临时表 • TABLE | DBF〈表名〉 查询结果输出到表 • ————————————————————— • TO FILE选项: • 表示输出到指定的文本文件,并取代原文件内容。 • ADDITIVE选项:表示只添加新数据,不清除原文件的内容。 • TO PRINTER选项:表示输出到打印机。 • PROMPT选项:表示打印前先显示打印确认框。 • TO SCREEN选项:表示输出到屏幕。 • PLAIN选项:表示输出时省略字段名。 • NOWAIT选项:表示显示浏览窗口后程序继续往下执行。
3.WHERE子句 • 用来指定查询的条件。其中的 〈联接条件〉 指定一个字段,该字段连接FROM子句中的表。 • 如果查询中包含不止一个表,就应该为第一个表后的每一个表指定连接条件。
4.其他子句和选项 • GROUP BY子句:对记录按〈组表达式〉值分组,常用于分组统计。 • HAVING子句:当含有GROUP BY子句时,HAVING子句可用作记录查询的限制条件;无GROUP BY 子句时,HAVING子句的作用如同WHERE子句。 • UNION子句:可以用UNION子句嵌入另一个SELECT-SQL命令,使这两个命令的查询结果合并输,但输出字段的类型和宽度必须一致。UNION子句默认组合结果中排除重复行,使用ALL,则允许包含重复行。 • ORDER BY子句:指定查询结查中记录按〈关键字表达式〉排序,默认升序。选项ASC表示升序,DESE表示降序。 • SELECT查询命令的使用非常灵活,用它可以构造各种各样的查询。本章将通过大量的实例来介绍SELECT命令的使用方法。
5.2.1 简单查询 一、 无条件查询 【格式】SELECT [ALL | DISTINCT] <字段列表> FROM <表> 【功能】无条件查询。 【说明】①SELECT关键字告诉VFP将要作查询操作。 ②字段列表:列出从表中输出的列。 ③表:告诉VFP从那个表中取数据,关键字FROM和表名组合在一起,通常叫做FROM子句。 ④语句中各组成部分的位置和间隔并不重要,但先后次序必须正确。 ⑤ALL: 表示显示全部查询记录,包括重复记录。 ⑥ DISTINCT: 表示显示无重复结果的记录。
例5·1 从职工关系中检索所有的工资值。 • SELECT 工资 FROM 职工 • SELECT DISTINCT 工资 FROM 职工 • 去掉查询结果中的重复值。 • 例5·2 检索仓库关系中的所有元组。 • SELECT * FROM 仓库 • 等价于SELECT 仓库号,城市,面积 FROM 仓库
二、 带条件(WHERE)的查询语句 【格式】SELECT [ALL | DISTINCT] <字段列表> FROM <表> [WHERE <条件表达式> ] 【功能】从一个表中查询满足条件的数据。 【说明】<条件表达式>由一系列用AND 或 OR 连接的条件表达式组成。 例5.3检索工资多于1230元的职工号 SELECT 职工号 FROM 职工 WHERE 工资>1230 例5.4检索哪些仓库有工资多于1210元的职工 SELECT DISTINCT 仓库号 FROM 职工 ; WHERE 工资>1210
例5.5给出仓库”WH1”或”WH2”工作,并且工资少于1250元的职工例5.5给出仓库”WH1”或”WH2”工作,并且工资少于1250元的职工 SELECT 职工号 FROM 职工 ; WHERE 工资<1250 AND; (仓库号=“WH1” OR 仓库号=”WH2”) • 以上检索只基于一个关系
【说明】在一个数据库中的多个表之间一般都存在着某些联系,在一个查询语句中同时涉及到两个或两个以上的表时,这种查询称之为联接查询(也称为多表查询)。在多表之间查询必须处理表与表之间的连接关系。 SELECT [ALL | DISTINCT] <字段列表> FROM <表1>[,表2…..] WHERE <条件表达式> 5.2.2 简单的联接查询
联接查询是一种基于多个关系的查询. 例5.6 找出工资多于1230元的职工号和他们所在的城市 SELECT 职工号,城市 FROM 职工,仓库 ; WHERE (工资>1230) AND(职工.仓库号=仓库.仓库号) 仓库关系和职工关系之间存在一个一对多的联系。 例5.7 找出工作在面积大于400的仓库的职工号以及这些职工所在的城市 SELECT 职工号,城市 FROM 职工,仓库 ; WHERE (面积>1230) AND(职工.仓库号=仓库.仓库号)
5.2.3.嵌套查询 • 是一类基于多个关系的查询,是指相关的条件涉及多个关系,即WHERE短语后的逻辑表达式中含有对其他表的查询。但它的最终查询结果数据却出自一个关系,出自由外层查询的FROM短语后所指定的表。 • 难点:查询条件要受另一个关系的查询结果的制约 • 重点:能正确写出外层查询的查询条件; 能正确写出嵌套查询的命令。 • 注意:内层查询块一定要用一对圆括号括起来; • 若内层查询的结果可能多于1个值,要用运算符“IN”,而不要用运算符“=”;
VFP只支持内外两层嵌套查询,不支持SQL的多层嵌套查询 通配符“*”表示所有属性; 各种查询的查询结果可以进行排序,但只能对最终的结果进行排序,不能对嵌套查询的内层查询结果即子查询结果进行排序。 • 【5.8】在仓库表和职工表中,检索哪些城市至少有一个仓库的职工工资为1250元 • SELECT 城市 FROM 仓库 WHERE 仓库号 IN; • (SELECT 仓库号 FROM 职工 WHERE 工资=1250) • 在这个命令中含有两个SELECT-FROM-WHERE查询块,即内层查询块和外层查询块,内层查询块 • 检索到的仓库号值是WH1和WH2, 这里IN相当于集合运算符∈。这样就可写出等价的命令: • SELECT 城市 FROM 仓库 WHERE 仓库号 IN("WH1", "WH2")
【5.9】在仓库表和职工表中,检索所有职工的工资都多于为1210元的仓库信息。【5.9】在仓库表和职工表中,检索所有职工的工资都多于为1210元的仓库信息。 • SELECT * FROM 仓库 WHERE 仓库号 NOT IN; • (SELECT 仓库号FROM职工 WHERE工资<=1210) • 内层SELECT-FROM-WHERE查询块指出所有职工的工资少于或等于1210元的仓库的仓库号值的集合,在这里该集合只有一个值“WH1”;然后从仓库关系中检索元组的仓库号属性值不在该集合中的每个元组。有的读者也许已经注意到刚才的检索出现了错误,尽管在“武汉”的“WH4”仓库还没有职工,但该仓库的信息也被检索出来了。所以必须认真分析检索要求,写出正确的SQL命令。
如果要求排除那些还没有职工的仓库,检索要求可以叙述为:检索所有职工的工资都多于1210元的仓库的信息,并且该仓库至少要有一名职工。这样描述就很清楚了,因为我们对没有职工的仓库不感兴趣。这样,写出的SQL命令也就复杂一些了: SELECT * FROM 仓库 WHERE 仓库号 NOT IN; • (SELECT 仓库号 FROM 职工 WHERE 工资<=1210); • AND 仓库号 IN(SELECT 仓库号 FROM 职工) • 这样内层是两个并列的查询,在结果中将不包含没有职工的仓库信息。 【5.10】检索出和职工E4挣同样工资的所有职工。 • SELECT 职工号 FROM 职工 WHERE 工资=; • (SELECT 工资 FROM 职工 WHERE 职工号="E4")
5.2.4 几个特殊的运算符 • 在SQL语句中,WHERE子句后面的联接条件,除了可以使用VFP语言中的关系表达式以及逻辑表达外,还可以使用几个特殊运算符: • (1)[NOT]IN:表示[不]在…之中。 • (2)[NOT]BETWEEN…AND…:表示[不]在…之间。 • (3)[NOT]LIKE:表示[不]与…匹配。 说明: (1)NOT运算符来设计否定条件。 (2)LIKE运算符提供两种字符串匹配方式,一种是使用下划线符号“_”,匹配一个和任意字符,另一种是使用百分号“%”,匹配0个或多个任意字符。 (3)IN运算符,格式为IN(常量1,常量2,…)。含义为查找和常量相等的值。
【5.11】检索出工资在1220元到1240元范围内的职工信息。这个查询的条件值是在什么范围之内,显然可以用BETWEEN…AND…,为此有如下查询语句:【5.11】检索出工资在1220元到1240元范围内的职工信息。这个查询的条件值是在什么范围之内,显然可以用BETWEEN…AND…,为此有如下查询语句: • SELECT * FROM 职工WHERE工资 BETWEEN 1220 AND 1240这里BETWEEN…AND…意思是在“…和…之间”,这个查询的条件等价于: • (工资>=1220) AND (工资<=1240) • 显然使用BETWEEN…AND…表达条件更清晰、更简洁。假如找出工资不在1220元和1240元之间的全部职工信息,可以用命令: • SELECT * FROM 职工 WHERE工资 NOT BETWEEN 1220 AND 1240命令执行结果如图13.20所示。
【5.12】在供应商表中,检索出全部公司的信息,不要工厂或其他供应商的信息。这是一个字符串匹配的查询,显然应该使用LIKE运算符:【5.12】在供应商表中,检索出全部公司的信息,不要工厂或其他供应商的信息。这是一个字符串匹配的查询,显然应该使用LIKE运算符: • SELECT * FROM 供应商 WHERE 供应商名 LIKE "%公司" • 这里的LIKE是字符串匹配运算符,通配符“%”表示0个或多个字符,另外还有一个通配符“-”表示一个字符。 【5.13】在供应商表中,找出不在北京的全部供应商的信息。 • SELECT * FROM 供应商 WHERE 地址!="北京" • 在SQL中,“不等于”用“!=”表示。另外还可以用否定运算符NOT写出等价命令: • SELECT * FROM 供应商 WHERE NOT(地址="北京") • NOT的应用范围很广,比如,可以有NOT IN(例5.9)、NOT BETWEEN等。
5.2.5 排序 用ORDER BY短语定义排序字段。 [格式]【格式】SELECT [ALL | DISTINCT] <字 段列表> FROM <表> [WHERE <条件>] [ORDER BY <排序项1> [ASC | DESC] [,排序项2[ASC | DESC]…] 说明:ASC为升序,DESC为降序,默认为升序。 注意:ORDER BY是对最终的查询结果进行排序,不可以在子查询中使用该短语。
【5.14】在职工表中,按职工的工资值升序检索出全部职工的信息。【5.14】在职工表中,按职工的工资值升序检索出全部职工的信息。 • SELECT * FROM 职工 ORDER BY 工资 • 这里ORDER BY是排序子句,如果需要将结果按降序排列,只要加上DESC。 • SELECT * FROM 职工 ORDER BY 工资 DESC • 【13.18】在职工表中,先按仓库号排序,再按工资排序,并输出全部职工信息。 • SELECT * FROM 职工 ORDER BY 仓库号,工资 • 这里一个按多列排序的例子。 • 说明:ORDER BY是对最终的查询结果进行排序,不可以在子查询中使用该短语。
5.2.6 简单的计算查询 SQL语言是完备的,也就是说,只要数据是按关系方式存入数据库的,就能构造合适的SQL命令把它检索出来。事实上,SQL不仅具有一般的检索能力,而且还有计算方式的检索,比如检索职工的平均工资、检索某个仓库中职工的最高工资值等。用于计算检索的函数有: • (1)COUNT—计数 • (2)SUM—求和 • (3)AVG—计算平均值 • (4)MAX—求最大值 • (5)MIN—求最小值 • 这些函数可以用在SELECT短语中对查询结果进行计算。
【5.16】在供应商表中,找出供应商所在地的数目。【5.16】在供应商表中,找出供应商所在地的数目。 • SELECT COUNT (DISTINCT 地址) FROM 供应商 • 参见前面给出的供应商的记录值,其中共有5个地址:北京、西安、郑州、上海和深圳。所以结果为5。 • 说明,除非对关系中的元组个数进行计数,一般应用COUNT函数应该使用DISTINCT。例如: • SELECT COUNT(*) FROM 供应商 • 将给出供应商关系中的记录数是6个。 • 【5.17】在职工表中,求支付的工资总数。 • SELECT SUM(工资) FROM 职工 • 结果是:6160。这个结果是职工关系中的工资值的总和,它并不管是否有重复值。这时若使用命令: • SELECT SUM(DISTINCT工资) FROM 职工 • 将得出错误的结果4910。原因是DISTINCT命令去掉重复值1250。
【5.18】在职工表和仓库表中,求北京和上海的仓库职工的工资总和。【5.18】在职工表和仓库表中,求北京和上海的仓库职工的工资总和。 • SELECT SUM(工资) FROM 职工WHERE仓库号IN; • (SELECT 仓库号 FROM 仓库 WHERE 城市="北京" OR 城市="上海") • 【5.19】在仓库表和职工表中,求所有职工的工资都多于1210元的仓库的平均面积。 • SELECT AVG(面积) FROM 仓库 WHERE 仓库号 NOT IN; • (SELECT 仓库号 FROM 职工 WHERE 工资<=1210) • 结果是:366.67 • 这里要注意,以上结果的运算包含了尚没有职工的WH4仓库。如果要排除没有职工的仓库,以上语句应该改为: • SELECT AVG(面积) FROM 仓库 WHERE 仓库号 NOT IN; • (SELECT 仓库号 FROM 职工 WHERE 工资<=1210); • AND仓库号 IN (SELECT仓库号 FROM 职工)
【5.20】在职工表中,求在WH2仓库工作的职工的最高工资值。【5.20】在职工表中,求在WH2仓库工作的职工的最高工资值。 • SELECT MAX(工资) FROM 职工 WHERE 仓库号="WH2" • 结果是:1250 • 与MAX函数相对应的是MIN函数(求最小值)。比如,求最低工资值可以有如下命令: • SELECT MIN(工资) FROM 职工 WHERE仓库号="WH2"
5.2.7 分组与计算查询 用GROUP BY短语定义分组字段 【格式】SELECT [ALL | DISTINCT] <字段列表> FROM <表> [WHERE <条件>] [GROUP BY <分类字段列表>[,分类字段列表…] [HAVING <过滤条件>] 【说明】按指定字段进行分组、汇总。在分组时如果包含条件,用HAVING后的关系表达式或逻辑表达式表示。
【5.21】在职工表中,求每个仓库的职工的平均工资。【5.21】在职工表中,求每个仓库的职工的平均工资。 • SELECT 仓库号,AVG(工资) FROM 职工 GROUP BY 仓库号 • 在这个查询中,首先按仓库号属性进行分组,然后再计算每个仓库的平均工资。GROUP BY子句一般跟在WHERE子句之后,没有WHERE子句时,跟在FROM子句之后。另外,还可以根据多个属性进行分组。在分组查询时,有时要求分组满足某个条件时才检索,这时可以用HAVING子句来限定分组。 • 【5.22】在职工表中,求至少有两个职工的每个仓库的平均工资。 • SELECT 仓库号,COUNT(*),AVG(工资) FROM职工; • GROUP BY 仓库号 HAVING COUNT(*)>=2 • HAVING子句总是跟在GROUP BY 子句之后,不可以单独使用。HAVING子句和WHERE 子句不矛盾,在查询中是先用WHERE子句限定元组,然后再进行分组,最后再用HAVING子句限定分组。 • 说明:HAVING子句和WHERE子句的区别:WHERE子句是用来指定表中各行所应满足的条件,而 • HAVING子句是用来指定每一分组所满足的条件,只有满足HAVING条件的那些组才能在结果中被显示。
5.2.8 利用空值查询 SQL支持空值,当然也可以利用空值进行查询。 注意:查询空值时要使用IS NULL,而=NULL是无效,因为空值不是一个确定的值,所以不能“=”这样的运算符进行比较。
例5.23 找出尚未确定供应商的订购单 SELECT * FROM 订购单 WHERE 供应商号 IS NULL 注意:查询空值时要使用IS NULL,而=NULL是无效的,因为空值不是一个确定的值,所以不能用“=”这样的运算符进行比较。 例5.24 列出已经确定了供应商的订购单信息 SELECT *FROM 订购单 WHERE 供应商号 IS NOT NULL
5.2.9 别名与自联接查询 别名的格式: FROM <关系名><别名> 注意:关系名与别名之间是用空格分隔的。 自联接:将同一关系与自身进行联接。 注意:别名是必不可少的;两个不同的属性的值域是相同的。
使用别名的联接嵌套查询 SELECT 供应商名 FROM 供应商 S,订购单 P,职工 E ,仓库 W; WHERE 地址=”北京” AND 城市=”北京”; AND S.供应商号=P.供应商号; AND P.职工号=E.职工号; AND E.仓库号=W.仓库号 以上例子中,别名不是必须的,但在关系的自然联接中,别名是必不可少的. 比如,如下的联接语句是一个基于4个关系的联接查询,其中必须使用关系名做前缀 SELECT 供应商名 FROM 供应商,订购单,职工,仓库; WHERE 地址=”北京” AND 城市=”北京”; AND 供应商.供应商号=订购单.供应商号; AND 订购单.职工号=职工.职工号; AND 职工.仓库号=仓库.仓库号
什么是自然联接? SQL不仅可以对多个关系实行联接操作,也可以将同一个关系与其自身进行联接,这种联接就称为自然联接. 在可以进行这种自然联接的关系中,实际存在着一种特殊的递归关系,即关系中的一些元组,根据出自同一值域的两个不同的属性,可以与另外的一些元组有一种对应关系(一对多联系). 自然联接
假设雇员关系: 雇员(雇员号,雇员姓名,经理) 其中雇员号和经理两个属性出自同一值域,同一元组的这两个属性值是上下级关系. 雇员号 雇员号 雇员姓名 雇员姓名 经理 经理 E3 赵涌 E4 钱潮 E3 E6 孙洁 E3 E8 李路 E6 举例 1:n 例5.25根据雇员关系列出上一级经理及其所领导的职员清单 SELECT S.雇员姓名,”领导”,E.雇员姓名FROM 雇员S, 雇员E; WHERE S.雇员号=E.经理
职工号 供应商号 订购单号 订购日期 总金额 E3 S7 OR67 2001/06/23 35000.0000 E1 S4 OR73 2001/07/28 12000.0000 E7 S4 OR76 2001/05/25 7250.0000 E6 NULL OR77 NULL 6000.0000 E3 S4 OR79 2001/06/12 30050.0000 E1 NULL OR80 NULL 25600.0000 E3 NULL OR90 NULL 7690.0000 E3 S3 OR91 2001/07/13 12560.0000 5.2.10 内外层互相关嵌套查询 内层查询的条件需要外层查询提供值,而外层查询的条件需要内层查询的结果。 例如在订购单表中加入一个新字段总金额,说明完成该订购单所应付出的总金额数,新的订购单表的记录如下:
【5.26】在订购单表中,列出每个职工经手的具有最高总金额的订购单信息。这里先给出相应的查询语句,然后再作必要的解释。【5.26】在订购单表中,列出每个职工经手的具有最高总金额的订购单信息。这里先给出相应的查询语句,然后再作必要的解释。 • SELECT out.职工号,out.供应商号,out.订购单号,out.订购日期,out.总金额; • FROM 订购单 out WHERE 总金额=(SELECT MAX(总金额) FROM 订购单 inner1; • WHERE out.职工号=inner1.职工号)
5.2.11使用量词和谓词的查询 两类和子查询有关的运算符,它们有以下两种形式: <表达式><比较运算符>[ANY|ALL|SOME](子查询) [NOT] EXIST (子查询) ANY、ALL和SOME是量词,其中ANY和SOME是同义词,在进行比较运算时只要查询中有一行能结果为真,而ALL则要求子查询中的所有行都使结果为真时,结果才为真。 EXISTS是谓词,EXISTS或NOT EXISTS是用来检查在子查询中是否有结果返回,即存在元组或不存在元组。 注意:当内层查询引用了外层查询的表,使用谓词EXISTS或NOT EXISTS才有意义。 [NOT] EXISTS只是判断子查询中是否有没有结果返回,它本身没有任何运算或比较。
【5.27】在仓库表和职工表中,检索哪些仓库中还没有职工的仓库的信息。【5.27】在仓库表和职工表中,检索哪些仓库中还没有职工的仓库的信息。 • 这里的查询是没有职工或不存在职工,所以可以使用谓词NOT EXISTS。 • SELECT * FROM 仓库 WHERE NOT EXISTS; • (SELECT * FROM 职工 WHERE 仓库号=仓库.仓库号) • 说明:这里的内层查询引用了外层查询的表,只有这样使用谓词EXISTS或NOT EXISTS 才有意义。所以这类查询也都是内、外层互相关嵌套查询。 • 以上的查询命令等价于如下查询命令: • SELECT * FROM 仓库 WHERE 仓库号 NOT IN (SELECT 仓库号 FROM 职工)
【5.28】在仓库表和职工中,检索哪些仓库中至少已经有一个职工的仓库的信息。【5.28】在仓库表和职工中,检索哪些仓库中至少已经有一个职工的仓库的信息。 • SELECT * FROM 仓库 WHERE EXISTS; • (SELECT * FROM 职工 WHERE 仓库号=仓库.仓库号) • 说明:[NOT]EXISTS只是判断子查询中是否有或没有结果返回,它本身并没有任何运算或比较。 • 【5.29】在职工表中, 检索有职工的工资大于或等于WH1仓库中任何一名职工工资的仓库号。 • 这个查询可以使用ANY或SOME量词。 • SELECT DISTINCT 仓库号 FROM 职工 WHERE 工资>=ANY; • (SELECT 工资 FROM 职工 WHERE 仓库号="WH1") • 它等价于: • SELECT DISTINCT 仓库号 FROM 职工 WHERE 工资>=; • (SELECT MIN(工资) FROM 职工 WHERE 仓库号="WH1")
【5.30】在职工表中, 检索有职工的工资大于或等于WH1仓库中所有职工工资的仓库号。这个查询使用ALL量词。 SELECT DISTINCT 仓库号 FROM 职工 WHERE 工资>=ALL; (SELECT 工资 FROM 职工 WHERE 仓库号="WH1") 它等价于: SELECT DISTINCT 仓库号 FROM 职工 WHERE 工资>=; (SELECT MAX(工资) FROM 职工 WHERE 仓库号="WH1")