实验2SQL 语⾔—SELECT 查询操作
实验2 SQL 语⾔—SELECT 查询操作
实验⽬的要求
掌握SQL 程序设计基本规范,熟练运⽤SQL 语⾔实现数据基本查询,包括单表查询、分组统计查询和连接查询。掌握SQL 嵌套查询和集合查询等各种⾼级查询的设计⽅法等。
要求学⽣掌握SQL Server 查询分析器和T -SQL 语⾔的使⽤⽅法,熟练掌握和使⽤简单表的数据查询﹑数据排序和数据连接查询﹑嵌套查询等操作⽅法。
实验仪器设备
学⽣每个⼀台PC 机已安装SQL Server 环境
实验主要内容
针对SQL Server 数据库设计各种单表查询语句、分组统计查询语句;设计单个表针对⾃⾝的连接查询,设计多个表的连接查询。理解和掌握SQL 查询语句各个⼦句的特点和作⽤,按照SQL 程序设计规范写出具体的SQL 查询语句,并调试通过。
针对SQL Server 数据库,正确分析⽤户查询要求,设计各种嵌套查询和集合查询。
本次实验基于图书发⾏数据库系统,进⾏实验
实验原理
# 单表查询
单表查询是指仅涉及⼀个表的查询
SELECT ⼦句后⾯不仅可以是表中的属性列,还可以是表达式、字符串常量、函数:取消取值重复的⾏|保留取值重复的⾏将DISTINCT 换成ALL ,不加则默认ALL 换码、通配符 和对⼀个或多个属性列进⾏排序,⼦句|  |ASC 升序,DESC 降序
聚集函数(放在SELECT 后⾯)
GROUP BY ⼦句:将查询结果按某⼀列或多列的值进⾏分组,值相等的为⼀组:作⽤于组,从中选择满⾜条件的组
# 连接查询
⼀个查询同时涉及两个及以上表的称为连接查询,属性列名前⾯加上表名,即SC.Sno 等值连接查询
连接运算符为=时称为等值连接⾮等值连接查询
连接运算符不是=时称为⾮等值连接⾃然连接
若在等值连接中把⽬标列中重复的属性列去掉则为⾃然连接
单个表的⾃⾝连接查询
多表连接
# 嵌套查询
将⼀个查询块嵌套在另⼀个查询块的WHERE ⼦句或者HAVING 短语的条件中的查询称为嵌套查询⼦查询
带有IN 谓词的⼦查询带有⽐较运算符的⼦查询
带有ANY(SOME)或ALL 谓词的⼦查询带有EXIST 谓词的⼦查询
# 集合查询
集合操作主要包括并操作UNION 、交操作INTERSECT 和差操作EXCEPT
实验记录
# 检索L1从书店S1购买的图书的书号及其册数;DISTINCT SELECT DISTINCT LNO %_ESCAPE
ORDER BY ORDER BY [属性列名] ASC|DESC COUNT(*)  --统计元组个数
COUNT([DISTINCT|ALL]<;列名>)  --统计⼀列中值的个数
SUM(DISTINCT|ALL]<;列名>)  --统计⼀列值的总和(必须是数值型)AVG([DISTINCT|ALL]<;列名>)  --统计⼀列值的平均值(必须是数值型)MAX([DISTINCT|ALL]<;列名>)  --统计⼀列值的最⼤值MIN([DISTINCT|ALL]<;列名>)  --统计⼀列值的最⼩值
GROUP BY HAVING 查询选修了三门以上课程的学⽣的学号SELECT SNO FROM SC GROUP BY SNO HAVING COUNT(*)>3
查询每⼀门课的间接选修课
SELECT FIRST.Cno,SECOND.Cpno FROM Course FIRST,Course SECOND WHERE FIRST.Cpno=
SECOND.Cno;查询每个学⽣的学号、姓名、选秀的课程名及成绩(涉及三个表的查询)、SELECT Student.Sno,Sname,Cname,Grade FROM Student,SC,Course
WHERE Student.Sno=SC.Sno AND SC.Cno=Course.Cno SELECT BNO,QTY FROM 图书发⾏
# 检索馆址在“上海”的图书馆及其电话号码;
SELECT LNAME,TEL
FROM 图书馆
WHERE CITY='上海';
# 检索L4收藏图书的书名;
SELECT 图书.BNAME
FROM 图书,图书发⾏
WHERE 图书发⾏.LNO='L4'AND 图书发⾏.BNO=图书.BNO;
# 检索S3发⾏的图书书名及数量;
SELECT 图书.BNAME,图书发⾏.QTY
FROM 图书,图书发⾏
WHERE 图书发⾏.SNO='S3'AND 图书发⾏.BNO=图书.BNO;
# 检索收藏图书“数据库设计”的馆名;
SELECT 图书馆.LNAME
FROM 图书馆,图书发⾏,图书
WHERE 图书.BNAME='数据库设计'AND 图书.BNO=图书发⾏.BNO
AND 图书馆.LNO=图书发⾏.LNO;
# 检索没有购买上海新华书店出售的图书的图书馆号LNO;
SELECT LNO,LNAME
FROM 图书馆
WHERE LNO NOT IN (SELECT 图书发⾏.LNO
sql语句替换表中内容
FROM 图书发⾏,书店
WHERE 图书发⾏.SNO=书店.SNO AND
书店.SNAME='上海新华书店');
思考题
如何提⾼数据查询和连接速度。
1.对查询进⾏优化,应尽量避免全表扫描,⾸先应考虑在 where 及 order by 涉及的列上建⽴索引。
2.应尽量避免在 where ⼦句中对字段进⾏ null 值判断,否则将导致引擎放弃使⽤索引⽽进⾏全表扫描,如:
select id from t where num is null
可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:
select id from t where num=0
3.应尽量避免在 where ⼦句中使⽤!=或<>操作符,否则将引擎放弃使⽤索引⽽进⾏全表扫描。
4.应尽量避免在 where ⼦句中使⽤ or 来连接条件,否则将导致引擎放弃使⽤索引⽽进⾏全表扫描,如:
select id from t where num=10 or num=20
可以这样查询:
select id from t where num=10
union all
select id from t where num=20
5.in 和 not in 也要慎⽤,否则会导致全表扫描,如:
select id from t where num in(1,2,3)
对于连续的数值,能⽤ between 就不要⽤ in 了:
select id from t where num between 1 and 3
6.下⾯的查询也将导致全表扫描:
select id from t where name like '%abc%'
若要提⾼效率,可以考虑全⽂检索。
7.如果在 where ⼦句中使⽤参数,也会导致全表扫描。因为SQL只有在运⾏时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运⾏时;它必须
在编译时进⾏选择。然⽽,如果在编译时建⽴访问计划,变量的值还是未知的,因⽽⽆法作为索引选择的输⼊项。如下⾯语句将进⾏全表扫描:
select id from t where
可以改为强制查询使⽤索引:
select id from t with(index(索引名)) where
8.应尽量避免在 where ⼦句中对字段进⾏表达式操作,这将导致引擎放弃使⽤索引⽽进⾏全表扫描。如:
select id from t where num/2=100
应改为:
select id from t where num=1002
9.应尽量避免在where⼦句中对字段进⾏函数操作,这将导致引擎放弃使⽤索引⽽进⾏全表扫描。如:
select id from t where substring(name,1,3)='abc'--name以abc开头的id
select id from t where datediff(day,createdate,'2005-11-30')=0--‘2005-11-30’⽣成的id
应改为:
select id from t where name like 'abc%'
select id from t where createdate>='2005-11-30' and createdate<'2005-12-1'
10.不要在 where ⼦句中的“=”左边进⾏函数、算术运算或其他表达式运算,否则系统将可能⽆法正确使⽤索引。
11.在使⽤索引字段作为条件时,如果该索引是复合索引,那么必须使⽤到该索引中的第⼀个字段作为条件时才能保证系统使⽤该索引,否则该索引将不会被
使⽤,并且应尽可能的让字段顺序与索引顺序相⼀致。
12.不要写⼀些没有意义的查询,如需要⽣成⼀个空表结构:
select col1,col2 into #t from t where 1=0
这类代码不会返回任何结果集,但是会消耗系统资源的,应改成这样:
create table #t(...)
13.很多时候⽤ exists 代替 in 是⼀个好的选择:
select num from a where num in(select num from b)
⽤下⾯的语句替换:
select num from a where exists(select 1 from b where num=a.num)
14.并不是所有索引对查询都有效,SQL是根据表中数据来进⾏查询优化的,当索引列有⼤量数据重复时,SQL查询可能不会去利⽤索引,如⼀表中有字段
sex,male、female⼏乎各⼀半,那么即使在sex上建了索引也对查询效率起不了作⽤。
15.索引并不是越多越好,索引固然可以提⾼相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引,
所以怎样建索引需要慎重考虑,视具体情况⽽定。⼀个表的索引数最好不要超过6个,若太多则应考虑⼀些不常使⽤到的列上建的索引是否有必要。
16.应尽可能的避免更新 clustered 索引数据列,因为 clustered 索引数据列的顺序就是表记录的物理存储顺序,⼀旦该列值改变将导致整个表记录的顺序的调
整,会耗费相当⼤的资源。若应⽤系统需要频繁更新 clustered 索引数据列,那么需要考虑是否应将该索引建为 clustered 索引。
17.尽量使⽤数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接
时会逐个⽐较字符串中每⼀个字符,⽽对于数字型⽽⾔只需要⽐较⼀次就够了。
18.尽可能的使⽤ varchar/nvarchar 代替 char/nchar ,因为⾸先变长字段存储空间⼩,可以节省存储空间,其次对于查询来说,在⼀个相对较⼩的字段内搜索
效率显然要⾼些。
19.任何地⽅都不要使⽤ select * from t ,⽤具体的字段列表代替“”,不要返回⽤不到的任何字段。
20.尽量使⽤表变量来代替临时表。如果表变量包含⼤量数据,请注意索引⾮常有限(只有主键索引)。
21.避免频繁创建和删除临时表,以减少系统表资源的消耗。
22.临时表并不是不可使⽤,适当地使⽤它们可以使某些例程更有效,例如,当需要重复引⽤⼤型表或常⽤表中的某个数据集时。但是,对于⼀次性事件,最
好使⽤导出表。
23.在新建临时表时,如果⼀次性插⼊数据量很⼤,那么可以使⽤ select into 代替 create table,避免造成⼤量 log ,以提⾼速度;如果数据量不⼤,为了缓
和系统表的资源,应先create table,然后insert。
24.如果使⽤到了临时表,在存储过程的最后务必将所有的临时表显式删除,先 truncate table ,然后 drop table ,这样可以避免系统表的较长时间锁定。
25.尽量避免使⽤游标,因为游标的效率较差,如果游标操作的数据超过1万⾏,那么就应该考虑改写。
26.使⽤基于游标的⽅法或临时表⽅法之前,应先寻基于集的解决⽅案来解决问题,基于集的⽅法通常更有效。
27.与临时表⼀样,游标并不是不可使⽤。对⼩型数据集使⽤ FAST_FORWARD 游标通常要优于其他逐⾏处理⽅法,尤其是在必须引⽤⼏个表才能获得所需
的数据时。在结果集中包括“合计”的例程通常要⽐使⽤游标执⾏的速度快。如果开发时间允许,基于游标的⽅法和基于集的⽅法都可以尝试⼀下,看哪⼀种⽅法的效果更好。
28.在所有的存储过程和触发器的开始处设置 SET NOCOUNT ON ,在结束时设置 SET NOCOUNT OFF 。⽆需在执⾏存储过程和触发器的每个语句后向客
户端发送 DONE_IN_PROC 消息。
29.尽量避免⼤事务操作,提⾼系统并发能⼒。
30.尽量避免向客户端返回⼤数据量,若数据量过⼤,应该考虑相应需求是否合理。
试⽐较连接查询和嵌套查询
1、意义上的差异
嵌套查询是包含⼀个或多个⼦查询或⼦查询的另⼀个术语的select语句。在外部查询中包含内部查询的另⼀个⼦查询是SQL语句的扩展。
连接查询是关系数据库中最重要的查询。在关系数据库管理系统中,数据之间的关系不需要确定表的建⽴时间,实体的所有信息通常都存储在表中。检
索数据时,通过连接操作查询存储在多个表中的不同实体的信息。
2、特征上的差异
嵌套查询的主要特点是sql允许从内到外进⾏多层嵌套分析,并将⼦查询的结果作为主查询的查询条件。连接是关系数据库模型的主要特征。多表查询
可以通过连接运算符实现。连接操作给⽤户带来极⼤的灵活性,可以随时添加新的数据类型。
基本表数据
图书馆 L.DBF
LNO LNAME CITY TEL
L1上海图书馆上海205800
L2上海外⽂书店上海310310
L3北京图书馆北京282471
L4武汉图书馆武汉812712
L5南京图书馆南京328173
图书 B.DBF
BNO BNAME PRICE
B1数据库原理9.80
B2系统分析与设计8.50
B3数据库设计7.10
B4计算机原理9.60
B5操作系统11.20
书店 S.DBF
SNO SNAME ADDRESS S1北京新华书店北京
S2上海新华书店上海
S3上海外⽂书店上海
S4湖北新华书店武汉
S5江苏新华书店南京
图书发⾏ LBS.DBF
LNO BNO SNO QTY L1B1S210 L1B2S15 L1B3S35 L1B4S520 L2B1S310 L2B4S520 L2B5S415 L4B4S420 L4B5S430 L5B1S210 L5B2S520 L5B4S530

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。