第三章——关系数据库标准语言SQL——数据查询

📅 2026/7/16 18:22:30
第三章——关系数据库标准语言SQL——数据查询
数据查询SQL提供了SELECT语句进行数据查询该语句具有灵活的使用方式和丰富的功能。其一般格式为SELECT [ALL|DISTINCT] 目标列表达式[,目标列表达式]…FROM 表名或视图名 [,表名或视图名…] | (SELET语句) [AS] 别名[WHERE 条件表达式][GROUP BY 列名1 [HAVING 条件表达式]] [ORDER BY 列名2 [ASC | DESC]];单表查询单表查询是指仅涉及一个表的查询选择表中的若干列选择表中的全部或部分列即关系代数的投影运算(1)查询指定列例1查询全体学生的姓名、学号、所在系SELECT Sname,Sno,SdeptFROM Student;目标列表达式中各个列的先后顺序可以与表中的顺序不一致(2)查询全部列将表中的所有属性列都选出来有两种方法一种方法就是在SELECT关键字后列出所有列名如果列的显示顺序与其在基表中的顺序相同也可以简单地将目标列表达式指定为*例2查询全体学生的详细记录SELECT *FROM Student;等价于SELECT Sno,Sname,Ssex,Sage,SdeptFROM Student;(3)查询经过计算的值SELECT子句的目标列表达式不仅可以是表中的属性列也可以是表达式例3查询全体学生的姓名、出生年份和所在院系要求用小写字母表示系名SELECT Sname NAME,‘Year of Birth:’ BIRTH,2014-Sage BIRTHDAY,LOWER(Sdept) DEPARTMENTFROM Student;目标表达式不仅可以是算术表达式还可以是字符串常量、函数等用户可以通过指定别名来改变查询结果的标题选择表中的若干元组(1)消除取值重复的行两个本来并不完全相同的元组在投影到指定的某些列上后可能会变成相同的行。可以用DISTINCT消除它们如果没有指定DISTINCT关键词则默认为ALL即保留结果表中取值重复的行(2)查询满足条件的元组查询满足条件的元组可以通过WHERE子句实现①比较大小用于进行比较的运算符一般包括(等于)(大于)(小于)(大于等于)(小于等于)!或(不等于)!(不大于)!(不小于)例4查询考试成绩不及格的学生的学号SELECT DISTINCT SnoFROM SCWHERE Grade60;②确定范围谓词BETWWEN…AND…和NOT BETWEEN…AND…可以用来查找属性值在(或不在)指定范围内的元组其中BETWEEN后是范围的下限(即低值)AND后是范围的上限(即高值)例5查询年龄不在20~23岁之间的学生姓名、系别和年龄SELECT Sname,Sdept,SageFROM StudentWHERE Sage NOT BETWEEN 20 AND 23;③确定集合谓词IN可以用来查找属性值属于指定集合的元组例6查询计算机科学系(CS)、数学系(MA)和信息系(IS)学生的姓名和性别SELECT Sname,SsexFROM StudentWHERE Sdept IN(‘CS’,‘MA’,‘IS’);与IN相对的谓词是NOT IN用于查找属性值不属于指定集合的元组④字符匹配谓词LIKE可以用来进行字符串的匹配。其一般语法格式如下[NOT] LIKE ‘匹配串’ [ESCAPE ‘换码字符’]其含义是查找指定的属性列值与匹配串相匹配的元组。匹配串可以是一个完整的字符串也可以含有通配符%和_。其中%(百分号)代表任意长度(长度可以为0)的字符串例如a%b表示以a开头以b结尾的任意长度的字符串。如acb、addgb、ab等都满足该匹配串_(下划线)代表单个字符模式是大小写敏感的例如a_b表示以a开头以b结尾的长度为3的任意字符串。如acb、afb等都满足该匹配串例7查询名字中第二个字为阳的学生的姓名和学号SELECT SnameFROM StudentWHERE Sname LIKE ‘_阳%’;如果LIKE后面的匹配串中不含通配符则可以用(等于)运算符取代LIKE谓词用!或(不等于)运算符取代NOT LIKE谓词数据库字符集为ASCII时一个汉字需要两个_当字符集为GBK时只需要一个_。如果用户要查询的字符串本身就含有通配符%或_这时就要使用ESCAPE ‘换码字符’ 短语对通配符进行转义了例8查询DB_Design课程的课程号和学分SELECT Cno,CcreditFROM CourseWHERE Sname LIKE ‘DB\_Design’ ESCAPE ‘\’;ESCAPE \表示\“为换码字符。这样匹配串中紧跟在”\“后面的字符”_“不再具有通配符的含有转义为普通的”_字符⑤涉及空值的查询例9某些学生选修课程后没有参加考试所以有选课记录但没有考试成绩。查询缺少成绩的学生的学号和相应的课程号SELECT Sno,CnoFROM SCWHERE Grade IS NULL;注意这里的IS不能用等号()代替⑥多重条件查询逻辑运算符AND和OR可用来连接多个查询条件。AND的优先级高于OR但用户可以用括号改变优先级在例6中的IN谓词实际上是多个OR运算符的缩写也可以用OR运算符写成如下等价形式SELECT Sname,SsexFROM StudentWHERE Sdept‘CS’ OR Sdept‘MA’ OR Sdept‘IS’;⑦使用别名SQL用AS子句为关系和属性指定不同的名称或别名以增加可读性其格式为Old-name AS new-name在例6中Sname用姓名表示Ssex用性别表示写成如下等价形式SELECT Sname AS 姓名,Ssex AS 性别FROM StudentWHERE Sdept‘CS’ OR Sdept‘MA’ OR Sdept‘IS’;ORDER BY子句用户可以用ORDER BY子句对查询结果按照一个或多个属性列的升序(ASC)或降序(DESC)排序默认值为升序例10查询全体学生情况查询结果按所在系的系号升序排序同一系中的学生按年龄降序排列SELECT *FROM StudentORDER BY Sdept,Sage DESC;聚集函数为了进一步方便用户增强检索功能SQL提供了许多聚集函数主要有COUNT(*)统一元组个数COUNT([DISTINCT|ALL] 列名)统计一列中值的个数SUM([DISTINCT|ALL] 列名)计算一列值的总和(此列必须是数值型)AVG([DISTINCT|ALL] 列名)计算一列值的平均值(此列必须是数值型)MAX([DISTINCT|ALL] 列名)求一列值中的最大值MIN([DISTINCT|ALL] 列名)求一列值中的最小值如果指定DISTINCT短语则表示在计算时要取消列中的重复值。如果不指定DISTINCT短语或指定ALL短语(ALL为默认值)则表示不取消重复值。例11查询学生201215012选修课程的总学分数SELECT SUM(Ccredit)FROM SC,CourseWHERE Sno‘201215012’ AND SC.CnoCourse.Cno;当聚集函数遇到空值时除COUNT(*)外都跳过空值而只处理非空值。COUNT(*)是对元组进行计数某个元组的一个或部分列取空值不影响COUNT的统计结果。WHERE子句中是不能用聚集函数作为条件表达式的。聚集函数只能用于SELECT子句和GROUP BY中的HAVING子句。GROUP BY子句GROUP BY子句将查询结果按某一列或多列的值分组值相等的为一组对查询结果分组的目的是为了细化聚集函数的作用对象。如果未对查询结果分组聚集函数将作用于整个查询结果。分组后聚集函数将作用于每一个组即每一个组都有一个函数值如果分组后还要求按一定的条件对这些组进行筛选最终只输出满足指定条件的组则可以使用HAVING短语指定筛选条件例12查询选修了三门以上课程的学生学号SELECT SnoFROM SCGROUP BY SnoHAVING COUNT(*)3;这里先用GROUP BY子句按Sno进行分组再用聚集函数COUNT对每一组计数HAVING短语给出了选择组的条件只有满足条件(即元组个数3表示此学生选修的课超过3门)的组才会被选出来。WHERE子句与HAVING短语的区别在于作用对象不同。WHERE子句作用于基本表或视图从中选择满足条件的元组。HAVING短语作用于组从中选择满足条件的组。WHERE子句中不能用聚集函数作为条件表达式连接查询若一个查询同时涉及两个以上的表则称之为连接查询等值与非等值连接查询连接查询的WHERE子句中用来连接两个表的条件称为连接条件或连接谓词其一般格式为[表名 1.] 列名 1比较运算符 [表名 2.] 列名 2此外连接谓词还可以使用下面形式[表名 1.] 列名 1 BETWEEN [表名 2.] 列名 2 AND [表名 3.] 列名 3当连接运算符为时称为等值连接。使用其他运算符称为非等值连接。连接谓词中的列名称为连接字段。连接条件中的各连接字段类型必须是可比的但名字不必相同。例13查询每个学生及其选修课程的情况SELECT Student.*,SC.*FROM Student,SCWHERE Student.SnoSC.sno;本例中SELECT子句与WHERE子句中的属性名前都加上了表名前缀这是为了避免混淆。如果属性名在参加连接的各表中是唯一的则可以省略表名前缀。若在等值连接中把目标列中重复的属性列去掉则为自然连接自身连接连接操作不仅可以在两个表之间进行也可以是一个表与其自己进行连接称为表的自身连接例14查询每一门课的间接先修课(即先修课的先修课)在Course表中只有每门课的直接先修课信息而没有先修课的先修课。要找到这个信息必须先对一门课找到其先修课再按此先修课的课程号查找它的先修课程。这就要将Course表与其自身连接。为此要为Course表取两个别名一个是FIRST另一个是SECOND完成该查询的SQL语句为SELECT FIRST.Cno,SECOND.CpnoFROM Course FIRST,Course SECONDWHERE FRIST.CpnoSECOND.Cno;外连接例13的结果表中没有201215123和201215125两个学生的信息原因在于他们没有选课在SC表中没有相应的元组导致Student中这些元组在连接时被舍弃了有时想以Student表为主体列出每个学生的基本情况及其选课情况。若某个学生没有选课仍把Student的悬浮元组保存在结果关系中而在SC表的属性上填空值NULL这时就需要使用外连接。SELECT Student.Sno,Sname,Ssex,Sdept,Cno,GradeFROM Student LEFT OUTER JOIN SC ON(Student.SnoSC.Sno);左外连接列出左边关系中所有的元组右外连接列出右边关系中所有的元组多表连接连接操作除了可以是两表连接、一个表与其自身连接外还可以是两个以上的表进行连接后者通常称为多表连接例15查询每个学生的学号、姓名、选修的课程名及成绩SELECT Student.Sno,Sname,Cname,GradeFROM Student,SC,CourseWHERE Student.SnoSC.Sno AND SC.CnoCourse.Cno;关系数据库管理系统在执行多表连接时通常是先进行两个表的连接操作再将其连接结果与第三个表进行连接嵌套查询在SQL语言中一个SELECT-FROM-WHERE语句称为一个查询块。将一个查询块嵌套在另一个查询块的WHERE子句或HAVING短语的条件中的查询称为嵌套查询(nested query)上层的查询块称为外层查询或父查询下层查询块称为内层查询或子查询需要特别指出的是子查询的SELCT语句中不能使用ORDER BY子句ORDER BY子句只能对最终查询结果排序带有IN谓词的子查询在嵌套查询中子查询的结果往往是一个集合所以谓词IN是嵌套查询中最经常使用的谓词带有比较运算符的子查询带有比较运算符的子查询是指父查询与子查询之间用比较运算符进行连接。当用户能确切知道内层查询返回的是单个值时可以用、、、、、!或等比较运算符。带有ANY(SOME)或ALL谓词的子查询子查询返回单值时可以用比较运算符但返回多值时要用ANY(有的系统用SOME)或ALL谓词修饰符。而使用ANY或ALL谓词时必须同时使用比较运算符。其语义如下谓词词义等价转换关系ANY大于子查询结果中的某个值MINALL小于子查询结果中的所有值MAXANY小于子查询结果中的某个值MAXALL小于子查询结果中的所有值MINANY大于等于子查询结果中的某个值MINALL小于等于子查询结果中的所有值MAXANY小于等于子查询结果中的某个值MAXALL小于等于子查询结果中的所有值MINANY等于子查询结果中的某个值INALL等于子查询结果中的所有值(通常没有实际意义)--!(或)ANY不等于子查询结果中的某个值NOT IN!(或)ALL不等于子查询结果中的任何一个值--事实上用聚集函数实现子查询通常比直接用ANY或ALL查询效率要高。ANYALL与聚集函数的对应关系如表或!ANYIN- -MAXMAXMINMINALL- -NOT INMINMINMAXMAX带有EXISTS谓词的子查询EXISTS代表存在量词∃。常有EXISTS谓词的子查询不返回任何数据只产生逻辑真值true或逻辑假值false可以利用EXISTS来判断x∈S、S⊆R、SR、S∩R非空等是否成立还可以基于派生表的查询SELECT SnameFROM Student,(SELECT Sno FROM SC WHERE Cno‘1’) AS SC1WHERE Student.SnoSC1.Sno;使用存在量词EXISTS后若内层查询结果非空则外层的WHERE子句返回真值否则返回假值与EXISTS谓词相对应的是NOT EXIST谓词。使用存在量词NOT EXISTS后若内层查询结果为空则外层的WHERE子句返回真值否则返回假值