VC驿站

 找回密码
 加入驿站

QQ登录

只需一步,快速开始

有编程疑问吗?还请到提问专区发帖提问!
搜索
查看: 367|回复: 0

VC++高级班之数据库篇-[4]深入的SQL查询语言

[复制链接]
51_avatar_middle
online_admins Syc 发表于 2018-4-25 23:50:14 | 显示全部楼层 |阅读模式
上节课介绍了各种简单的查询子句,这些查询都是对一个表进行操作。
在本节及下节会讲解比较复杂的SQL查询语句,主要涉及集合查询、多表查询、嵌套查询。

①、集合查询:
SQL通常都包含一些集合运算,一般都支持并(union)运算,有些SQL版本还有交(intersection)或差(minus)集合运算。
select语句查询的结果是元素的集合,多个select语句的结果可以进行集合操作。但是有个前提就是参与运算的查询结果必须具有相同的列数,
并且对应列的属性域相同。例如:查询选修课程C001的以及年龄小于22的学生的学号:
select sno from students where sage < 22;
select sno from sc where cno = 'C001';
select sno from students where sage < 22 union select sno from sc where cno = 'C001';

SQL Server 2005 支持三种集合操作:union、except 和 intersection。
而 SQL Server 2000 只支持 union。集合操作在两个输入中比较全部行。
union 返回包含两个输入中的所有行的结果集。如果未指定ALL选项,UNION将从结果集中去除重复行。
except 返回出现在左输入但未出现在右输入的不重复行。
intersect 返回在两个输入中都出现过的不重复行。
===================================================
②、连接查询;
连接查询也叫多表查询,通过连接运算符可以实现多个表查询。连接是关系数据库模型的主要特点,
也是它区别于其他类型数据库管理系统的一个标志。

连接查询包括:等值和非等值连接查询、自身连接查询、外连接查询、复合条件连接查询。
===================================================
◆ 等值和非等值连接查询:
其中比较运算符有:=、>、<、>=、<=、!=
比较运算符为 = 号时称为等值连接,其他的称为非等值连接;
连接条件中的列名所指的字段值必须是可比的,但不一定要求是相同的。
例如:要查询学生及学生选课的信息,需要查询students表和sc表,这两个表是通过sno字段相关的,
使用等值连接的SQL语句如下:select students.*, sc.* from students, sc where students.sno = sc.sno;
===================================================
◆ 自身连接查询:
连接操作不仅可以用于两个表之间,也可以是一个表与其自己进行连接,称为自身连接查询。
当一个表所代表的实体之间或列之间有关系时,往往可以用到自身连接查询。
如:科目表的科目中有先修的关系时,则可以添加一个字段 cpre,该字段表示先修的科目号,
新建表如下:

//科目表
create table coursex(
        cno char(8) not null unique,
        cname char(8) not null,
        ccredit smallint,
        cpre char(8)
        );
insert into coursex values ('C001', 'English', 3, NULL);
insert into coursex values ('C002', 'C++', 2, 'C001');
insert into coursex values ('C003', 'Database', 3, 'C002');

例如:要查询各课程的间接先修课程,实现时为了清楚,给表起两个别名:cr1,cr2
实现自身连接查询的SQL语句如下:
select cr1.cno, cr2.cpre from coursex cr1, coursex cr2 where cr1.cpre = cr2.cno;
===================================================
◆ 外连接查询:
在普通的连接查询操作中,只有满足连接条件的记录才能作为结果输出。在前面讲解等值和非等值连接时的例子中,
如果有学生没有选课则选课表中就没有该学生的学号,那么结果中就没有该学生的其他信息。
例如:
select students.*, sc.* from students, sc where students.sno = sc.sno;
这样就看不到学号为0406328的学生信息了。。。

但实际使用时,也许需要显示所有学生的学生信息为要求,如果没有选课,可以在选课信息中设置为空值。
这里就用到了外连接查询,上面的需求用以下SQL实现:
select students.*, sc.* from students, sc where students.sno(*) = sc.sno;
右边括号的为老式写法,SQL Server 2005 已不支持;

select students.*, sc.* from students, sc where students.sno *= sc.sno;
=* 的写法,默认SQL Server 2005也以不支持,但是可以通过更改数据库的兼容性方式来使其支持;
数据库右键属性 -> 选项 -> 兼容级别

select students.*, sc.* from students left outer join sc on students.sno = sc.sno;

解释:外连接的表示方法为,在连接谓词的某一边加*号,外连接好比是在*号所在的表增加了一个万能行,
该行全部由空值组成,它可以和另一边基本表所有不满足连接条件的记录进行连接。
外连接符出现在连接条件的右边,称其为右外连接(有些数据库也用right outer join关键字);
如果外连接符出现在连接条件的左边,称其为左外连接(有些数据库也用left outer join 关键字)。
===================================================
◆ 复合连接查询:
上面介绍的连接查询都是只有一个 where 子句查询条件的,where子句中可以有多个连接条件,
这样的查询称为复合条件查询。多个条件使用 and 关键词连接即可,不再举例说明。
===================================================
③、嵌套查询:
在 select 查询语句里可以嵌入 select 查询语句,称为嵌套查询。
子查询形成的结果又成为父查询的条件。SQL语言允许多层嵌套查询。
※※ 子查询操作的数据表可以是父查询不操作的数据表;
※※ 子查询中不能有 order by 子句,order by 子句只能对最终结果排序。

