数据查询.
数据查询是数据库中最常用的操作,SQL中提供SELECT
语句,通过查询操作可以得到所需的信息。SELECT
语句的一般格式如下所示,可以暂时跳过,通过例子对查询操作有了直观的认知之后再看一般格式会更有理解:
SELECT [ALL|DISTINCT][TOP N [PERCENT]|[WITH TIES]]
Col_1 AS Nickname_1,Col_2 AS Nickname_2,...,Col_n AS Nickname_n
FROM NAME_OF_TABLE AS Table_Nickname
WHERE CONDITION
GROUP BY Col_x [HAVING CONDITION]
ORDER BY Col_y [ASC|DESC]
我们需要注意,查询的结果依然是一个关系,也就是一个数据表。SELECT
语句的执行过程是,根据WHERE
子句的检索条件,从FROM
子句指定的基本表中选取满足条件的元组,再按照SELECT
子句中指定的列,投影到这些列上得到结果。如果当中还有GROUP BY Col_x
子句,则将查询的结果按照Col_x
中相同的值进行分组,如果GROUP
子句之后还有HAVING CONDITON
子句,则只会输出满足条件表达式的元组。如果最后还有ORDER BY Col_y
子句,查询结果还要按照ORDER
子句中Col_y的值以及后面[ASC]|[DESC]
进行升序或降序排列。
单关系数据查询.
无条件查询.
无条件查询是指只包含SELECT...FROM...
的查询,这种查询最简单,相当于只对关系进行投影操作。
【例】查询全体学生的学号、姓名和年龄。
SELECT SNo,SN,Age
FROM S
【例】查询学生的全部信息。
SELECT *
FROM S
我们在SELECT
语句中使用【*】表示全部列,而不必一一写出。
【例】查询选修了课程的学生的学号。
由于会存在一个学生选修多门课的情况,所以学生选课表中会存在重复的学号记录,我们希望过滤掉重复的学号。
SELECT DISTINCT SNo
FROM SC
上述查询中,都是没有出现WHERE
子句的无条件查询,也称作投影查询。但需要注意,在关系代数的定义中,投影操作是会自动消去重复行,而SQL中的查询语句只有在使用关键字DISTINCT
的情况下才会消去重复行。另外,通过查询语句,我们可以控制结果中列名出现的顺序,并且可以通过关键字AS
来指定别名用于显示时的可读性。
【例】查询全体学生的姓名、年龄和学号。
SELECT SN AS Name,Age,SNo
FROM S
其中Name
作为SN
的别名出现在查询结果中。
条件查询.
当要在表中找出满足某些条件的行时,则需要使用WHERE
子句指定查询条件,WHERE
子句中的查询条件常常通过三部分来描述:
- 列名
- 比较运算符
- 列名、常数
常用的比较运算符如下所示:
给出几个例子来展示条件查询的代码:
【例】查询选修课程号为C1的学生的学号和成绩。
SELECT SNo,Score
FROM SC
WHERE CNo='C1'
【例】查询成绩高于85分的学生的学号、课程号和成绩。
SELECT SNo,CNo,Score
FROM SC
WHERE Score>85
【例】查询选修C1或C2且分数大于等于85分的学生的学号、课程号和成绩。
SELECT SNo,CNo,Score
FROM SC
WHERE (CNo='C1' OR CNo='C2') AND Score>=85
【例】查询工资在1000元到1500元之间的教师的教师号、姓名以及职称。
SELECT TNo,TN,Prof
FROM T
WHERE Salary BETWEEN 1000 AND 1500
注意!在SQL Server中BETWEEN...AND...
是一个闭区间,而有些DBMS中这是一个开区间。
【例】查询工资不在1000元到1500元之间的教师的教师号、姓名以及职称。
SELECT TNo,TN,Prof
FROM T
WHERE Salary NOT BETWEEN 1000 AND 1500
【例】查询选修了C1或C2或C3的学生的学号、课程号和成绩。
SELECT SNo,CNo,Score
FROM SC
WHERE CNo IN ('C1','C2','C3')
【例】查询那些没有考试成绩的学生的学号和相应的课程号。
SELECT SNo,CNo
FROM SC
WHERE Score IS NULL
【例】部分匹配查询。以上的查询都是属于完全匹配查询,当不知到精确的值时,我们还可以使用LIKE
或NOT LIKE
进行模糊查询,也就是部分匹配查询。LIKE
的一般格式为:
NAME_OF_ATTRIBUTE LIKE STRING
其中,NAME_OF_ATTRIBUTR
必须是一个字符型的量,后面的字符串常量STRING
中可以包含通配符,利用它们进行模糊匹配。一些常用的通配符及其含义如下所示:
- 【%】代表0个或多个字符,例如
ab%
代表ab
之后可以接任意字符串。 - 【_】代表1个字符,例如
a_b
代表a
与b
之间可以有一个字符。 - 【[ ]】代表在某一范围内的字符,例如
[0-9]
代表0~9之间的字符。 - 【[^ ]】代表不在某一范围内的字符,例如
[^0-9]
代表不在0~9之间的字符。
【例】查询所有姓张的老师的教师号和姓名。
SELECT TNo,TN
FROM T
WHERE TN LIKE '张%'
【例】查询姓名中第二个字是’力’的教师的教师号和姓名。
SELECT TNo,TN
FROM T
WHERE TN LIKE '_力%'
库函数.
SQL中提供了许多库函数,增强了基本检索能力,常用的一些库函数如下所示:
【例】求学号为S1的学生的总分和平均分。
SELECT SUM(Score) AS TotalScore,AVG(Score) AS AverageScore
FROM SC
WHERE SNo='S1'
上述的代码中,as
关键字之后的是列的别名,别名会显示在查询结果中,让用户有更好的体验。在查询中使用库函数时,通常需要给每一项内容加上别名,否则查询结果中就不会显示列名。并且注意:库函数SUM()
和AVG()
只能对于数值型的数据使用。
【例】求选修C1课程的最高分、最低分以及极差。
SELECT MAX(Score) AS MaxScore,MIN(Score) AS MinScore,
MAX(Score)-MIN(Score) AS Difference
FROM SC
WHERE CNo='C1'
【例】求计算机系学生的总数。
SELECT COUNT(SNo) AS TotalStudents
FROM S
WHERE Dept='计算机'
【例】求学校中共有多少个系。
SELECT COUNT(DISTINCT Dept) AS DeptNumber
FROM S
使用关键字DISTINCT
之后表示消除重复行,如此一来就可以计算字段Dept
不同值的数目。
【例】统计计算机系的学生总数,使用COUNT(*)
函数。
SELECT COUNT(*) AS TotalStudents
FROM S
WHERE Dept='计算机'
COUNT(*)
函数用于统计所有元组的个数,不会消除重复行,也不允许使用关键字DISTINCT
。
分组查询.
GROUP BY
子句可以将查询结果按照属性列或者属性列的组合(即分组依据),在行的方向上进行分组,每一个分组内部在分组依据的属性列组合上拥有相同的值。
【例】查询每个教师的教师号及其任课的门数。
SELECT TNo,COUNT(*) AS TeachNumber
FROM TC
GROUP BY TNo
GROUP BY
子句按照TNo
的值进行分组,所有具有相同TNo
的元组被分到一个组里,而后对于分好的每一个组进行COUNT(*)
函数的计算,就能统计出每个教师的任课门数。
【例】查询选修两门及以上课程的学生的学号和选课门数。
SELECT SNo,COUNT(*) AS ClassNumber
FROM SC
GROUP BY SNo
HAVING COUNT(*)>=2
GROUP BY
子句按照SNo
的值进行分组,所有具有相同SNo
的元组被归为一组,在每一个组内进行COUNT(*)
函数的计算,并且HAVING
子句选择那些结果大于等于2的组。
总结来说,当一个SQL查询中同时包含WEHER
、GROUP BY
以及HAVING
子句时,其顺序就是我们列出的顺序。
排序.
当我们需要对查询结果进行排序时,应当使用ORDER BY
子句,ORDER BY
子句必须出现在其它所有的子句之后。并且我们可以指定排序的方式,ASC
为升序,DESC
为降序,默认时采用升序。
【例】查询选修C1课程学生的学号和成绩,按成绩的降序排列。
SELECT SNo,Score
FROM SC
WHERE CNo='C1'
ORDER BY Score DESC
【例】查询选修C2、C3或C4课程学生的学号、课程号和成绩,结果按学号升序排列,学号相同即同一个学生的信息再按成绩降序排列。
SELECT SNo,CNo,Score
FROM SC
WHERE CNo IN ('C2','C3','C4')
ORDER BY SNo ASC,Score DESC
注意,其中ORDER BY SNo ASC,Score DESC
也可以写成ORDER BY SNo,Score DESC
,因为默认情况下采用升序。