4.5 简单的SQL查询语言
SQL查询语句的格式如下:
SELECT[ALL | DISTINCT]<目标列表达式>[,<目标列表达式>]… FROM<表名或视图名>[,<表名或视图名>]… [WHERE<条件表达式>] [GROUP BY<列名1>[HAVING <条件表达式>]] [ORDER BY<列名2>[ASC | DESC]];
查询语句可以分为SELECT子句、FROM子句、WHERE子句、GROUP BY子句和ORDER BY子句。
SELECT子句指明需要查询的项目,一般是列名,也可以是表达式。利用表达式,可以查询表中并未存储但可以导出的结果。FROM子句指明被查询的表或视图名。如果需要,也可以为表和视图取一别名,这种别名只在本句中有效。SELECT子句和FROM子句是每个SQL查询语句所必需的,其他子句是任选的。WHERE子句说明查询的条件。GROUP BY子句用来将结果分组。ORDER BY子句将结果排序。
查询语句可以完成简单的单表查询,也可以完成复杂的多表查询和嵌套查询。本节主要介绍在最常用的查询中各个子句如何使用。在下一节会介绍比较复杂的联合查询。
为了便于举例,在这里先给出后面例子中用到的表。假设数据库中有三个表:STUDENTS表、COURSE表和SC(学生选课)表,分别如表4-3、表4-4、表4-5所示。
表4-3 STUDENTS表
表4-4 COURSE表
表4-5 SC表(学生选课表)
★ 注意 ★
“ ?”表示该元组的该字段为空。
4.5.1 SELECT子句和FROM子句
SELECT子句指明需要查询的项目,FROM子句指明被查询的表或视图名。SELECT子句和FROM子句可以构成最基本的查询语句。例如,需要查询全体学生的学号和系别,SQL查询语句如下:
SELECT SNO,SDEPT FROM STUDENTS;
若要查询表的全部列,则可以将<目标列表达式>指定为*。例如要查询课程的详细记录,SQL查询语句如下:
SELECT * FROM COURSE;
前面提到过,SELECT子句后面的<目标列表达式>可以是列名,也可以是表达式,例如查询学生的姓名和出生年份。假设今天是2005年,那么由SAGE字段值就可以得到出生年份。SQL语句如下:
SELECT SNAME,2005-SAGE FROM STUDENTS;
可以看到第二个<目标列表达式>就是一个计算表达式。
在SELECT子句中有DISTINCT选项,在使用查询语句时,满足条件的结果可能不止一个,如果加了DISTINCT选项,则要求消除查询结果中的重复项。例如,查询选课表中的课程号,不要重复字段,SQL语句如下:
SELECT DISTINCT CNO FROM SC;
结果如下表4-6所示。
表4-6 查询结果表
如果没有指定DISTINCT选型,则默认为ALL选项,就会保留所有结果。
4.5.2 WHERE子句定义查询条件
前面的例子都是查询表中所有行的数据,只是对列进行了查询,也就是投影操作,而更普遍的应用是使用WHERE子句定义查询条件,在投影操作的同时也进行元组的选择。
WHERE子句后面加条件表达式。常用的查询条件如表4-7所示。
表4-7 常用的查询条件
下面分别介绍各类查询符号的用法。
1.比较
SQL语言中的比较符号和数学中的比较符号是统一的,这也是SQL语言易懂易学的原因。表4-7的第一行给出了所有比较符号,其中NOT加上比较运算符表示对条件求非。
例如需要查询STUDENTS表中,年龄大于20岁的学生的姓名和系别,SQL语句如下:
SELECT SNAME,SDEPT FROM STUDENTS WHERE SAGE>20;
2.确定范围
BETWEEN条件可表示为E [NOT] BETWEEN E1 AND E2,其语义可以用比较符号表示为[NOT](E>=E1 AND E<=E2)。其中AND是多重条件符号。
例如查询学生选课表(SC)中,成绩在80分到90分之间(包括80和90分)的学生的学号和成绩。SQL语句如下:
SELECT SNO,GRADE FROM SC WHERE GRADE BETWEEN 80 AND 90;
3.确定集合
IN条件可以表示为E [NOT] IN(V1,V2,…,Vn),其语义相当于[NOT] (E=V1 OR E=V2 OR…OR E=Vn),也就是说查找属性值属于指定集合(V1,V2,…,Vn)的元组。
例如查询学生表中数学系和英语系学生的姓名和系别,SQL语句可以如下表达:
SELECT SNAME,SDEPT FROM STUDENTS WHERE SDEPT IN('English','Maths');
4.字符匹配
LIKE条件用于字符串的比较,在比较时,引用了两个具有特殊意义的通配符:下画线“_”和百分号“%”。
● 下画线“_”表示任意单字符;
● 百分号“%”表示包括长为零的任意长的字符串。
LIKE条件可以表示为E [NOT] LIKE ‘<匹配串>’,其中匹配串中可以是一个完整的字符串,也可以是包含通配符的字符串。
★ 说明 ★
如果是完整的字符串,则可以使用比较符号的等号“=”取代LIKE。
例如查询课程号为“C001”的详细情况,SQL语句如下:
SELECT * FROM COURSE WHERE CNO LIKE 'C001';
其实该语句就等价与
SELECT * FROM COURSE WHERE CNO='C001';
例如查询姓李的学生的详细信息,SQL语句如下:
SELECT * FROM STUDENTS WHERE SNAME LIKE '李%';
★ 注意 ★
在使用下画线“_”代表字符时,一个汉字应该使用两个下画线,因为一个汉字占两个字符的位置。
5.涉及NULL的查询
例如,某些学生选修课程后没有参加考试,所以有选课记录,但没有考试成绩。查询缺少成绩的学生的学号和相应的课程号,SQL语句如下:
SELECT SNO,CNO FROM SC WHERE GRADE IS NULL;
6.多重条件查询
AND和OR可以用来联结多个查询条件。例如,查询学生表中年龄大于20的男学生的详细信息,SQL语句如下:
SELECT * FROM STUDENTS WHERE SAGE>20 AND SSEX='男';
4.5.3 GROUP BY子句对查询结果分组
GROUP BY子句将表按列的值分组,列的值相同的分为一组。如果GROUP BY后面有多个列名,则先按第一列名分组,再在每组中按第二列名分组。GROUP BY子句经常与聚集函数联用,所以下面会先简单介绍聚集函数。如果分组后还要求按一定的条件对组进行筛选,最终只输出满足条件的组,则可以使用HAVING子句。
SQL中的聚集函数有AVG、MAX、MIN、SUM、COUNT五种。聚集函数的变量为一集合。AVG表示取平均值。MAX/MIN表示取最大值或最小值。SUM表示求和。COUNT表示元组个数。
在使用聚集函数时,若不使用GROUP BY子句,则作用于整个查询结果。例如,查询选课学生的平均分,SQL语句如下;
SELECT AVG(GRADE) FROM SC;
而如果在GROUP BY子句中使用聚集函数,则分组后,聚集函数会作用于每个组,每个组都得到一个函数值。
例如求各门选课的平均成绩,SQL语句如下,结果如表4-8所示。
表4-8 查询结果表
SELECT CNO,AVG(GRADE) FROM SC GROUP BY CNO;
4.5.4 ORDER BY子句对查询结果分组
ORDER BY子句可对查询结果按子句中指定的列的值排序。列可以用列名表示,也可以用在SELECT子句中出现的序号表示。后者书写起来比较简便,特别当选择的列是聚集函数或表达式时,由于没有列名,只能用序号表示。ASC选项表示升序,DESC选项表示降序,默认时表示升序。
例如,查询学生选课表,给出选了C001号课程的学生的学号和成绩,结果以成绩升序排列。SQL语句如下:
SELECT SNO,GRADE FROM SC WHERE CNO='C001' ORDER BY GRADE ASC;