嵌套查询的求解方法是由里向外处理,即每个子查询在上一级查询处理之前求解,
子查询的结果用于建立其父查询的查找条件。
===================================================
◆ 带有 in 的子查询:
要查询选修了C++课程的学生姓名和系别,SQL语句如下:
select sname , sdept from students where sno in
        (select sno from sc where cno in
                (select cno from course where cname = 'C++')
        );
===================================================
◆ 带有比较运算符的子查询:
带有比较运算符的子查询是指父查询与子查询之间用比较运算符进行连接。
当用户能确切的知道子查询返回的是单值时,可以用 >、<、=、>=、<=、!=、<> 等比较运算符。
要查询和李明同学在同一个系的学生的姓名和年龄,子查询获得李明的系别,该子查询结果必定为一个值,
所以,在这里可以用 = 号,SQL语句如下:
select sname, sage from students where sdept =
        (select sdept from students where sname = '李明');
===================================================
◆ 带有 any 或 all 的子查询:
使用ANY或ALL谓词时则必须同时使用比较运算符,其语义为:
>ANY   大于子查询结果的某个值
>ALL   大于子查询结果中的所有值
<ANY   小于子查询结果中的某个值
<ALL   小于子查询结果中的所有值
>=ANY   大于等于子查询结果中的某个值
>=ALL   大于等于子查询结果中的所有值
<=ANY   小于等于子查询结果中的某个值
<=ALL   小于等于子查询结果中的所有值
=ANY   等于子查询结果中的某个值
=ALL   等于子查询结果中的所有值(通常没有实际意义)
!=(或<>)ANY  不等于子查询结果中的某个值
!=(或<>)ALL  不等于子查询结果中的任何一个值
要查询数学系中比英语系中某个学生年龄小的学生的名字和年龄,SQL语句如下:
select sname, sage from students where sage < any
        (select sage from students where sdept = 'computer')
        and sdept = 'math';
===================================================
◆ 带有 exists 的子查询:
带有EXISTS的子查询不返回任何数据,只产生逻辑值true或false。

先介绍两个概念:不相关子查询、相关子查询;

在之前的子查询例子中可以看出,各子查询都只执行一次查询操作,其结果集合用于父查询。
子查询的查询条件不依赖于父查询,这类子查询称为不相关子查询。

在带有exists的子查询中,查询条件依赖于父查询,这类子查询就称为相关子查询。
例如:查询选修了课程号为C001的课程的学生姓名和系别,SQL语句如下:
select sname, sdept from students where exists
        (select * from sc where sno = students.sno and cno = 'C001');
       
使用存在量词exists之后,若内层查询结果非空,则外层的where子句返回true,否则返回false。

由 exists 引出的子查询,其目标列表达式通常使用 *,因为带 exists 的子查询只返回真值或假值,
给出列名无实际意义。

查询处理过程如下:
首先,取外层查询中students表的第1个元组,根据他与内层查询相关的属性值sno,处理内层查询,
若where子句返回为真,则将该元组放入结果表,然后再取students表的下一个元组,重复这个过程,
直到外层students表检查完毕为止。

与 exists 对应的是 not exists,使用 not exists 之后,若内层查询结果为空,
则外层的where子句返回真值,否则返回假值。
===================================================
===================================================
※※※ 小作业:熟练掌握本节课讲解的各个SQL语句的用法。
------------------------------------- End -------------------------------------------

相关课程演示细节还请观看视频教程!
本套教程由VC驿站原创,提供视频教程+售后答疑服务!
VC驿站Vip会员售后答疑截图【持续更新】:https://www.cctry.com/thread-288054-1-1.html
教程介绍及详情请见:https://www.cctry.com/static/vip/index.html
VC驿站Vip会员详情请见:https://www.cctry.com/static/vip/index.html




上一篇:VC++高级班之数据库篇-[3]简单的SQL查询语言
下一篇:VC++高级班之数据库篇-[5]SQL之数据操纵语言DML的简介及使用

发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

如果你已经在论坛发帖求助,并且从坛友或者管理的回复中解决了问题,请编辑帖子并把分类改成【已解决】

如何回报帮助你解决问题的坛友?可以给对方加【热心】【驿站币】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

您需要登录后才可以回帖 登录 | 加入驿站 qq_login

本版积分规则

QQ|小黑屋|手机版|VC驿站 ( 辽ICP备09019393号tongdun|网站地图wx_jqr

GMT+8, 2018-12-11 02:51

Powered by Discuz! X3.4

© 2009-2018 cctry.com

快速回复 返回顶部 返回列表