在PL/SQL中的数据查询语言
SELECT语句的基本语法格式如下:
SELECT <列> /*SELECT子句,指定列*/
FROM <表或视图> /*FROM子句,指定表或视图*/
[ WHERE <条件表达式> ] /*WHERE子句,指定行*/
[ GROUP BY <分组表达式> ] /*GROUP BY子句,指定分组表达式*/
[ HAVING <分组条件表达式> ] /*HAVING子句,指定分组统计条件*/
[ ORDER BY <排序表达式> [ ASC | DESC ]] /*ORDER子句,指定排序表达式和顺序*/
注:HAVING一定是跟在GROUP BY后面用的。WHERE是对所有记录起作用,HAVING只对组内起作用
ORDER BY,默认是增序(ASC),DEC表示降序
投影查询—SELECT
投影查询用于选择列
投影查询通过SELECT语句的SELECT子句来表示,SELECT子句的语法格式如下:
SELECT [ ALL | DISTINCT ] <列名列表>
其中,<列名列表>指出了查询结果的形式,其格式为:
{ * /*选择当前表或视图的所有列*/
|<表名>|<视图>|.* /*选择指定的表或视图的所有列*/
|{|<列名>|<表达式>}
[[ AS ] <列别名>] /*选择指定的列,为列指定别名*/
| <列标题> = <列名表达式> /*选择指定的列并更改列标题,为列指定别名*/
}[,… n ]
1.投影指定的列—SELECT、FROM、WHERE
使用SELECT语句可选择表中的一个列或多个列,如果是多个列,各列名中间要用逗号分开。
语法格式
SELECT <列名1> [ , <列名2> [,…n] ]
FROM <表名>
[WHERE <条件表达式>]
该语句的功能为在FROM子句指定表中检索符合条件的列。
【例】查询student表中所有学生的学号、姓名和班号。
SELECT sno, sname, sclass
FROM student;
2.投影全部列— *
在SELECT子句指定列的位置上使用*号时,则为查询表中所有列。
【例】查询student表中所有列。
SELECT *
FROM student;
该语句与下面语句等价
SELECT sno, sname, ssex, sbirthday, speciality, sclass, tc
FROM student;
3.修改查询结果的列标题—AS
为了改变查询结果中显示的列标题,可以在列名后使用AS <列别名>。
【例】查询student表中所有学生的学生的sno、sname、speciality,并将结果中各列的标题分别修改为学号, 姓名, 专业。
SELECT sno AS 学号, sname AS 姓名, speciality AS 专业
FROM student;
4.计算列值— + - * /等
使用SELECT子句对列进行查询时,可以对数字类型的列进行计算,可以使用加(+)、减(-)、乘(*)、除(/)等算术运送符,SELECT子句可使用表达式,其语法格式如下:
语法格式:
SELECT <表达式> [ , <表达式> ]
【例】列出goods表的商品号、商品名称和商品总值。
SELECT gid AS 商品号, gname AS 商品名称, price*stockqt AS 商品总值
FROM goods;
5.去掉重复行—DISTINCT
语法格式:
SELECT DISTINCT <列名> [ , <列名>…]
【例】查询student表中sclass列,消除结果中的重复行。
SELECT DISTINCT sclass
FROM student;
选择查询—WHERE
语法格式:
WHERE <条件表达式>
其中,<条件表达式>为查询条件,格式为:
<条件表达式>::=
{ [ NOT ] <判定运算> | (<条件表达式> ) }
[ { AND | OR } [ NOT ] { <判定运算> | (<条件表达式>) } ]
[ ,…n ]
其中,<判定运算>的结果为TRUE、FALSE或UNKNOWN,其格式为:
<判定运算>::=
{ <表达式1> { = | < | <= | > | >= | <> | != } <表达式2> /*比较运算*/
| <字符串表达式1> [ NOT ] LIKE <字符串表达式2> [ ESCAPE '<转义字符>' ]
/*字符串模式匹配*/
| <表达式> [ NOT ] BETWEEN <表达式1> AND <表达式2>
/*指定范围*/
| <表达式> IS [ NOT ] NULL /*是否空值判断*/
| <表达式> [ NOT ] IN ( <子查询> | <表达式> [,…n] )
/*IN子句*/
| EXIST ( <子查询> ) /*EXIST子查询*/
}
| <表达式> IS [ NOT ] NULL /*是否空值判断*/
| <表达式> [ NOT ] IN ( <子查询> | <表达式> [,…n] )
/*IN子句*/
| EXIST ( <子查询> ) /*EXIST子查询*/
}
说明:
(1)判定运算包括比较运算、模式匹配、指定范围、空值判断、子查询等,判定运算的结果为TRUE、FALSE或UNKNOWN。
(2)逻辑运算符包括.AND(与)、OR(或)、 NOT(非),NOT、AND和OR的使用是有优先级的,三者之中,NOT优先级最高,AND次之,OR优先级最低。
(3)条件表达式可以使用多个判定运算通过逻辑运算符成复杂的查询条件。
(4)字符串和日期必须用单引号括起来。
(5)关于[ ESCAPE '<转义字符>' ]
:
在LIKE语句中使用
【例1】LIKE '%M%' ESCAPE 'M'
这里使用ESCAPE关键字定义了转义字符“M”,告诉DBMS将搜索字符串“%M%"中的第二个百分号(%)作为实际值,而不是通配符。当然,第一个百分号(%)仍然被看作是通配符,因此满足该查询条件的字符串为所有以“%”结尾的字符串。
【例2】LIKE 'AB&_%' ESCAPE '%'
此时,我们定义了转义字符“&”,搜索字符串中紧跟“&”之后的字符,即“_
”看作是实际字符值,而不是通配符。而表达式中的“%”,仍然作为通配符进行处理。该表达式的查询条件为以“AB_”开始的所有字符串。
1.表达式比较— = > <
语法格式:
<表达式1> { = | < | <= | > | >= | <> | != } <表达式2>
【例1】查询student表中班号为201205或性别为女的学生。
SELECT *
FROM student
WHERE sclass='201205' or ssex='女';
【例2】查询goods表中价格为3000元以上的商品。
SELECT *
FROM goods
WHERE price>3000;
2.指定范围—BETWEEN、NOT BETWEEN、IN
BETWEEN、NOT BETWEEN、IN是用于指定范围的三个关键字,用于查找字段值在(或不在)指定范围的行。
当要查询的条件是某个值的范围时,可以使用BETWEEN关键字。BETWEEN关键字指出查询范围。
语法格式:
<表达式> [ NOT ] BETWEEN <表达式1> AND <表达式2>
(IN)【例1】查询score表成绩为86、92、95的记录。
SELECT *
FROM score
WHERE grade in (86,92,95);
(BETWEEN)【例2】查询goods表中价格在1500元到4000元之间的商品。
SELECT *
FROM goods
WHERE price BETWEEN 1500 AND 4000;
BETWEEN AND是包括两个边界点的
(NOT BETWEEN)【例3】查询student表中不在1992年出生的学生情况。
SELECT *
FROM student
WHERE sbirthday NOT BETWEEN TO_DATE('19920101','YYYYMMDD') AND
TO_DATE('19921231','YYYYMMDD');
3.模式匹配—LIKE
模式匹配使用LIKE谓词,LIKE谓词用于指出一个字符串是否与指定的字符串相匹配,其运算对象可以是char、varchar2和date类型的数据,返回逻辑值TRUE或FALSE。
语法格式:
<字符串表达式1> [ NOT ] LIKE <字符串表达式2> [ ESCAPE '<转义字符>' ]
在使用LIKE谓词时,<字符串表达式2>可以含有通配符,通配符有以下两种:
%:代表0或多个字符。
_: 代表一个字符。
LIKE匹配中使用通配符的查询也称模糊查询。
【例1】查询student表中姓林的学生情况。
SELECT *
FROM student
WHERE sname LIKE '林%';
【例2】要查询的名称里有单引号(LIKE本身也要用到单引号把要查询的括起来)。例如在goods表查的名称含有 In’spiron 的商品(注意名称里有 ’ )
此时要用到转义字符,不能直接查,不然系统会认为查询到’In’就截止了
在SQLsever里面的转义字符是 \ ,所以如果在SQLsever里,就这样查询:
SELECT *
FROM goods
WHERE gname LIKE '%In\'spiron';
但在Oracle数据库里,默认的转义字符是单引号’,所以在Oracle数据库里这样写:
SELECT *
FROM goods
WHERE gname LIKE '%In''spiron';
第一个是转义字符,第二个是转义的对象,所以到这里系统就知道''
表示一个单引号
也可以用ESCAPE自定义转义字符(前面也有用法举例)
所以也可以这样写:
SELECT *
FROM goods
WHERE gname LIKE '%In@'spiron' ESCAPE '@';
4.空值判断—IS [ NOT ] NULL
语法格式:
<表达式> IS [ NOT ] NULL
【例】查询已选课但未参加考试的学生情况。
SELECT *
FROM score
WHERE grade IS null;
分组查询和统计计算
1.聚合函数—COUNT、SUM、AVG、MAX
聚合函数实现数据的统计计算,用于计算表中的数据,返回单个计算结果。
聚合函数包括COUNT、SUM、AVG、MAX、MIN等函数,下面分别介绍。
(1)COUNT函数
COUNT函数用于计算组中满足条件的行数或总行数。
语法格式:
COUNT ( { [ ALL | DISTINCT ] <表达式> } | * )
其中,ALL表示对所有值进行计算,ALL为默认值,DISTINCT指去掉重复值,COUNT函数用于计算时忽略NULL值。
【例1】求学生的总人数。
SELECT COUNT(*) AS 总人数
FROM student;
该语句采用COUNT(*)计算总行数,总人数与总行数一致。
【例2】】查询201236班学生的总人数。
SELECT COUNT(*) AS 总人数
FROM student
WHERE sclass='201236';
该语句采用COUNT(*)计算总人数,并用WHERE子句指定的条件进行限定为201236。
(2)SUM和AVG函数
SUM函数用于求出一组数据的总和,AVG函数用于求出一组数据的平均值,这两个函数只能针对数值类型的数据。
语法格式:
SUM / AVG ( [ ALL | DISTINCT ] <表达式> )
【例1】查询goods表库存量的总和。
SELECT SUM(stockqt) AS 库存量总和
FROM goods;
【例2】查询1004课程的平均分。
SELECT AVG (grade) AS 课程1004平均分
FROM score
WHERE cno='1004';
(3)MAX和MIN函数
MAX函数用于求出一组数据的最大值,MIN函数用于求出一组数据的最小值,这两个函数都可以适用于任意类型数据。
语法格式:
MAX / MIN ( [ ALL | DISTINCT ] <表达式> )
其中,ALL表示对所有值进行计算,ALL为默认值,DISTINCT指去掉重复值,MAX / MIN函数用于计算时忽略NULL值。
【例】查询8001课程的最高分、最低分、平均成绩。
SELECT MAX(grade) AS 课程8001最高分, MIN(grade) AS 课程8001最低分, AVG(grade) AS 课程8001平均成绩
FROM score
WHERE cno='8001';
2.GROUP BY子句
GROUP BY子句用于指定需要分组的列。
语法格式:
GROUP BY [ ALL ] <分组表达式> [,…n]
【例1】查询各个班级的人数。
SELECT sclass AS 班级, COUNT(*) AS 人数
FROM student
GROUP BY sclass;
看到各个班级就要想到分组,按班分组
使用GROUP BY语句,SELECT后面跟的列是有要求的:要么这个列是跟着GROUP BY的那个(比如例中的sclass),要么这个列要用到聚合函数(比如想要GROUP BY后面跟着的是sno,可以在COUNT的时候用到sno,即COUNT(sno) )
【例2】查询各门课程的最高分、最低分、平均成绩。
SELECT cno AS 课程号, MAX(grade)AS 最高分,MIN (grade)AS 最低分, AVG(grade)AS 平均成绩
FROM score
WHERE NOT grade IS null
GROUP BY cno;
【例3】求选修各门课程的平均成绩和选修人数。
SELECT cno AS 课程号, AVG(grade) AS 平均成绩, COUNT(*) AS 选修人数
FROM score
GROUP BY cno;
3.HAVING子句
HAVING子句用于对分组按指定条件进一步进行筛选,过滤出满足指定条件的分组。
一定要跟GROUP BY一起使用的
语法格式:
[ HAVING <条件表达式> ]
其中,条件表达式为筛选条件,可以使用聚合函数。
当WHERE子句、GROUP BY子句、HAVING子句、ORDER BY子句在一个SELECT语句中时,执行顺序如下:
(1)执行WHERE子句,在表中选择行。
(2)执行GROUP BY子句,对选取行进行分组。
(3)执行聚合函数。
(4)执行HAVING子句,筛选满足条件的分组。
(5)执行ORDER BY子句,进行排序。
【例1】查询平均成绩在90分以上学生的学号和平均成绩。
SELECT sno AS 学号, AVG(grade) AS 平均成绩
FROM score
GROUP BY sno
HAVING AVG(grade)>90;
【例2】查询选修课程3门以上且成绩在85分以上的学生的情况。
SELECT sno AS 学号, COUNT(cno) AS 选修课程数
FROM score
WHERE grade>=85
GROUP BY sno
HAVING COUNT(*)>=3;
【例3】查询至少有5名学生选修且以8开头的课程号和平均分数。
SELECT cno AS 课程号, AVG (grade) AS 平均分数
FROM score
WHERE cno LIKE '8%'
GROUP BY cno
HAVING COUNT(*)>5;
排序查询—ORDER BY
语法格式:
[ ORDER BY { <排序表达式> [ ASC | DESC ] } [ ,…n ]
【例1】将商品类型代码为10的商品按价格排序。
SELECT *
FROM goods
WHERE gclass='10'
ORDER BY price;
【例2】将201236班级的学生按出生时间降序排序。
SELECT *
FROM student
WHERE sclass='201236'
ORDER BY sbirthday DESC;
综合练习
(1)查询student表中计算机专业学生的情况。
SELECT *
FROM student
WHERE speciality='计算机';
(2)查询score表中学号为124003,课程号为4002的学生成绩。
SELECT *
FROM score
WHERE sno='124003' and cno='4002';
(3)查找学号为121002学生所有课程的平均成绩。
SELECT sno AS 学号, avg(grade) AS 平均成绩
FROM score
WHERE sno='121002'
GROUP BY sno;