欢迎光临
免费的PDF电子书下载网站

数据库原理与技术(SQL Server 2012) PDF下载

编辑推荐

《数据库原理与技术(SQL Server 2008)》是云南省普通高等学校“十二五”规划教材,从数据库基础理论和实际应用出发,循序渐进、深入浅出地介绍数据库基础知识,包含上机实验操作,并配有例题、练习题和实验指导 ;

内容简介

本书是云南省普通高等学校“十二五”规划教材,共分12章,从数据库基础理论和实际应用出发,循序渐进、深入浅出地介绍数据库基础知识,基于SQL Server 2012介绍数据库的创建、表的操作、索引、视图、数据完整性、SQL Server函数、SQL Server程序设计、存储过程与触发器、SQL Server的安全管理、SQL Server客户端开发与编程等内容;以实例为主线,将“选课管理信息系统”和“计算机计费系统”数据库案例融入各章节,重点阐述数据库的创建、维护、开发与SQL语言程序设计的思想及具体方法;简明扼要地介绍SQL Server的上机实验操作,并配有例题、练习题和实验指导,以便于读者更好地学习和掌握数据库的基本知识与技能。   本书可作为计算机及相关专业的本科教材,也可作为广大计算机爱好者学习数据库技术的参考书。

作者简介

暂无

数据库原理与技术(SQL Server 2012) PDF下载

目录

 ;第1章 ; 数据库技术基础 1

1.1 ; 数据库基础知识 1

 ;1.1.1 ; 信息、数据与数据管理1

 ;1.1.2 ; 数据管理技术的发展1

 ;1.1.3 ; 数据库、数据库管理系统、数据库系统2

 ;1.1.4 ; 数据模型3

 ;1.1.5 ; 数据库系统的体系结构6

1.2 ; 关系数据库 7

 ;1.2.1 ; 关系模型7

 ;1.2.2 ; 关系数据理论10

1.3 ; 数据库设计 14

 ;1.3.1 ; 数据库设计的任务、特点和基本步骤14

 ;1.3.2 ; 需求分析的任务15

 ;1.3.3 ; 概念结构设计16

 ;1.3.4 ; 逻辑结构设计17

 ;1.3.5 ; 数据库设计案例18

1.4 ; 主流数据库简介 21

 ;1.4.1 ;SQL Server 21

 ;1.4.2 ;Oracle 22

 ;1.4.3 ;Sybase ASE 22

 ;1.4.4 ;DB2 23

练习题23

第2章 ; SQL Server 2012综述 24

2.1 ; SQL Server 2012概述 24

 ;2.1.1 ;SQL Server的发展过程24

 ;2.1.2 ;SQL Server 2012的体系结构 25

 ;2.1.3 ;SQL Server 2012的主要特性 27

 ;2.1.4 ;SQL Server 2012的版本 28

2.2 ; SQL Server 2012的安装 29

 ;2.2.1 ;SQL Server 2012安装前的准备工作 29

 ;2.2.2 ; 安装SQLServer 2012 31

 ;2.2.3 ; 升级到SQLServer 2012 43

 ;2.2.4 ;SQL Server 2012安装成功的验证 44

2.3 ; SQL Server 2012的安全性 48

 ;2.3.1 ;SQL Server 2012安全性综述 48

 ;2.3.2 ; 权限验证模式49

 ;2.3.3 ; 数据库用户账号、角色和权限50

2.4 ; SQL Server 2012工具 51

 ;2.4.1 ; 配置SQLServer 2012服务器51

 ;2.4.2 ; 注册和连接SQLServer 2012服务器54

 ;2.4.3 ; 启动和关闭SQLServer 2012服务器57

 ;2.4.4 ;SQL Server 2012的常用工具 58

练习题67

第3章 ; 数据库的基本操作 68

3.1 ; SQL Server数据库的基本知识和概念 68

 ;3.1.1 ;SQL Server的数据库对象68

 ;3.1.2 ;SQL Server的系统数据库69

 ;3.1.3 ; 数据库的组成70

 ;3.1.4 ; 数据库文件组70

 ;3.1.5 ; 数据库的存储空间分配72

3.2 ; 创建数据库 73

 ;3.2.1 ; 使用对象资源管理器创建数据库73

 ;3.2.2 ; 使用T-SQL语句创建数据库78

3.3 ; 查看和设置数据库信息 82

 ;3.3.1 ; 使用SQLServer对象资源管理器查看数据库信息82

 ;3.3.2 ; 使用T-SQL语句查看数据库的信息82

3.4 ; 打开数据库 83

3.5 ; 修改数据库 84

 ;3.5.1 ; 增加数据库的容量84

 3.5.2  缩减数据库容量89

 3.5.3  创建和更改文件组94

 3.5.4  增加或删除数据库文件95

 3.5.5  更改数据库名称99

3.6  分离数据库 100

3.7  附加数据库 101

3.8  删除数据库 103

3.9  应用举例 104

 3.9.1  创建计算机计费数据库104

 3.9.2  创建选课管理数据库104

练习题106

第4章  表的基本操作 108

4.1  SQL Server表概述 108

 4.1.1 SQL Server表的概念108

 4.1.2 SQL Server 2012数据类型 109

4.2  数据库中表的创建 112

 4.2.1  使用对象资源管理器创建表112

 4.2.2  使用T-SQL语句创建表115

4.3  修改表结构 118

 4.3.1  使用对象资源管理器修改表结构118

 4.3.2  使用T-SQL语句修改表结构119

4.4  删除表 120

 4.4.1  使用对象资源管理器删除表121

 4.4.2  使用DROPTABLE语句删除表121

4.5  添加数据 122

 4.5.1  使用对象资源管理器向表中添加数据122

 4.5.2  使用INSERT语句向表中添加数据123

4.6  查看表 124

 4.6.1  查看表结构124

 4.6.2  查看表中的数据125

4.7  应用举例 126

 4.7.1  学生选课管理信息系统的各表定义及创建126

 4.7.2  计算机计费系统的各表定义及创建130

练习题131

第5章  数据的基本操作 132

5.1  关系运算 132

 5.1.1  关系数据结构的形式化定义133

 5.1.2  关系代数134

 5.1.3  关系代数的等价变换规则142

 5.1.4  关系代数表达式应用实例142

5.2  单表查询 144

 5.2.1  完整的SELECT语句的基本语法格式144

 5.2.2  选择表中的若干列145

 5.2.3  选择表中的若干记录147

 5.2.4  对查询的结果排序156

 5.2.5  对数据进行统计158

 5.2.6  用查询结果生成新表161

 5.2.7  集合查询162

5.3  连接查询 165

 5.3.1  交叉连接查询165

 5.3.2  等值与非等值连接查询166

 5.3.3  自身连接查询168

 5.3.4  外连接查询169

 5.3.5  复合连接条件查询171

5.4  子查询 173

 5.4.1  带有IN谓词的子查询173

 5.4.2  带有比较运算符的子查询175

 5.4.3  带有ANY或ALL谓词的子查询178

 5.4.4  带有EXISTS谓词的子查询180

5.5  数据的添加、修改和删除 183

 5.5.1  数据的添加184

 5.5.2  数据的修改191

 5.5.3  数据的删除193

5.6  应用举例 194

练习题197

第6章  索引及视图 200

6.1  索引的基础知识 200

 6.1.1  数据存储200

 6.1.2  索引200

6.2  索引的分类 201

 6.2.1  聚集索引201

 6.2.2  非聚集索引202

 6.2.3  聚集和非聚集索引的性能比较203

 6.2.4  使用索引的原则203

6.3  索引的操作 204

 6.3.1  创建索引204

 6.3.2  查询索引信息208

 6.3.3  重命名索引209

 6.3.4  删除索引209

6.4  索引的分析与维护 210

 6.4.1  索引的分析210

 6.4.2  索引的维护212

6.5  索引应用举例 214

6.6  视图综述 214

 6.6.1  视图的基本概念215

 6.6.2  视图的作用216

6.7  视图的操作 216

 6.7.1  创建视图217

 6.7.2  修改视图221

 6.7.3  重命名视图222

 6.7.4  使用视图223

 6.7.5  删除视图225

6.8  视图定义信息查询 227

 6.8.1  使用对象资源管理器227

 6.8.2  通过执行系统存储过程查看视图的定义信息228

6.9  加密视图 228

6.10  用视图加强数据安全性 229

6.11  视图应用举例 230

练习题231

第7章  数据完整性 232

7.1  数据完整性的概念 232

7.2  约束的类型 233

7.3  约束的创建 234

 7.3.1  创建主键约束234

 7.3.2  创建唯一约束238

 7.3.3  创建检查约束239

 7.3.4  创建默认约束241

 7.3.5  创建外键约束243

7.4  查看约束的定义 245

7.5  删除约束 246

7.6  使用规则 246

7.7  使用默认 248

7.8  数据完整性强制选择方法 249

7.9  应用举例 250

练习题251

第8章  SQL Server函数 252

8.1  内置函数 252

 8.1.1  聚合函数252

 8.1.2  配置函数255

 8.1.3  日期和时间函数256

 8.1.4  数学函数258

 8.1.5  元数据函数259

 8.1.6  字符串函数259

 8.1.7  系统函数262

 8.1.8  排名函数263

 8.1.9  其他新增函数264

8.2  用户定义函数 265

8.3  标量函数 267

8.4  表值函数 270

8.5  应用举例 274

练习题275

第9章  SQL Server程序设计 277

9.1  程序中的批处理、脚本、注释277

 9.1.1  批处理277

 9.1.2  脚本278

 9.1.3  注释279

9.2  程序中的事务 279

 9.2.1  事务概述280

 9.2.2  事务处理语句280

 9.2.3  分布式事务283

 9.2.4  锁定283

9.3  SQL Server变量 284

 9.3.1  全局变量284

 9.3.2  局部变量286

9.4  SQL语言流程控制 289

 9.4.1 BEGIN…END语句块289

 9.4.2  IF…ELSE语句289

 9.4.3 CASE结构290

 9.4.4 WAITFOR语句292

 9.4.5 PRINT语句293

 9.4.6 WHILE语句294

9.5  应用举例 295

练习题297

第10章  存储过程与触发器 298

10.1  存储过程综述 298

 10.1.1  存储过程的概念 298

 10.1.2  存储过程的类型 298

 10.1.3  创建、执行、修改、删除简单存储过程299

 10.1.4  创建和执行含参数的存储过程305

 10.1.5  存储过程的重新编译 305

 10.1.6  系统存储过程与扩展存储过程306

 10.1.7  案例中的存储过程 309

10.2  触发器 311

 10.2.1  触发器的概念 311

 10.2.2  触发器的优点 311

 10.2.3  触发器的类型 312

 10.2.4  DML触发器 313

 10.2.5  DDL触发器 328

 10.2.6  案例中的触发器 329

练习题331

第11章  SQL Server 2012安全管理 333

11.1  SQL Server 2012安全的相关概念 333

 11.1.1  登录验证 333

 11.1.2  角色 334

 11.1.3  许可权限 335

11.2  服务器的安全性管理 335

 11.2.1  查看登录账号 335

 11.2.2  创建一个登录账号 336

 11.2.3  更改、删除登录账号属性 338

 11.2.4  禁止登录账号 338

 11.2.5  删除登录账号 339

11.3  数据库安全性管理 340

 11.3.1  数据库用户 340

 11.3.2  数据库角色 341

 11.3.3  管理权限 344

11.4  数据备份与还原 345

 11.4.1  备份和还原的基本概念 345

 11.4.2  数据备份的类型 346

 11.4.3  还原模式 347

11.5  备份与还原操作 348

 11.5.1  数据库的备份 348

 11.5.2  数据库的还原 350

11.6  备份与还原计划 352

11.7  案例中的安全 353

11.8  案例中的备份和还原操作 357

11.9  数据导出与导入 363

练习题367

第12章  数据库与开发工具的协同使用369

12.1  常用的数据库连接方法 369

 12.1.1  ODBC 369

 12.1.2  OLE DB 371

 12.1.3  ADO 371

12.2  在Visual Basic中的数据库开发373

 12.2.1  Visual Basic简介 373

 12.2.2  在VB中使用ADO数据控件连接数据库373

12.3  在Delphi或C Builder中的数据库开发376

 12.3.1  Delphi与C Builder简介376

 12.3.2  C Builder提供的SQL Server访问机制376

12.4  ASP与SQL Server 2012的协同运用382

 12.4.1  ASP运行环境的建立 382

 12.4.2  在ASP中连接SQLServer 2012数据库383

 12.4.3  ASP与SQL Server 2012数据库协同开发程序的方式385

12.5  案例中的程序 386

 12.5.1  学生信息管理 386

 12.5.2  教师信息管理 389

 12.5.3  学生信息查询 391

练习题393

附录  实验指导 394

参考文献407

 

前沿


  数据库技术是20世纪60年代开始兴起的一门综合性的数据管理技术,也是信息管理中的一项非常重要的技术。进入20世纪90年代后,随着计算机及计算机网络的普及,网络数据库得到了日益广泛的应用。  本书具有以下特色:  (1)理论与实践相结合。本书既介绍数据库的基本理论知识,又有取舍地基于  Windows 7操作系统介绍SQL Server 2012数据库中文版的基本操作及应用。  (2)以实例为主线。结合“选课管理信息系统”和“计算机计费系统”数据库案例,通过精心组织和系统编排,使学生通过案例学会数据库设计,使教学更具有针对性。  (3)本书讲解力求准确、简练,强调知识的层次性和技能培养的渐进性,例题和习题设计丰富实用,注重对学生的SQL Server数据库管理与开发技能的培养。  (4)在内容安排上遵循“循序渐进”与“难点分解”的原则,合理安排各章节内容。  全书共分12章,第1章由申时凯、韩红帮、肖红编写,第2章由邱莎、张志红编写,第3章由李海雁、黄吉花编写,第4章由申时凯、张大卫、佘玉梅编写,第5章由王付艳、申浩如编写,第6章由王武、李凯佳编写,第7章由马宏编写,第8章由段玻编写,第9章由申时凯、邱莎、佘玉梅编写,第10章由邱莎、王玉见编写,第11章和第12章由方刚编写,附录由邱莎、申时凯、何英、李冬萍编写,配套电子教案由上述老师共同制作。申时凯、邱莎、王付艳、方刚任主编,负责全书的策划和修改定稿工作;王武、王玉见、段玻、韩红帮任副主编。  本书得到云南省普通高等学校“十二五”规划教材、云南省科技计划项目(NO.2011FZ176)、昆明市物联网应用技术科技创新团队、昆明学院物联网应用技术科研创新团队(NO.2015CXTD04)、昆明学院应用型人才培养改革创新项目——应用型本科计算机类专业实践教学基地的资助。在本书的编写过程中,得到了日本函馆未来大学姜晓鸿教授的关心和指导,很多老师对本书的组织和协调做了大量工作,不少兄弟院校的老师对本书提出了宝贵的意见和建议。在此对他们深表谢意。  由于编者水平有限,书中不足之处在所难免,敬请广大读者批评指正。      编  者    2017年12月于昆明

免费在线读

数据的基本操作  通过第4章表的基本操作,用户明确了创建表的目的是为了利用表存储和管理数据。本章将首先介绍关系运算的基础知识,然后在第4章建立的如图5-1所示的“学生选课管理信息系统”的student数据库用户表的基础上讲述数据的基本操作。数据的操作主要包括数据库表中数据的增加、修改、删除和查询操作。查询是数据操作的重点,是用户必须重点掌握的数据操作技术。
图5-1  数据库表结构图5.1  关 系 运 算  1.2节介绍了关系数据库的相关概念,关系数据库应用数学方法来处理数据库中的数据,有的人把该处理过程称为关系操作,更多的人则称为关系运算。关系运算是关系数据模型的理论基础,由高度抽象的数学语言来表达,这些语言与具体的数据库管理系统中实现的实际语言并不完全相同,但它们能用于评估实际系统中查询语言的能力高低。关系运算包含关系代数和关系演算两个部分,关系演算以离散数学中的谓词演算为基础,此处限于篇幅,重点讨论关系数据结构的形式化定义和关系代数两个基本内容。5.1.1  关系数据结构的形式化定义  关系模型的数据结构非常单一,就是关系,它由关系数据结构、关系操作集合和关系完整性约束三部分组成。  关系模型中常用的关系操作有查询(Query)、插入(Insert)、删除(Delete)、修改(Update)操作。查询操作又可分为选择(Select)、投影(Project)、连接(Join)、除(Divide)、并(Union)、交(Intersection)、差(Except)和笛卡儿积(Cartesian Product)等。   关系模型的完整性规则是对关系的某种约束条件。有三类完整性约束:实体完整性(Entity Integrity)、参照完整性(Referential Integrity)和用户定义的完整性(User-defined Integrity),将在第7章详细介绍。  如何理解关系?从逻辑上看可以把关系理解为一张二维表,表是用来保持数据库所要描述数据的逻辑数据结构,而非物理结构。下面用集合代数来定义二维表的关系。  定义1  域(Domain)是一组具有相同数据类型的值的集合。  例如,学生性别域是{男,女},学生百分制成绩的域是0~100的整数集合。  定义2  给定一组域D1,D2,…,Dn,则D1,D2,…,Dn的笛卡儿积定义为:  其中,每一个元素(d1,d2,…,dn)称为一个n元组(n-tuple),简称元组(Tuple),元素中每一个值di称为一个分量(Component)。例如,给出两个域,学生姓名域D1={张斌,周红瑜}和专业名称域D2={软件工程,信息管理,经济管理},则D1和D2的笛卡儿积为:{(张斌,软件工程),(张斌,信息管理),(张斌,经济管理),(周红瑜,软件工程),             (周红瑜,信息管理),(周红瑜,经济管理)}表示学生姓名和专业名的所有可能组合。其中(张斌,软件工程)、(周红瑜,信息管理)等都是元组。张斌、周红瑜、软件工程、经济管理等都是分量。若Di(i=1,2,…,n)为有限集,其基数(Cardinal number)为mi(i=1,2,…,n)(基数是一个表中除属性行外的行的总数),则D1×D2×…×Dn的基数为:    上例中D1×D2一共有2×3=6个元组。  定义3  关系(Relation)。  D1×D2×…×Dn的子集叫作在域D1,D2,…,Dn上的关系,表示为R(D1,D2,…,Dn)。R表示关系的名字,n为关系的目或度(Degree),当n=1时,称该关系为单元关系或一元关系(Unary relation);当n=2时,称该关系为二元关系(Binary relation)。关系是笛卡儿积的有限子集,关系也是二维表,表的每行对应一个元组,每列对应一个域。由于域可以相同,如学生学号和身份证号有可能都为整数域,为了加以区分,必须为每列起一个名字,称为属性(Attribute)。n目关系必有n个属性。图5-2给出了用表描述关系的一般格式。  值得注意的是,基本关系具有以下4个特点:  (1)关系(表)可以看成是由行和列交叉组成的二维表。同列具有相同的域,即每一列中的各个分量属于同一数据类型。不同的列可以有相同的域。  (2)表中任意两行(元组)不能完全相同。
图5-2  用表描述关系的一般格式  (3)行的顺序可以任意交换,列的顺序也可任意交换。  (4)各分量必须是原子值,即每一个分量不可再分解,这是由于关系模式要求关系必须满足一定的规范条件,这也是把规范化的关系称为范式的原因。通常数据库中不允许出现非原子分量,即数据表中含有可再分解的“表”,俗称“表中表”现象。5.1.2  关系代数  关系代数是允许从给定关系集合中构造新关系的运算符全集,它是一种抽象的查询语言,是关系数据操纵语言(DML)的一种传统表达方式。关系代数以集合代数为基础发展而来,以关系为运算对象,其运算结果仍为关系。关系代数用到的运算符称为关系运算符,包括传统集合运算符、针对数据库表进行操作的专用运算符以及算术比较和逻辑运算符,如表5-1所示。对关系的每种运算都解决面向数据库的一个询问,用数据库的术语简称为查询或检索。表5-1  关系代数运算符集合运算符专用关系运算符符    号含    义符    号含    义符    号含    义
并(Union)
选择(Selection)
投影(Projection)
交(Intersection)
F连接(Formula Join)
θ连接(Theta Join)—差(Difference)
等值连接(Equijoin)
自然连接(Natural Join)
广义笛卡儿积(ECP)
半连接(Semijoin)
除(Division)逻辑运算符比较运算符符    号含    义符    号含    义符    号含    义
逻辑非(NOT)>大于<小于
逻辑与(AND)≥大于或等于≤小于或等于
逻辑或(OR)=等于<>不等于    1.传统集合运算  传统集合运算把关系看成元组的集合,其运算从“水平”方向即行的角度来进行。设关系R和关系S具有相同的度n(即两个关系都有n个属性),且相应属性取自同一个域,记t为元组变量,定义并、交、差运算如下:  1)并  ,并运算是将两个关系中的所有元组构成一个新关系,结果应该消除重复的元组。  【例5.1】 表5-2(a)和表5-2(b)所示的两个关系:开设C程序设计课程教师情况和Java程序设计课程教师情况,执行并操作得到如表5-2(c) 所示结果,即开设计算机程序设计课程的教师情况。表5-2(a)  C_teachers工    号姓    名性    别所 属 系 部T107何英女   计算机系T207王宁男   计算机系T306李杰男   数学系表5-2(b)  Java_teachers工    号姓    名性    别所 属 系 部T211         张学杰男     信息工程系T107         何英女     计算机系表5-2(c)  C_teachers ∪ Java_teachers工    号姓    名性    别所 属 系 部T107    何英女     计算机系T207    王宁男     计算机系T306    李杰男     数学系T211    张学杰男     信息工程系    2)交  ,交运算得到的关系由既属于R又属于S的元组组成。上例中的,得到如表5-3所示结果,即同时开设两门课程的教师情况。表5-3  C_teachers ∩ Java_teachers工    号姓    名性    别所 属 系 部T107何英女计算机系    3)差  ,差运算得到的关系由属于R而不属于S的所有元组组成。在差运算中顺序非常重要,,上例中表示只开设了C程序设计的教师情况,而则表示只开设了Java程序设计的教师情况,分别如表5-4(a)、(b)所示。表5-4(a)  C_teachers - Java_teachers工    号姓    名性    别所 属 系 部T207王宁男       计算机系T306李杰男       数学系表5-4(b)  Java_teachers - C_teachers工    号姓    名性    别所 属 系 部T211张学杰男信息工程系  4)广义笛卡儿积  在5.1.1节中已给出了笛卡儿积的定义,记作:    笛卡儿积运算得到的关系,其度是R和S的度之和,基数是R和S的基数之积。值得注意的是,笛卡儿积运算得到的结果可能没有任何意义,而且计算代价较大。有时也把笛卡儿积运算叫作交叉连接或非限制连接。  【例5.2】 以“学生”表(见表5-5)和“专业”表(见表5-6)为例说明笛卡儿积的运算过程,两表产生的结果集如表5-7所示。表5-5  “学生”表(Student)学    号(SNO)姓    名(Name)性    别(Sex)系 部 代 码(Dept_NO)专 业 代 码(Spec_NO)010101001001     张斌男010101010102002001     周红瑜女010102010201001001     贾凌云男020201010202002001     向雪林女020202表5-6  “专业”表(Specialty)专 业 代 码(Spec_NO)专 业 名 称(Spec)系 部 代 码(Dept_NO)0101     软件工程010102     信息管理010201     经济管理020202     会计02表5-7  交叉连接的结果表学    号(SNO)姓    名(Name)性  别(Sex)系 部 代 码(Dept_NO)专 业 代 码(Spec_NO)专 业 代 码*(Sp_NO)专 业 名 称(Spec)系 部 代 码*(De_NO)010101001001张斌男0101010101软件工程01010102002001周红瑜女0101020101软件工程01010201001001贾凌云男0202010101软件工程01010202002001向雪林女0202020101软件工程01010101001001张斌男0101010102信息管理01010102002001周红瑜女0101020102信息管理01010201001001贾凌云男0202010102信息管理01010202002001向雪林女0202020102信息管理01010101001001张斌男0101010201经济管理02010102002001周红瑜女0101020201经济管理02010201001001贾凌云男0202010201经济管理02010202002001向雪林女0202020201经济管理02010101001001张斌男0101010202会计02010102002001周红瑜女0101020202会计02010201001001贾凌云男0202010202会计02010202002001向雪林女0202020202会计02  以上执行过程是:把“学生”表(共有5个属性列)中的每一条记录取出(共有4条记录),与“专业”表(共有3个属性列)中的第一条记录连接,形成如表5-7所示的前4条记录;同样地,再取出“学生”表中的每一条记录,与“专业”表中的第二条至第四条记录分别连接,从而形成后12条记录,一共形成了4(来自“学生”表)×4(来自“专业”表)=16条记录,即16个元组,同时,该笛卡儿积有8个属性列=5(来自“学生”表) 3(来自“专业”表)。在表5-7中加“*”的“专业代码”和“系部代码”列是为了区别来自表5-5和表5-6具有相同名称的列。  关系也满足集合运算的若干定律,设关系R、S和Q具有相同的度n,且相应属性取自同一个域,则有:  (1)结合律。          (2)交换律。;  (3)分配律。          (4)吸收律。;  (5)关系的交可以用差来表示。  2.专用关系运算  专用关系运算包括选择、投影、连接、除等。  1)选择  ,在关系R中选择符合条件F的元组,也就是从关系R中选取使逻辑表达式F为真的元组,F由逻辑运算符连接各种算术表达式组成。选择运算是根据某些条件对关系做水平分割,目的是检索一个特定的列中一个给定值的元组或元组集合的所有可能信息。例如,表5-5、表5-6分别列出了学生和专业情况,现在要查询经济管理专业(已知专业代码为0201)的全体学生,用关系代数表示为或,其中下标5是Spec_NO的属性序号。结果如表5-8所示。表5-8  经济管理专业学生的查询结果(选择运算)学    号(SNO)姓    名(Name)性    别(Sex)系 部 代 码(Dept_NO)专 业 代 码(Spec_NO)010201001001贾凌云男020201    若要列出所有女同学的基本情况则表示为或,其中下标3是Sex的属性序号。查询结果如表5-9所示。表5-9  全体女生的查询结果(选择运算)学    号(SNO)姓    名(Name)性    别(Sex)系 部 代 码(Dept_NO)专 业 代 码(Spec_NO)010102002001周红瑜女010102010202002001向雪林女020202    2)投影  ,其中X={A1,A2,…,Ak}是关系R属性的子集,它是先删除在X中没有指明的列,然后删除一些重复的元组(因为取消了某些属性列后,就可能出现重复行),而得到的一个新的关系,即运算结果中的一个元组j的记录是从关系R的元组j选择记录统计tj(A1),tj(A2),…,tj(Ak)而形成的。投影运算是对一个关系做垂直分割,目的是研究某个特定列或者某几个列存在的不同值。例如在表5-5中查询学生学号和姓名,用关系代数表示为或,其中下标1和2分别是SNO和Name的属性序号。查询结果如表5-10所示。表5-10  全体学生的学号、姓名的查询结果(投影运算)学    号(SNO)姓    名(Name)010101001001         张斌010102002001         周红瑜010201001001         贾凌云010202002001         向雪林    若要列出所有系部代码,则应查询表5-6,表示为或,其中下标3是Dept_NO的属性序号。结果如表5-11所示。表5-11  系部代码的查询结果(投影运算)系 部 代 码(Dept_NO)0102    3)连接  连接运算将两个关系连在一起,形成一个新的关系。通常连接也称为θ连接,它是从两个关系的笛卡儿积中选取属性值满足某一条件的元组,即从R和S的广义笛卡儿积R×S中选取(R关系)在A属性上的值与(S关系)在B属性上的值满足比较关系θ的元组,记为:  其中,A和B分别为R和S上度数相等且可比的属性组,θ为比较运算符。θ连接一般不直接被关系数据库厂商支持,它可以被模拟成选择和投影运算。  当θ为“=”时,称该连接为等值连接,它是从R和S的广义笛卡儿积R×S中选取A、B属性值相等的元组,记为:    当要求等值连接得到的结果中去掉重复的属性列时,就产生了一种特殊的等值连接,叫自然连接。自然连接继承了“等值连接两个关系中进行比较的分量必须是相同的属性组”这个规则。一般的连接运算是从行的角度进行,而自然连接还需要消除重复列,同时从行和列的角度进行运算。自然连接记为:    此外,还有一种F连接,从R和S的广义笛卡儿积R×S中选取属性间满足某一公式F的元组,F是形如F1∧F2∧…∧Fi∧…∧Fn的公式,每个Fi等价于的形式。图5-3描述了各种连接的层次关系。
图5-3  各种连接的层次关系  【例5.3】 表5-12~表5-14分别是“学生成绩”表、“成绩等级”表和“选课情况”表。表5-12 “学生成绩”表(SCG)学    号(SNO)课  程  号(CNO)成    绩(Grade)S001Math0188S002Math0290S201Math0178S202Eng1869S301Math0283S302Math0164表5-13 “成绩等级”表(GL)成 绩 边 界(G)等    级(Level)90A80B表5-14 “选课情况”表(CS)课  程  号(CNO)课 程 名 称(Cname)选课学生学号(SNO)选课学生姓名(Sname)Math01高等数学S001       张斌Math02离散数学S002       周红瑜Math01高等数学S201       贾凌云Math02离散数学S301       黄丽Math01高等数学S302       杨素梅    首先,要求列出获得成绩等级的学生情况(包括其成绩等级、所修课程等信息)。用关系代数表示为,这是一个θ连接运算,等价于执行操作。结果如表5-15所示。表5-15  获得成绩等级的学生情况(SCGL)学    号(SNO)课  程  号(CNO)成    绩(Grade)成绩边界(G)等    级(Level)S001Math018880BS002Math029090AS301Math028380B    根据表5-15,列出与表5-14中相匹配的学生情况(包括课程名称、学生姓名等信息)。用关系代数表示为,这是一个自然连接运算,等价于执行

结果如表5-16所示。表5-16  获得成绩等级的学生详细情况学    号(SNO)学生姓名(Sname)课  程  号(CNO)课程名称(Cname)成    绩(Grade)成绩边界(G)等    级(Level)S001  张斌Math01高等数学8880BS002  周红瑜Math02离散数学9090AS301  黄丽Math02离散数学8380B    4)除  在介绍除运算之前先给出像集的定义。关系R(X,Z)中X和Z为属性组,当时,在R中的像集定义为:    表示R中属性组X上值为的诸元组在属性组Z上分量的集合。例如表5-17所示的关系R,其中属性列A可以取三个值,则有:a1的像集为,a2的像集为,a3的像集为。表5-17  关系RABCa1b1c5a2b2c1a1b4c5a3b3c4a2b6c2    由此给出除运算定义:关系R(X,Y)和S(Y,Z),其中X、Y、Z为属性组。R中的Y与S中的Y必须出自同一个域,则,新关系Q是R满足下列条件的元组在X属性组上的投影,即元组在X上分量值x的像集Yx包含S在Y上投影的集合。记作:,其中Yx是x在R上的像集,x=tr[X]。除运算的定义很复杂,用来回答这样的问题:一个表的哪些元组包含在另一个表的某特定列的所有值,其具体计算过程是:  (1)  (2)  (3)  (4)  另给出关系S如表5-18所示。表5-18  关系SUBCu1b1c5u2b4c5    显然,只有a1的像集包含了,因此,,如表5-19所示。表5-19  的结果  A  a1    【例5.4】 给出“学生学习情况”表(见表5-20)和“主干课程成绩等级”表(见表5-21),查询主干课程成绩优秀(等级A)的学生情况(学号、姓名和专业)。表5-20 “学生学习情况”表(SCG)学号(SNO)学生姓名(Sname)专业名称(Spec)课程名称(Cname)成绩等级(Glevel)S001  张小斌 通信工程   计算机网络AS001  张小斌 通信工程   数理方程BS001  张小斌 通信工程   数据结构AS002  周念 计算机科学与技术   计算机网络AS002  周念 计算机科学与技术   数据结构AS301  黄丽丽 计算机科学与技术   数据结构AS201  贾云飞 电子信息工程   计算机网络BS201  贾云飞 电子信息工程   数理方程AS201  贾云飞 电子信息工程   数据结构A表5-21 “主干课程成绩等级”表(CL)课程名称(Cname)等级(Level)                 数据结构A                 计算机网络A    本例是一个典型的除运算例子,即,显然,只有“张小斌”和“周念”两人满足修读主干课程及相应成绩等级的条件,结果如表5-22所示。表5-22  主干课程成绩优秀的学生情况()学    号(SNO)学 生 姓 名(Sname)专 业 名 称(Spec)S001     张小斌     通信工程S002     周念     计算机科学5.1.3  关系代数的等价变换规则  关系代数表达式的满足一些等价变换规则。设E1和E2是关系代数表达式,F是连接条件,L是属性集,则有:  (1)连接交换律、笛卡儿积交换律:,,。  (2)投影串联。,其中L1,L2,…,Ln为属性集,且。  (3)选择串联。,其中,则又有选择的交换律:。  (4)选择对集合并的分配律:,E1和E2具有相同的属性名,或E1和E2表达的关系的属性有对应性。  (5)选择对集合差的分配律:,E1和E2的属性有对    应性。  (6)投影对集合并的分配律:,E1和E2的属性有对      应性。  (7)投影对笛卡儿积的分配律:,L1是E1的属性集,L2是E2的属性集。  (8)选择和投影操作的交换律:,F只涉及L中的属性,若F涉及非L中的属性L,那么就有。  (9)选择对自然连接的分配律:,F只涉及E1和E2的公共属性。  (10)选择与连接操作的结合律:,。  其余规则请读者总结,此处不再详述。5.1.4  关系代数表达式应用实例  并、差、笛卡儿积、投影和选择是关系代数最基本的操作,构成了关系运算的最小完备集。已经证明关系代数、安全的关系演算(对关系演算施加了安全约束条件)在关系的表达和操作能力上是等价的。我们可以用关系代数表达式表示各种数据查询操作,其执行的一般过程如图5-4所示。需要注意的是,当查询涉及否定或全部、包含值时,下述流程就不能完全胜任了,要用到差运算或除运算。
图5-4  关系代数表达式的一般执行流程  【例5.5】 设教学管理数据库中有三个关系,带下画线的属性为主键:  学生关系Student(SNO,Sname,Age,Sex,Sdept)  课程关系Course(CNO,Cname,Cdept)  学习关系SC(SNO,CNO,Grade)  (1)查询电子工程系全体学生的学号、姓名和性别。  属于单表查询,关系代数表达式为。  (2)查询学习课程号为Math02的学生学号与姓名。  属于两表连接查询,关系代数表达式为。  (3)查询选修课程名为“离散数学”的学生学号与姓名。  属于三表连接查询,关系代数表达式为。  (4)至少选修课程号为Math01和Math02的学生学号。  涉及多条件查询,关系代数表达式为,其中,SC1和SC2是关系SC的别名,这里表示关系SC自身进行笛卡儿积运算,而选择表达式则表示同一个学生既选修了Math01课程又选修了Math02课程。  (5)查询没有选修Math02课程的学生学号与姓名。  这里用全体学生的学号与姓名集合同选修了Math02课程的学生学号与姓名集合进行差运算。关系代数表达式为。  (6)查询选修了所有课程(号)的学生学号。  先求学生选课情况,再求开设的全部课程,选修了全部课程的学生学号用除运算表示为。  除了能够正确写出符合查询要求的关系代数表达式外,还应该考虑表达式的优化问题,即系统应该以什么样的操作顺序,才能兼顾时间、空间和效率三者。有一些优化策略,比如,在表达式中尽可能早地执行选择运算;把笛卡儿积和其后的选择操作合并成F连接运算;应对在一个表达式中多次出现的某个子表达式预处理,即预先计算好结果保存起来等等。例如上题中的,可以利用选择对自然连接的分配律,把选择运算移至关系Course前面,得到:    在每个操作后,应做投影运算,挑选完后操作中需要的属性,去掉不用的属性值,减少中间的数据量,最终得到一个比较优化的表达式:
5.2  单 表 查 询  数据库存在的意义在于将数据组织在一起,以方便查询。“查询”的含义就是用来描述从数据库中获取数据和操纵数据的过程。本节主要涉及单个数据表中信息的查询问题。  SQL语言中最主要、最核心的部分是查询功能。查询语言用来对已经存在于数据库的数据按照特定的组合、条件表达式或者一定次序进行检索。其基本格式是由SELECT子句、FROM子句和WHERE子句组成的SQL查询语句:  SELECT <列名表>FROM <表或视图名>WHERE <查询限定条件>    也就是说,SELECT指定了要查看的列(字段),FROM 指定这些数据的来源(表或者视图),WHERE则指定了要查询哪些记录。    注意:在T-SQL语言中,SELECT子句除了进行查询外,其他的很多功能也都离不开SELECT子句,例如,创建视图是利用查询语句来完成的;插入数据时,在很多情况下是从另外一个表或者多个表中选择符合条件的数据。所以查询语句是掌握T-SQL语言的关键。  5.2.1  完整的SELECT语句的基本语法格式  虽然SELECT语句的完整语法较复杂,但是其主要的语法格式可归纳如下:  SELECT select_list  [INTO new_table_name]  FROM table_list[WHERE search_conditions]  [GROUP BY group_by_expression][HAVING search_conditions]  [ORDER BY order_expression [ASC|DESC]]  其中,带有中括号的子句是可选择的,大写的单词表示SQL的关键字,而小写的单词或词组表示表或视图名称或给定的条件。以上语法格式的详细说明如下:* SELECT select_list描述结果集的列,它是一个由逗号分隔的表达式列表。每个表达式通常是从中获取数据的源表或视图的列的引用,但也可能是其他表达式,例如常量或T-SQL函数。在选择列表中使用“*”表达式指定返回源表中的所有列。* [INTO new_table_name]用于指定使用结果集来创建一个新表,new_table_name是新表的名称。* FROM table_list包含从中检索到结果集数据来创建的表的列表,也就是结果集数据来源于哪些表或视图,FROM子句还可包含连接的定义。* [WHERE search_conditions]中的WHERE子句是一个筛选,它定义了源表中的行要满足SELECT语句的要求所必须达到的条件。只有符合条件的行才向结果集提供数据,不符合条件的行中的数据不会被使用。* GROUP BY group_by_expression中GROUP BY子句根据group_by_expression列中的值将结果集分成组。* HAVING search_conditions中HAVING子句是应用于结果集的附加筛选。从逻辑上讲,HAVING子句从中间结果集对行进行筛选,这些中间结果集是用SELECT语句中的FROM、WHERE或GROUP BY子句创建的。HAVING子句通常与GROUP BY子句一起使用,尽管HAVING子句前面不必有GROUP BY子句。* ORDER BY order_expression [ASC | DESC]中ORDER BY子句定义结果集中的行排列的顺序。order_expression指定组成排序列表的结果集的列。ASC和DESC关键字用于指定行是按升序还是按降序排序。5.2.2  选择表中的若干列  选择表中的全部列或部分列就是表的投影运算。这种运算可以通过SELECT子句给出的字段列表来实现。字段列表中的列可以是表中的列,也可以是表达式列。所谓表达式列,就是多个列运算后产生的列或者是利用函数计算后所得的列。  1.输出表中的所有列  将表中的所有字段都在“结果”窗格中列出来,可以有两种方法:一种是将所有的字段名在SELECT关键字后列出来;另一种是在SELECT语句后使用一个“*”。  【例5.6】 查询“学生”表中全体学生的记录。  代码如下:  USE student GOSELECT *FROM 学生GO    在查询编辑器中输入并执行上述代码,将返回学生表中的全部列,如图5-5所示。  2.输出表中部分列  如果在“结果”窗格中列出表中的部分列,可以将要显示的字段名在SELECT关键字后依次列出来,列名与列名之间用英文逗号隔开,字段的顺序可以根据需要来指定。  【例5.7】 查询全体教师的教师编号、姓名和职称信息。
图5-5  查询“学生”表的全部字段  代码如下:  USE studentGOSELECT 教师编号,姓名,职称FROM 教师GO    在查询编辑器中输入并执行上述代码,在“结果”窗格中将只有“教师编号”“姓名”和“职称”三个字段,如图5-6所示。
图5-6  查询全体教师的编号、姓名和职称  3.为“查询结果”窗格内的列指定别名   有时,“查询结果”窗格中的列不是表中现成的列,而是通过表中的一个或多个列计算出来的,这时,需要为这个计算列指定一个列名,同时该表达式将显示在字段列表中。格式如下:  SELCET 表达式 AS 列别名FROM 数据源    【例5.8】 查询“教师”表中全体教师的姓名及年龄。  代码如下:  USE studentGOSELECT 姓名,YEAR(GETDATE())-YEAR(出生日期) AS 年龄FROM 教师GO    其中,“YEAR(GETDATE())-YEAR(出生日期)”是表达式,其含义是取得系统当前日期中的年份减去“出生日期”字段中的年份,就是教师的当前年龄。“年龄”是表达式别名。将上述代码在查询编辑器中输入并执行,返回结果如图5-7所示。
图5-7  带有别名的查询5.2.3  选择表中的若干记录  选择表中的若干记录这就是表的选择运算。这种运算可以通过增加一些谓词(例如WHERE子句)等来实现。  1.消除取值重复的行  两个本来并不相同的记录,当投影到指定的某些列上后,可能变成相同的行。如果要去掉结果集中重复的行,可以在字段列表前面加上DISTINCT关键字。  【例5.9】 查询选修了课程的学生学号。  代码如下:  USE studentGOSELECT 学号FROM 课程注册GO    上述代码执行结果如图5-8所示,选课的学生号有重复,共有36条记录。下面的代码就去掉了重复的学号,仅有7条记录,执行结果如图5-9所示。  USE studentGOSELECT DISTINCT 学号FROM 课程注册GO 图5-8  未去掉重复学号的查询  2.限制返回行数  如果一个表中有上万条记录,而用户只想查看记录的样式和内容,这就没有必要显示全部的记录。如果要限制返回的行数,可以在字段列表之前使用TOP n关键字,则查询结果只显示表中前面的n条记录,如果在字段列表之前使用TOP n PERCENT关键字,则查询结果只显示前面n%条记录。
图5-9  去掉了重复学号的查询   【例5.10】 查询“课程注册”表中的前三条记录的信息。  代码如下:  USE studentGOSELECT TOP 3 *FROM 课程注册GO    在查询编辑器中输入并执行上述代码,执行结果如图5-10所示。
图5-10  显示前三条记录  3.查询满足条件的元组  如果只希望得到表中满足特定条件的一些记录,可以在查询语句中使用WHERE子句。使用WHERE子句的条件如表5-23所示。表5-23  常用的查询条件查 询 条 件运  算  符含    义比较=、>、<、>=、<=、!=、<>、!>; NOT 上述运算符比较大小确定范围BETWEEN…AND…、NOT BETWEEN…AND…判断值是否在范围内确定集合IN、NOT IN判断值是否为列表中的值字符匹配LIKE、NOT LIKE判断值是否与指定的字符通配格式相符空值IS NULL、NOT IS NULL判断值是否为空多重条件AND、OR、NOT用于多重条件判断    1)比较大小  比较运算符是比较两个表达式大小的运算符,各运算符的含义是=(等于)、>(大于)、<(小于)、>=(大于或等于)、<=(小于或等于)、<>(不等于)、!=(不等于)、!<(不小于)、!>(不大于)。逻辑运算符NOT可以与比较运算符同用,对条件求非。  【例5.11】 查询“课程注册”表成绩大于等于50分的记录。  代码如下:  USE studentGOSELECT *FROM 课程注册WHERE 成绩>=50GO    将上述代码在查询编辑器中输入并执行,结果如图5-11所示。
图5-11  查询成绩大于等于50分的记录  2)确定范围  范围运算符BETWEEN…AND…和NOT BETWEEN…AND…可以查找属性值在(或不在)指定的范围内的记录。其中,BETWEEN后是范围的下限(即低值),AND后是范围的上限(即高值)。语法格式如下:  列表达式 [NOT] BETWEEN 起始值AND 终止值    【例5.12】 查询出生日期在1992—1995年的学生姓名、学号和出生日期。  代码如下:  USE studentGOSELECT 姓名,学号,出生日期FROM 学生WHERE year(出生日期) BETWEEN 1992 AND 1995GO    上述代码的含义是:如果返回出生日期的年份大于等于1992且小于等于1995,则该记录会在“结果”窗格中显示。在查询编辑器中输入并执行上述代码,执行结果如图5-12所示。
图5-12  范围查找  3)确定集合  确定集合运算符IN和NOT IN可以用来查找属性值属于(或不属于)指定集合的记录,运算符的语法格式如下:  列表达式[NOT] IN(列值1,列值2,列值3,…)  【例5.13】 查询计算机系(系部代码是01)、经济管理系(系部代码是02)的班级名称与班级编号。  代码如下:  USE studentGOSELECT 班级代码,班级名称FROM 班级WHERE 系部代码 IN(1,2)GO    将上述代码在查询编辑器中输入并执行,结果如图5-13所示。
图5-13  确定集合查询  4)字符匹配  在实际的应用中,用户有时候不能给出精确的查询条件。因此,经常需要根据一些不确定的信息来查询。T-SQL语言提供了字符匹配运算符LIKE进行字符串的匹配运算,实现这类模糊查询。其一般语法格式如下:  [NOT] LIKE <匹配串> [ESCAPE <换码字符>]    其含义是查找指定的属性列值与“<匹配串>”相匹配的记录。“<匹配串>”可以是一个完整的字符串,也可以含有通配符“%”和“_”,其中通配符包括如下四种。  (1)%(百分号),代表任意长度的字符串(长度可以是0)的字符串。例如,a%b表示以a开头、以b结尾的任意长度的字符串。例如,acb、adxyzb、ab等都满足该匹配串。  (2)_(下画线),代表任意单个字符。例如,a_b表示以a开头,以b结尾的长度为3的任意字符串。如afb等。  (3)[]表示中括号里列出的任意一个字符。例如A[BCDE],表示第一个字符是A,第二个字符为B、C、D、E中的任意一个。也可以是字符范围,例如A[B-E]同A[BCDE]的含义相同。  (4)[^]表示不在中括号里列出的任意一个字符。  【例5.14】 查询“学生”表中姓“周”的学生的信息。  代码如下:  USE studentGOSELECT *FROM 学生WHERE 姓名 LIKE 周%GO    通配符字符串“周%”的含义是第一个汉字是“周”的字符串。将上述代码在查询编辑器中输入并执行,执行结果如图5-14所示。
图5-14  模糊查询  如果用户要查询的字符串本身就含有%或_,这时就需要使用“ESCAPE<换码字符>”短语对通配符进行转义了。  【例5.15】 有一门课程的名称是Photoshop CC_2014,查询它的课程号和课程名。  代码如下:  USE studentGOINSERT INTO 课程    (课程号,课程名,学分)VALUES(008,Photoshop CC_2014,4)GOSELECT 课程号,课程名FROM 课程WHERE 课程名 LIKE Photoshop CC/_2014 ESCAPE /GO    “ESCAPE/”短语表示“/”是换码字符,这样匹配串中紧跟在“/”之后的字符“_”不再具有通配符的含义,转义为普通的“_”字符。本例中的INSERT语句是向“课程”表插入一条新记录,以便完成后面的查找任务。INSERT语句将在后续章节中详细讲解。  将上述代码在查询编辑器中输入并执行,结果如图5-15所示。
图5-15  使用“ESCAPE<换码字符>”短语对通配符“_”进行转义  5)涉及空值的查询  一般情况下,表的每一列都有其存在的意义,但有时某些列可能暂时没有确定的值,这时用户可以不输入该列的值,那么这列的值为NULL。NULL与0或空格是不一样的。空值运算符IS NULL用来判断指定的列值是否为空。语法格式如下:  列表达式 [NOT] IS NULL    【例5.16】 查询“教师”表中备注字段为空的教师信息。  代码如下:  USE studentGOSELECT *FROM 教师WHERE 备注 IS NULLGO    这里的IS运算符不能用“=”代替。将上述代码在查询编辑器中输入并执行,执行结果如图5-16所示。
图5-16  查询空值  6)多重条件查询  用户可以使用逻辑运算符AND、OR、NOT连接多个查询条件,实现多重条件查询。逻辑运算符使用格式如下:  [NOT] 逻辑表达式 AND|OR [NOT] 逻辑表达式    【例5.17】 查询“课程注册”表中课程号为0001成绩在80~89分(不含89分)的学生的学号、成绩。  代码如下:  USE studentGOSELECT 学号,成绩FROM 课程注册WHERE 课程号=001 AND 成绩>=80 AND 成绩<89GO    将上述代码在查询编辑器中输入并执行,结果如图5-17所示。
图5-17  多重条件查询5.2.4  对查询的结果排序  可以使用ORDER BY子句对查询结果按照一个或多个属性列的升序(ASC)或降序(DESC)排列,默认为升序。如果不使用ORDER BY子句,则结果集按照记录在表中的顺序排列。ORDER BY子句的语法格式如下:  ORDER BY {列名 [ASC|DESC]}[,…n]    当按多列排序时,先按前面的列排序,如果值相同再按后面的列排序。  【例5.18】 查询选修了0001号课程的学生的学号,并按成绩降序排列。  代码如下:  USE studentGOSELECT 学号,成绩FROM 课程注册WHERE 课程号=001ORDER BY 成绩 DESCGO    将上述代码在查询编辑器中输入并执行,结果如图5-18所示。  【例5.19】 查询全体学生信息,查询结果按所在班级代码降序排列,同一个班的按照学号升序排列。
图5-18  将查询结果降序排序  代码如下:  USE studentGOSELECT *FROM 学生ORDER BY 班级代码 DESC,学号 ASCGO    将上述代码在查询编辑器中输入并执行,结果如图5-19所示。
图5-19  组合排序5.2.5  对数据进行统计  需要对结果集进行统计,例如求和、平均值、最大值、最小值、个数等,这些统计可以通过集合函数、COMPUTE子句、GROUP BY子句来实现。  1.使用集合函数  为了进一步方便用户,增强检索功能,SQL Server提供了许多集合函数,主要有:  (1)COUNT( [ DISTINCT | ALL ] * )统计记录个数。  (2)COUNT( [ DISTINCT | ALL ] <列名> )统计一列中值的个数。  (3)SUM( [ DISTINCT | ALL ] <列名> )计算一列值的总和(此列必须是数值型)。  (4)AVG( [ DISTINCT | ALL ] <列名> )计算一列值的平均值(此列必须是数值型)。  (5)MAX( [ DISTINCT | ALL ] <列名> )求一列值中的最大值。  (6)MIN( [ DISTINCT | ALL ] <列名> )求一列值中的最小值。  在SELECT子句中,集合函数用来对结果集记录进行统计计算。DISTINCT是去掉指定列中的重复信息的意思,ALL是不取消重复,默认是ALL。  【例5.20】 查询“教师”表中的教师总数。  代码如下:  USE studentGOSELECT COUNT(*) AS 教师总数FROM 教师GO    将上述代码在查询编辑器中输入并执行,结果如图5-20所示。
图5-20  统计记录总数  【例5.21】 查询“课程注册”表中学生的成绩平均分。  代码如下:USE studentGOSELECT AVG (成绩) AS 平均分FROM 课程注册GO    将上述代码在查询编辑器中输入并执行,结果如图5-21所示。
图5-21  求学生成绩的平均分  2.对结果进行分组  GROUP BY子句将查询结果集按某一列或多列值分组,分组列值相等的为一组,并对每一组进行统计。对查询结果集分组的目的是为了细化集合函数的作用对象。GROUP BY子句的语法格式为:  GROUP BY列名 [HAVING筛选条件表达式]  其中:* “BY 列名”是按列名指定的字段进行分组,将该字段值相同的记录组成一组,对每一组记录进行汇总计算并生成一条记录。* “HAVING筛选条件表达式”表示对生成的组筛选后再对满足条件的组进行统计。  SELECT子句的列名必须是GROUP BY子句已有的列名或是计算列。  【例5.22】 查询“课程注册”表中课程选课人数4人以上的各个课程号和相应的选课人数。  代码如下:  USE studentGOSELECT 课程号,COUNT(*) AS 选课人数FROM 课程注册GROUP BY 课程号HAVING COUNT(*)>=4GO    将上述代码在查询编辑器中输入并执行,结果如图5-22所示。  HAVING与WHERE子句的区别在于作用的对象不同。HAVING作用于组,选择满足条件的组;WHERE子句作用于表,选择满足条件的记录。
图5-22  分组统计  3.使用COMPUTE子句  COMPUTE子句对查询结果集中的所有记录进行汇总统计,并显示所有参加汇总记录的详细信息。使用语法格式如下:  COMPUTE 集合函数 [BY 列名]  其中:* 集合函数,例如SUM()、AVG()、COUNT()等。* “BY列名”按指定“列名”字段进行分组计算,并显示被统计记录的详细信息。* BY选项必须与ORDER BY子句一起使用。  COMPUTE BY子句之前要使用ORDER BY子句,原因是必须先按分类字段排序之后才能使用COMPUTE BY子句进行分类汇总。COMPUTE BY与GROUP BY子句的区别在于:前者既显示统计记录又显示详细记录,后者仅显示分组统计的汇总记录。    注意:SQL Server 2012废弃了COMPUTE和COMPUTE BY功能,此处不再举例赘述。5.2.6  用查询结果生成新表  在实际的应用系统中,有时需要将查询结果保存成一个表,这个功能可以通过SELECT语句中的INTO子句实现。INTO子句语法格式如下:  INTO 新表名  其中:* 新表名是被创建的新表,查询的结果集中的记录将添加到此表中。* 新表的字段由结果集中的字段列表决定。* 如果表名前加“#”则创建的表为临时表。* 用户必须拥有该数据库中建表的权限。* INTO子句不能与COMPUTE子句一起使用。  【例5.23】 创建“课程注册”表的一个副本。  代码如下:  USE studentGOSELECT * INTO 课程注册副本FROM 课程注册GOSELECT *FROM 课程注册副本GO    将上述代码在查询编辑器中输入并执行,结果如图5-23所示。
图5-23  生成新表  【例5.24】 创建一个空的“教师”表的副本。  代码如下:USE studentGOSELECT * INTO 教师副本FROM 教师WHERE 1=2GO    上述代码中WHERE子句的条件永远为“假”,所以不会在创建的表中添加记录。在查询编辑器中输入并执行上述代码,用户可以查看到新建的表,但表中没有添加任何记录,如图5-24所示。
图5-24  创建教师空表副本5.2.7  集合查询  集合操作主要包括并操作UNION、交操作INTERSECT和差操作EXPECT。参加集合操作的各结果的列数量和对应的数据类型必须相同。  使用UNION语句可以将多个查询结果集合并为一个结果集,也就是集合的合并操作。UNION子句的语法格式如下:  SELECT语句{UNION  SELECT语句}[,…n]                其中:* 参加UNION操作的各结果集的列数必须相同,对应的数据类型也必须相同。* 系统将自动去掉并集的重复记录,如果要保留重复记录需使用UNION ALL操作符。* 最后结果集的列名来自第一个SELECT语句。  【例5.25】 查询“课程注册”表中选修了0001课程或者选修了0002课程的学生,也就是选修了课程0001的学生集合与选修了课程0002的学生集合的并集,且按课程号升序排列。  代码如下:  USE studentGOSELECT *FROM 课程注册WHERE 课程号=001UNIONSELECT * FROM 课程注册WHERE 课程号=002ORDER BY 课程号 ASCGO    将上述代码在查询编辑器中输入并执行,可得到如图5-25所示的结果。
图5-25  查询结果的并操作  使用INTERSECT语句和EXCEPT语句的语法结构与UNION相似,此处不再赘述。  【例5.26】 查询“课程注册”表中既选修了0001课程又选修了0002课程的学生学号,即选修了课程0001的学生集合与选修了课程0002的学生集合的交集,结果按学号升序排列。图5-26显示了查询结果。代码如下:  USE studentGOSELECT 学号FROM 课程注册WHERE 课程号=001INTERSECTSELECT 学号 FROM 课程注册WHERE 课程号=002ORDER BY 学号 ASCGO
图5-26  查询结果的交操作  【例5.27】 查询“课程注册”表中选修了0001课程而未选修0005课程的学生学号,即选修了课程0001的学生集合与选修了课程0005的学生集合的差集,结果按学号升序排列。如图5-27给出了查询结果。代码如下:  USE studentGOSELECT 学号FROM 课程注册WHERE 课程号=001EXCEPTSELECT 学号 FROM 课程注册WHERE 课程号=005ORDER BY 学号 ASCGO  
图5-27  查询结果的差操作5.3  连 接 查 询  5.2节所述查询是单表查询。若一个查询同时涉及两个或两个以上的表,则称为连接查询。连接查询是关系数据库中最主要的查询,包括等值与非等值查询、自然连接查询、自身连接查询、外连接查询和复合条件连接查询等。5.3.1  交叉连接查询  交叉连接又称非限制连接,也叫广义笛卡儿积,交叉连接的执行过程已在5.1节做了深入讨论。现给出其语法格式:  SELECT 列表列名 FROM 表名1 CROSS JOIN 表名2    其中,CROSS JOIN为交叉表连接关键字。  【例5.28】 使用示例中的“学生”表、“专业”表,实现交叉查询。  代码如下:  USE studentGOSELECT 学号,姓名,性别,学生.系部代码,学生.专业代码,专业.专业代码,专业名称,专业.系部代码FROM 学生 CROSS JOIN 专业GO    在查询分析器中输入并执行上述代码,结果如图5-28所示。
图5-28  交叉连接的执行结果  在例5.28的查询语句中,由于“学号”“姓名”“性别”和“专业名称”列在“学生”表、“专业”表中是唯一的,因此引用时可去掉表名前缀。而“系部代码”“专业代码”在两个表中都出现了,引用时必须加上表名前缀。    注意:多表查询时,如果要引用不同表中的同名属性,则在属性名前加表名,即用“表名.属性名”的形式表示,以便区分。  5.3.2  等值与非等值连接查询  用来连接两个表的条件称为连接条件或连接谓词,其一般格式为:  [<表名1>.]<列名1>  <比较运算符>  [<表名2>.]<列名2>  其中,比较运算符主要是=、>、<、>=、<=、!=(或<>)。  当比较运算符为“=”时,称为等值连接。使用除等号外的其他运算符的称非等值连接。与比较运算符一起组成连接条件的列名称为连接字段。连接字段的类型必须是可比的,但名字不必相同。  在例5.28中,如果使用等值连接,其过程如下:把“学生”表中的每一条记录取出,与“专业”表中的第一条记录比较,如果“专业代码”列值相等(连接条件),则连接形成第一条记录,否则不连接;同样地,再取出“学生”表中的每一条记录,与“专业”表中的第二条、第三条、第四条……比较,若“专业代码”列值相等,则分别连接;否则不连接。这样的操作,要进行到“专业”表中的全部记录都处理完毕为止。  通过以上描述,可得出结论:等值连接的过程类似于交叉连接,不过,它只将满足连接条件的记录连接到结果集中。其语法格式为:  SELECT 列表列名FROM 表名1 [INNER] JOIN表名2ON 表名1.列名=表名2.列名  其中,INNER是连接类型可选关键字,表示内连接,可以省略。“ON 表名1.列名=表名2.列名”是等值连接的连接条件。  【例5.29】 用等值连接方法连接“学生”表和“专业”表,观察通过“专业代码”连接后的结果与交叉连接的结果有何区别。  代码如下:  USE studentGOSELECT 学号,姓名,性别,学生.系部代码,学生.专业代码,专业.专业代码,专业名称,专业.系部代码FROM 学生 INNER JOIN 专业 ON 学生.专业代码=专业.专业代码GO    在查询分析器中输入并执行上述代码,结果如图5-29所示。
图5-29  等值连接的执行结果  从结果中可以发现,只有满足连接条件的记录才被连接到结果集中,结果集是两个表的交集。在如图5-29所示的图中,“系部代码”“专业代码”列有重复。在等值连接中,把目标列中重复的属性列删除,称为自然连接。  【例5.30】 自然连接“学生”表和“专业”表。  代码如下:  USE studentGOSELECT 学号,姓名,性别,学生.系部代码,专业.专业代码,专业名称FROM 学生 JOIN 专业 ON 学生.专业代码=专业.专业代码GO    在查询分析器中输入并执行上述代码,结果如图5-30所示。  例5-30中“系部代码”列和“专业代码”列在两表中都出现过,只需引用一个即可,但引用时必须加上相应的表名前缀。
图5-30  自然连接的执行结果5.3.3  自身连接查询  连接操作既可在多表之间进行,也可以是一个表与其自己进行连接,称为表的自身连接。使用自身连接时,必须为表指定两个别名,以示区别。  【例5.31】 使用“教师任课”表,查询至少为两个专业开设课程的教师编号和专业代码。  代码如下:  USE studentGOSELECT first.教师编号,second.专业代码FROM 教师任课 AS first JOIN 教师任课 AS secondON first.教师编号=second.教师编号 AND first.专业代码!=second.专业代码GO    在查询分析器中输入并执行上述代码,结果如图5-31所示。
图5-31  自身连接的执行结果5.3.4  外连接查询  外连接的结果集不但包含满足连接条件的行,还包括相应表中的所有行,也就是说,即使某些行不满足连接条件,但仍需要输出该行记录。外连接包括三种:左外连接、右外连接和完全外连接。  1.左外连接  左外连接(Left Outer Join)是指结果表中除了包含满足连接条件的记录外,还包含左表中不满足连接条件的记录。    注意:左表中不满足条件的记录与右表记录连接时,右表的相应列上填充NULL值。左外连接的语法格式为:  SELECT 列表列名FROM 表名1 LEFT [OUTER] JOIN 表名2ON 表名1.列名=表名2.列名  其中,OUTER关键字可省略。  【例5.32】 将“学生”表左外连接“成绩”表。  代码如下:  USE studentGOSELECT 学生.学号,学生.姓名,性别,系部代码,语文,数学,英语,美术,自然,体育,音乐FROM 学生 LEFT OUTER JOIN 成绩 ON 学生.学号=成绩.学号GO    在查询分析器中输入并执行上述代码,结果如图5-32所示。其含义是:以“学生”表为主体列出每个学生的基本情况及其课程成绩,而无论该生是否有该门课程的成绩,若没有该门课成绩,则在相应位置填空值(Null),这就避免了在连接时舍弃成绩全为空的学生基本信息,即保留图中贾凌云、周红瑜、李晨、周春梅、张雪琪、李艾一6名学生的基本信息。
图5-32  左外连接的执行结果  2.右外连接  右外连接(Right Outer Join)是指结果表中除了包含满足连接条件的记录外,还包含右表中不满足连接条件的记录。    注意:右表中不满足条件的记录与左表记录连接时,左表的相应列上填充NULL值。右外连接的语法格式为:  SELECT 列表列名FROM 表名1 RIGHT [OUTER] JOIN 表名2ON 表名1.列名=表名2.列名  其中,OUTER关键字可省略。  【例5.33】 将“学生”表右外连接“成绩”表。  代码如下:  USE studentGOSELECT 学生.学号,学生.姓名,性别,系部代码,语文,数学,英语,美术,自然,体育,音乐FROM 学生 RIGHT OUTER JOIN 成绩 ON 学生.学号=成绩.学号GO    输入并执行上述代码的结果如图5-33所示。我们发现在连接时舍弃了成绩全为空的学生基本信息,即删除了图5-32中贾凌云、周红瑜、李晨、周春梅、张雪琪、李艾一的基本信息,表明该右外连接是以“成绩”表为主体列出每个学生的基本情况及其课程成绩的。
图5-33  右外连接的执行结果  3.完全外连接  同理,完全外连接(Full Outer Join)是指结果表中除了包含满足连接条件的记录外,还包含两个表中不满足连接条件的记录。    注意:左(右)表中不满足条件的记录与右(左)表记录连接时,右(左)表的相应列上填充NULL值。完全外连接的语法格式为:  SELECT 列表列名FROM 表名1 FULL [OUTER] JOIN 表名2ON 表名1.列名=表名2.列名  其中,OUTER关键字可省略。5.3.5  复合连接条件查询  以上各个连接查询中,ON连接条件表达式只有一个条件,允许ON连接表达式有多个连接条件,称为复合条件连接,或多表连接。实际上,在例5-31中已经给出了多表连接的应用。这里再举一例。  【例5.34】 使用“学生”表、“课程”表和“课程注册”表,查询成绩在70~80分(含70分和80分)的学生学号、姓名、专业代码,选修课的课程号、课程名称以及对应的        成绩。  代码如下:  USE studentGOSELECT S.学号,S.姓名,S.专业代码,C.课程号,CN.课程名,C.成绩FROM 学生 AS S JOIN 课程注册 AS CON S.学号=C.学号 AND C.成绩>=70 AND C.成绩<=80JOIN 课程 AS CNON C.课程号=CN.课程号GO    在查询分析器中输入并执行上述代码,结果如图5-34所示。
图5-34  复合连接条件的执行结果  用WHERE子句改写例5.34,可简化代码如下,其执行结果与图5-34一致:  USE studentGOSELECT S.学号,S.姓名,S.专业代码,C.课程号,CN.课程名,C.成绩FROM 学生 AS S,课程注册 AS C, 课程 AS CNWHERE S.学号=C.学号 AND C.课程号=CN.课程号 AND C.成绩>=70 AND C.成绩<=80GO5.4  子  查  询  SQL语言作为一门超高级语言,继承了其他计算机语言的主要特征,例如,将要讲述的嵌套查询就类似于程序语言中的循环嵌套。通常把一个SELECT-FROM-WHERE语句组称为一个查询块。将一个查询块嵌套在另一个查询块的WHERE子句或HAVING短语条件中的查询称为嵌套查询(Nested Query)。例如:  SELECT 姓名FROM 学生WHERE 学号 IN ( SELECT 学号 FROM 课程注册 WHERE 教师编号=100000000001 )    括号内的查询块作为括号外WHERE子句的条件嵌入SQL语句中。我们把括号内的查询块称为子查询或内层查询,与之相对的概念就是父查询或外层查询,即包含子查询的查询块。SQL语言允许多层嵌套查询,但需要注意的是,子查询的SELECT语句中不能使用ORDER BY子句,ORDER BY子句只能对最终查询结果进行排序,也不能包括COMPUTE 或FOR BROWSE子句。  SQL Server 2012对嵌套查询的求解顺序是先内后外。即每个子查询在上一级查询处理之前求解,子查询的结果用于建立父查询的查找条件。有了嵌套查询,可以用多个简单的查询构造复杂查询(嵌套不能超过32层),提高SQL语言的表达能力,以这样的方式来构造查询程序,层次清晰,易于实现,这正是SQL中“结构化(structured)”的内涵所在。  某些嵌套查询可用连接运算替代,某些则不能。到底采用哪种方法,用户可根据实际情况判断。5.4.1  带有IN谓词的子查询  在嵌套查询中,子查询的结果通常是一个集合。IN是嵌套查询中使用最频繁的谓词。其处理过程是:父查询通过IN谓词将父查询中的一个表达式与子查询返回的结果集进行比较,如果表达式的值等于子查询结果集中的某个值,父查询中的条件表达式返回真(TRUE),否则返回假(FALSE)。还可以在IN前加上关键字NOT,其功能与IN相反。  【例5.35】 使用“学生”表、“课程”表和“课程注册”表,查询选修了课程名为“高等数学”或“计算机导论”的学生的学号和姓名。  代码如下:  USE studentGO
SELECT 学号,姓名FROM 学生WHERE 学号 IN (SELECT 学号 FROM 课程注册 WHERE 课程号 IN (SELECT 课程号 FROM 课程 WHERE 课程名=高等数学 OR课程名=计算机导论 ) )GO    例5.35涉及三个属性:学号、姓名和课程名。学号和姓名存放在“学生”表中,课程名存放在“课程”表中,两个表通过“课程注册”表建立联系,所以本例涉及三个关系(如上面标号所示):  (1)在“课程”表中找到“高等数学”或“计算机导论”两课程的课程号,结果为0002或0003。  (2)在“课程注册”表中找出选修了(1)中课程的学生学号,结果为140101001001、140101001011、140201001001、140202002001、150102002001、150102002007、150102002018。  (3)在“学生”表中取出(2)中的学号和对应的姓名。  在查询分析器中输入并执行上述代码,结果如图5-35所示。
图5-35  带有IN运算符的子查询的执行结果  例5.35同样可用连接查询实现,代码如下,执行结果与图5-35一致:  USE studentGOSELECT DISTINCT 学生.学号,姓名FROM 学生,课程注册,课程WHERE 学生.学号 = 课程注册.学号 AND    课程注册.课程号 = 课程.课程号 AND    (课程名=高等数学 OR 课程名=计算机导论)GO5.4.2  带有比较运算符的子查询  5.4.1节示例中子查询的查询条件不依赖于父查询,这类子查询称为不相关子查询;反之,则称为相关子查询(Correlated Subquery)。  父查询与子查询之间通过比较运算符连接,便形成了带有比较运算符的子查询。其处理过程是:父查询通过诸如=、>、<、>=、<=、!=或<>等比较运算符将父查询中的一个表达式与子查询返回的结果(单值)进行比较,如果表达式的值与子查询结果相比为真,那么,父查询中的条件表达式返回真(TRUE),否则返回假(FALSE)。  要强调的是,带有IN运算符的子查询返回的结果是集合,而带有比较运算符的子查询返回的结果是单值,而且用户在查询开始时就知晓“内层查询返回的是单值”这一事实。在书写带比较运算符的子查询时,注意子查询一定要跟在比较运算符之后。特殊地,若IN的子查询结果集为单值,则“=”符号和IN可以互换,如图5-36所示。
图5-36  查询与“王钢”(含王钢本人)同在一个系的教师基本信息  【例5.36】 使用“教师”表,查询与“王钢”同在一个系的教师基本信息。  代码如下:  USE studentGOSELECT 教师编号,姓名,性别,学历,职务,职称FROM 教师WHERE 系部代码= (SELECT 系部代码 FROM 教师 WHERE 姓名=王钢 )GO    在查询分析器中输入并执行上述代码,结果如图5-36所示,结果集中包括“王钢”本人的情况,若要去掉“王钢”本人的情况,则代码改写为图5-37即可。
图5-37  查询与“王钢”(不含王钢本人)同在一个系的教师基本信息  【例5.37】 找出每个学生超过他所修课程平均成绩的课程号。  代码如下:  USE studentGOSELECT 学号,课程号FROM 课程注册 AS xWHERE 成绩>= (SELECT AVG(成绩) FROM 课程注册 AS y WHERE y.学号=x.学号 )GO    其中,x和y都是课程注册表的别名。子查询是求解一个学生所有课程的平均成绩,至于是哪名学生的平均成绩要看x.学号的值,而该值是与父查询相关的,这就是相关子查询。上述语句的执行过程是:  (1)从外层查询中取出“课程注册”表的一个元组,将其学号(如取出学号140101001001)的值传送给子查询,即:  SELECT AVG(成绩)FROM 课程注册 AS yWHERE y.学号=140101001001    (2)执行子查询,得到近似结果78((87 74 71 69 90)÷5≈78),用该值代替子查询,得到父查询,即:  SELECT 学号,课程号FROM 课程注册 AS xWHERE 成绩 >=78    (3)执行父查询,得到  (140101001001, 0001) /*0001号课程成绩87分*/(140101001001, 0005) /*0004号课程成绩90分*/    接着,父查询取出下一个元组,重复上述(1)~(3)步,直到外层所有元组处理完毕,结果如图5-38所示。
图5-38  查询每个学生超过他所修课程平均成绩的课程号5.4.3  带有ANY或ALL谓词的子查询  子查询返回单值时可以使用比较运算符,但返回多值时则使用ANY或ALL谓词,还必须同时使用比较运算符,其语义如表5-24所示。表5-24  ANY或ALL谓词与比较运算符连用的语义表运  算  符语    义运  算  符语    义 >ANY大于子查询结果中的某个值 >ALL大于子查询结果中的所有值 


=ANY大于或等于子查询结果中的某个值 >=ALL大于或等于子查询结果中的所有值 <=ANY小于或等于子查询结果中的某个值 <=ALL小于或等于子查询结果中的所有值 =ANY等于子查询结果中的某个值 =ALL等于子查询结果中的所有值 !=ANY或 <> ANY不等于子查询结果中的某个值 !=ALL 或 <>ALL不等于子查询结果中的所有值    带有ANY或ALL谓词的子查询,其处理过程是:父查询通过ANY或ALL谓词将父查询中的一个表达式与子查询返回结果集中的某个值进行比较,如果表达式的值与子查询结果相比为真,那么,父查询中的条件表达式返回真(TRUE),否则返回假(FALSE)。  ANY或ALL谓词与聚集函数、IN谓词的等价转换关系如表5-25所示。表5-25  ANY或ALL谓词与聚集函数、IN谓词的等价关系

=<>或!=<或<=>或>=ANYIN—<或<=MAX>或>=MINALL—NOT IN<或<=MIN>或>=MAX    【例5.38】 使用“学生”表和“系部”表,查询其他系中比“计算机系”某一学生年龄小的学生信息。  代码如下:  USE studentGOSELECT 学号,姓名,性别,出生日期,系部代码FROM 学生WHERE 系部代码<>(SELECT 系部代码
FROM 系部
WHERE 系部名称= 计算机系
)AND 出生日期 >ANY
(SELECT 出生日期
FROM 学生
WHERE 系部代码=
(SELECT 系部代码
FROM 系部
WHERE 系部名称=计算机系)
)ORDER BY 出生日期GO    在查询分析器中输入并执行上述代码,结果如图5-39所示。    注意:在例5.38中,做“>ANY”运算的并不是学生年龄,而是学生的出生日期(年龄越小,表示出生日期的数值越大),因此,用“>ANY”运算符。也可用聚集函数YEAR()、GETDATE()先将出生日期计算转换为年龄(若采用年龄参与比较运算,则“>ANY”应改写为“

/*用系统当前日期中的年份减去学生出生日期中的年份,得到学生年龄*/    此外,本例还用到比较运算符“=”的子查询,通过“系部名称”查找对应的“系部代码”。AND前面的表达式是为了去除计算机系系内的学生信息。最后,要求结果按出生日期升序排列。
图5-39  查询其他系中比“计算机系”某一学生年龄小的学生信息  将例5.38改为查询其他系中比“计算机系”所有学生年龄都小的学生信息。只需把“>ANY”修改为“>ALL”即可,请读者自己实现代码并验证结果。  例5.38使用MAX()函数来实现:先用子查询找出计算机系中学生的最大年龄(年龄计算方法如前所述),接着在父查询中查找所有非计算机系且年龄小于该“最大年龄”的学生信息。  代码如下:  USE studentGOSELECT 学号,姓名,性别,出生日期,系部代码FROM 学生WHERE 系部代码<>(SELECT 系部代码 FROM 系部 WHERE 系部名称= 计算机系 )AND YEAR(GETDATE())-YEAR(出生日期) <   (SELECT MAX(YEAR(GETDATE())-YEAR(出生日期)) AS 年龄   From 学生   WHERE 系部代码 =(SELECT 系部代码   FROM 系部   WHERE 系部名称=计算机系)    )GO  5.4.4  带有EXISTS谓词的子查询  EXISTS是存在量词,使用EXISTS谓词的子查询不返回任何数据,此时,若子查询结果非空(即至少存在一条记录),则父查询的WHERE子句返回真(TRUE),否则返回假(FALSE)。  由EXISTS引出的子查询,其目标列通常都用“*”,原因在于该查询只返回逻辑值,给出列名毫无意义。正是因为EXISTS的这个用途,其查询效率不一定比不相关查询低,有时是一种高效的查询方法。  前面所讲的子查询,其查询条件不依赖于父查询,并且每个子查询都只执行一次,我们称之为不相关子查询。与此相对的概念是相关子查询,即查询条件依赖于父查询中的某个值,鉴于这种相关性(relativity),必须反复求值,供父查询使用。其处理过程是:取出父查询表中的第一条记录,根据它与子查询相关的属性值处理子查询,若子查询的WHERE子句返回真值,则把该条记录放入结果表中;然后再取父表的第二条记录;重复以上过程,直至父查询表全部处理完毕为止。  与EXISTS运算符相对的是NOT EXISTS,使用NOT EXISTS后,若子查询结果为空,则父查询的WHERE子句返回真(TRUE),否则返回假(FALSE)。  【例5.39】 用EXISTS谓词改写例5.36,即查询与“王钢”同在一个系的教师基本信息。  代码如下:  USE studentGOSELECT 教师编号,姓名,性别,学历,职务,职称FROM 教师 AS T1WHERE EXISTS (SELECT * FROM 教师 AS T2 WHERE T2.系部代码=T1.系部代码 AND T2.姓名=王钢 )GO    在查询分析器中输入并执行上述代码,结果与例5.36一致,如图5-40所示。从本例中可以看出所有带IN谓词、比较运算符、ANY或ALL谓词的子查询都能使用带EXISTS运算符的子查询等价替换。
图5-40  用EXISTS谓词改写例5.36  【例5.40】 使用“学生”表和“课程注册”表,查询所有选修“计算机导论”课学生的学号和姓名。  代码如下:  USE studentGOSELECT 学号,姓名FROM 学生WHERE EXISTS (SELECT * FROM 课程注册 WHERE 学号=学生.学号 AND 课程号= (SELECT 课程号  FROM 课程 WHERE 课程名=计算机导论 ) )GO  在查询分析器中输入并执行上述代码,结果如图5-41所示。
图5-41  用EXISTS谓词查询所有选修了“计算机导论”课的学生学号和姓名  【例5.41】 查询选修了全部课程的学生学号和姓名。  由于SQL语言中没有描述“全部”量词(For all),我们将该查询转译为“查询这样的学生:没有一门课程是他不选修的”。  代码如下:  USE studentGOSELECT 学号,姓名FROM 学生WHERE NOT EXISTS (SELECT * FROM 课程 WHERE NOT EXISTS (SELECT * FROM 课程注册 WHERE 学号=学生.学号 AND 课程号=课程.课程号 ) )GO    在查询分析器中输入并执行上述代码,结果如图5-42所示。
图5-42  用NOT EXISTS实现全称量词的查询  5.3节、5.4节涉及的运算符基本上是二元运算符,即用这些运算符来“组合”两个或两个以上的关系(即表)。学习这两节时,要注意公共属性集合的问题:它是第一个关系与第二个关系(与第三个关系,……,与第n个关系)相联系的中间环节,尽管这些公共属性可能在各个关系上具有不同的名称,但是它们必须具有相同的域和含义,只要掌握了它们的“内涵”,并结合5.2节简单查询的知识,就能写出结构规范、运行高效的SQL多表查询语句。5.5  数据的添加、修改和删除  SQL Server数据库的新表建好后,表中并不包含任何记录,要想实现数据的存储,必须向表中添加数据。同样要实现表的良好管理,则需要经常修改表中的数据。本节主要介绍数据的添加、修改和删除。  在数据的基本操作中,常用到T-SQL语句,首先应掌握如表5-26所示的SQL语句的语法规则。表5-26  SQL语句的语法规则规    则含    义大写T-SQL关键字斜体T-SQL语法中用户提供的参数|(竖线)分隔括号或大括号内的语法项目。只能选择一个项目[ ](中括号)可选语法项目,不必输入中括号{ }(大括号)必选语法项目,不要输入大括号[,…n]表示前面的项可重复n次。每一项由英文逗号分隔[…n]表示前面的项可重复n次。每一项由空格分隔加粗数据库名、表名、列名、索引名、存储过程、实用工具、数据类型名以及必须按所显示的原样输入的文本<标签>::=语法块的名称。此规则用于对可在语句中多个位置使用的过长语法或语法单元部分进行分组和标记。适合使用语法块的每个位置由括在尖括号内的标签表示:<标签>5.5.1  数据的添加  向表中添加数据可以使用INSERT语句。INSERT语句的语法格式如下:  INSERT [INTO] table_name [column_list] VALUES (data_values)  其中,各项参数的含义如下:* [INTO]是一个可选关键字,可以将它用在INSERT和目标表之间。* table_name是要添加数据的表名或table变量名称。* [column_list]是要添加数据的字段名称或字段列表,必须用中括号将column_list括起来,并且用逗号进行分隔。若没有指定字段列表,则指全部字段。* VALUES(data_values)用于引入添加记录的字段值。必须与column_list相对应。也就是说,每一个字段必须对应一个字段值,且必须用小括号将字段值列表括起来。如果VALUES列表中的值与表中列的顺序不相同,或者未包含表中所有列的值,那么必须使用column_list明确地指定存储每个传入值的列。  1.最简单的INSERT语句  【例5.42】 在结构如图5-43所示的“专业”表中添加一行记录:在计算机系部中添加一个电子商务专业。代码如下:  USE student GOINSERT 专业   (专业代码,专业名称,系部代码)VALUES     (103,电子商务,1)GO     在查询编辑器中输入上述代码,单击按钮,运行结果如图5-44和图5-45所示。                图5-44  简单添加数据语句                          图5-45  查看运行结果    注意:VALUES列表中的表达式的数量必须匹配列表中的列数,表达式的数据类型应与列的数据类型相兼容。  2.省略清单的INSERT语句  【例5.43】 在结构如图5-46所示的“班级”表中添加“15级电子商务001班”。  代码如下:  USE studentGOINSERT 班级VALUES (150103001,15级电子商务001班,103,1,NULL)GO    在查询编辑器中输入上述代码并执行,即可在“班级”表中增加如图5-47所示的值为“150103001,15级电子商务001班, 103, 1, NULL”的记录。    注意:此种方法省略了字段清单,用户必须按照这些列在表中定义的顺序提供每一个列的值,建议在输入数据时最好使用列清单。           图5-46  “班级”表结构                    图5-47  执行添加语句后的结果   3.省略VALUES清单的INSERT语句  在T-SQL语言中,有一种简单的插入多行的方法。这种方法是使用SELECT语句查询出的结果代替VALUES子句。这种方法的语法结构如下:  INSERT [INTO] table_name (column_name[,…n])SELECT column_name[,…n]  FROM  table_name WHERE search_conditions  其中,各项参数的含义如下:  (1)search_conditions——查询条件。  (2)INSERT表和SELECT表的结果集的列数、列序、数据类型必须一致。  【例5.44】 创建“课程”表的一个副本“课程1”表,将“课程”表的全部数据添加到“课程1”表中。  代码如下:  USE studentGOCREATE table 课程1(课程号 char(4) NOT NULL,课程名 char(20)  NOT NULL,学分 smallint NULL)GOINSERT INTO 课程1(课程号,课程名,学分) SELECT 课程号,课程名,学分  FROM 课程GO    将上述代码在查询编辑器中运行,用户可以看到在“课程1”中增加了7行数据,如图5-48所示。
图5-48  增加多行数据语句执行结果  4.向学生选课系统各表中添加数据  根据需要,向学生选课系统的各表中添加数据,在查询编辑器中分别执行下列代码。  (1)向“系部”表中添加如图5-49所示的4条记录。代码如下:  USE student GOINSERT 系部   (系部代码,系部名称,系主任)VALUES     (1,计算机系,徐才智)                      GO …                    (a)“系部”表结构                    (b)“系部”表中增加4条记录后的执行结果图5-49  表结构及增加4条记录后的执行结果  (2)向“专业”表添加如图5-50所示的8条记录。代码如下:  USE student GOINSERT 专业   (专业代码,专业名称,系部代码)VALUES     (101,软件工程,1) GO …                      (a)“专业”表结构                 (b)“专业”表中增加8条记录后的执行结果图5-50  表结构及增加8条记录后的执行结果  (3)向“班级”表添加如图5-51所示的5条记录。代码如下:  USE student GOINSERT 班级(班级代码,班级名称,专业代码,系部代码,备注)VALUES (140101001,14级软件工程001班,101,1,NULL)GO…          (a)“班级”表结构                       (b)“班级”表中增加5条记录后的执行结果图5-51  表结构及增加5条记录后的执行结果  (4)向“学生”表添加如图5-52所示的10条数据记录。代码如下:  USE studentGOINSERT 学生VALUES (140101001001,张斌,男,1995-5-4,2014-9-1,140101001, 1,101)GO…          (a)“学生”表结构                       (b)“学生”表中增加10条记录后的执行结果图5-52  表结构及增加10条记录后的执行结果  (5)向“课程”表添加如图5-53所示的7条数据记录。代码如下:  USE studentGOINSERT 课程(课程号,课程名,学分)VALUES (001,大学英语,6)GO…                  (a)“课程”表结构                    (b)“课程”表中增加7条记录后的执行结果图5-53  表结构及增加7条记录后的执行结果  (6)向“教学计划”表添加如图5-54所示的42条数据记录。代码如下:USE studentGOINSERT 教学计划(课程号,专业代码,专业学级,课程类型,开课学期,学分)VALUES (001,101,2014,公共必修,1,6)GO…      (a)“教学计划”表结构                 (b)“教学计划”表中增加42条记录后的部分执行结果图5-54  表结构及增加42条记录后的执行结果  (7)向“教师”表添加如图5-55所示的5条数据记录。代码如下:  USE studentGOINSERT 教师(教师编号,姓名,性别,出生日期,学历,职务,职称,系部代码,专业,备注)VALUES (100000000001,张学杰,男,1969-1-1,硕士,主任,教授,1,   计算机,NULL)GO…         (a)“教师”表结构                       (b)“教师”表中增加5条记录后的执行结果图5-55  表结构及增加5条记录后的执行结果  (8)向“教师任课”表添加如图5-56所示的42条数据记录。代码如下:  USE studentGOINSERT 教师任课(教师编号,课程号,专业学级,专业代码,学年,学期,学生数)VALUES(100000000001,002,2014,101,2014,2,0)GO…       (a)“教师任课”表结构               (b)“教师任课”表中增加42条记录后的部分执行结果图5-56  表结构及增加42条记录后的执行结果  (9)利用“学生”表、“教师任课”表、“教学计划”表向“课程注册”表添加如图5-57所示的36条数据记录(注意,若学生完成该门课程学习,还需手动修改成绩、学分列的值或使用触发器来自动修改学分列的值,具体内容参见10.2节)。代码如下:  USE studentGOINSERT 课程注册(学号,课程号,教师编号,专业代码,专业学级,选课类型,学期,学年,成绩,学分)SELECT DISTINCT 学生.学号,教师任课.课程号,教师任课.教师编号,学生.专业代码,教师任课.专业学级,教学计划.课程类型,教师任课.学期,教师任课.学年,0,0FROM 学生,教师任课,教学计划WHERE 教师任课.专业学级=YEAR(学生.入学时间) AND 教师任课.专业代码=学生.专业代码 AND 教师任课.专业代码=教学计划.专业代码 AND 教师任课.课程号=教学计划.课程号 AND 教师任课.专业学级=教学计划.专业学级GO           (a)“课程注册”表结构                (b)“课程注册”表中增加36条记录后的部分执行结果图5-57  表结构及增加36条记录后的执行结果5.5.2  数据的修改  在数据输入过程中,可能会出现输入错误,或是因为时间变化而需要更新数据,这都需要修改数据。修改表中的数据可以使用SQL Server Management Studio中的图形界面进行修改,即右击某数据表图标,在弹出的快捷菜单中选择“编辑前200行”命令,在打开的“表数据窗口”中进行修改。这里主要介绍T-SQL的UPDATE语句实现修改的方法,UPDATE的语法格式如下:  UPDATE table_nameSET{column_name={expression|DEFAULT|NULL}}[,…n][FROM{
}[,…n]] [WHERE

]
::=Table_name[[AS]table_alias][ WITH(
[,…n])]  其中:* table_name是需要更新的表的名称。* SET是指定要更新的列或变量名称的列表。* column_name是含有要更改数据的列的名称。* {expression| DEFAULT | NULL)是列值表达式。*
是修改数据来源表。    注意:当没有WHERE子句指定修改条件时,则表中所有记录的指定列都被修改。若修改的数据来自另一个表时,则需要FROM子句语句指定一个表。    【例5.45】 将“教学计划”表中专业代码为0101的“开课学期”的值改为第二学期。  代码如下:  USE studentGOUPDATE 教学计划SET 开课学期=2WHERE 专业代码=101GO    在查询编辑器中输入并执行上述代码后,用户可以通过SQL Server Management Studio查看修改的结果,这里如果没有使用WHERE子句,则对表中所有记录的“开课学期”进行修改。  【例5.46】 更新“课程注册”表中学生成绩及格的课程的“学分”值。  代码如下:  USE studentGOUPDATE 课程注册SET 学分=(SELECT 学分 FROM 课程 WHERE 课程号=课程注册.课程号)WHERE 成绩>=60GO    修改“课程注册”表中成绩及格记录的“学分”值需要利用“课程”表中的“学分”字段值,所以需要使用FROM子句。在查询编辑器中输入并执行上述代码后,可以查看结果以检验执行情况。这里只对表中一列数据进行修改,如要修改多个列,列与列之间要用英文逗号隔开。  【例5.47】 利用“课程注册”表更新“教师任课”表中“学生数”的值。  代码如下:  USE studentGOUPDATE 教师任课SET 学生数=(SELECT COUNT(*) FROM 课程注册 WHERE 专业代码=教师任课.专业代码 AND 教师任课.专业学级=课程注册.专业学级 AND 教师任课.教师编号=课程注册.教师编号 AND 教师任课.课程号=课程注册.课程号 AND 教师任课.专业学级=课程注册.专业学级)GO    修改“教师任课”表中“学生数”字段时,需要通过“课程注册”表统计出选课的学生人数,所以查询语句中使用了集合函数COUNT。在查询编辑器中输入并执行上述代码后,可以查看结果以检验执行情况,如图5-58所示。

图5-58  更新学生数后的“教师任课”表部分记录5.5.3  数据的删除  随着系统的运行,表中可能产生一些无用的数据,这些数据不仅占用空间,而且还影响查询的速度,所以应该及时删除。删除数据可以使用DELETE语句和TRUNCATE TABLE语句。  1.使用DELETE语句删除数据  从表中删除数据,最常用的是DELETE语句。DELETE语句的语法格式如下:  DELETE table_name[FROM{
}[,…n]][WHERE {

}]
::=table_name[[AS]table_alias][, …n]]  其中:* table_name是要从其中删除数据的表的名称。* FROM
为指定附加的FROM子句。* WHERE指定用于限制删除行数的条件。如果没有提供WHERE子句,则DELETE删除表中的所有行。*

指定删除行的限定条件。对搜索条件中可以包含的谓词数量没有限制。* table_name[[AS] table_alias]是为删除操作提供标准的表名。  【例5.48】 删除“课程注册”表中的所有记录。  代码如下:  USE studentGODELETE 课程注册GO    此例中没有使用WHERE语句指定删除的条件,将删除课程注册表中的所有记录,只剩下表格的定义。  【例5.49】 删除“教师”表中没有姓名的记录。  代码如下:  USE studentGODELETE 教师WHERE 姓名 IS NULLGO    【例5.50】 删除“课程注册”表中姓名为“张斌”的课程号为0001的选课信息。  代码如下:  USE studentGODELETE 课程注册WHERE 课程注册.课程号=001 AND 学号=(SELECT 学号 FROM 学生 WHERE 姓名 LIKE    张斌)GO    删除“课程注册”表中的数据时,用到了“学生”表里的“姓名”字段值“张斌”,所以使用了FROM子句。在查询编辑器中输入并执行上述代码。用户可以使用SQL Server Management Studio检查代码执行结果。用户在操作数据库时,要小心使用DELETE语句,因为数据会从数据库中永久地被删除。  2.使用TRUNCATE TABLE清空表格  使用TRUNCATE TABLE语句删除所有记录的语法格式为:  TRUNCATE TABLE  table_name    其中:* TRUNCATE TABLE为关键字。* table_name为要删除所有记录的表名。  使用TRUNCATE TABLE语句清空表格要比DELETE语句快,TRUNCATE TABLE是不记录日志的操作,它将释放表的数据和索引所占据的所有空间以及所有为全部索引分配的页,删除的数据是不可恢复的。而DELETE语句则不同,它在删除每一行记录时都要把删除操作记录在日志中。删除操作记录在日志中,可以通过事务回滚来恢复删除的数据。用TRUNCATE TABLE和DELETE语句都可以删除所有的记录,但是表结构还存在,而DROP TABLE是删除表结构和所有记录,并释放表所占用的空间。  【例5.51】 用TRUNCATE TABLE语句清空“课程注册”表。  代码如下:  USE studentGOTRUNCATE TABLE 课程注册GO5.6  应 用 举 例  1.添加学生课程信息  (1)自动添加学生必修课。假设现在是2014学年的第一个学期,将学生该学期的必修课程(即公共必修和专业必修)自动添加到“课程注册”表中,正常选课时选课类型设置为空。代码如下:  USE studentGOINSERT INTO 课程注册(学号,课程号,教师编号,专业代码,专业学级,选课类型,学期,学年,成绩,学分)SELECT DISTINCT A.学号,B.课程号,C.教师编号,A.专业代码,B.专业学级,  ,C.学期,C.学年,0,0FROM 学生 AS A JOIN 教学计划 AS B ON A.专业代码=B.专业代码 AND B.专业学级=YEAR(A.入学时间) JOIN 教师任课 AS C ON B.专业代码=C.专业代码 AND B.专业学级=C.专业学级 AND B.课程号=C.课程号WHERE C.学年=2014 AND C.学期=1 AND (B.课程类型=公共必修 OR B.课程类型=专业必修)    (2)将学生未取得学分的必修课自动添加到“课程注册”表中,且选课类型设置为    “重修”。代码如下:  USE studentGOINSERT INTO 课程注册(学号,课程号,教师编号,专业代码,专业学级,选课类型,学期,学年,成绩,学分)SELECT DISTINCT A.学号,C.课程号,C.教师编号,B.专业代码,B.专业学级,重修,C.学期,   C.学年,0,0FROM 课程注册 AS AJOIN 教学计划 AS B ON A.专业代码=B.专业代码 AND A.课程号=B.课程号 AND A.专业学级=B.专业学级JOIN 教师任课 AS C ON B.专业代码=C.专业代码 AND B.课程号=C.课程号 AND B.专业学级=C.专业学级WHERE A.成绩<60 AND (B.课程类型=公共必修 OR B.课程类型=专业必修)    2.查询学生课程成绩  (1)查询所有学生各门课程成绩。代码如下:USE studentGOSELECT A.学号,A.姓名,C.课程名,B.成绩FROM 学生 AS A
JOIN 课程注册 AS B ON A.学号=B.学号
JOIN 课程 AS C ON B.课程号=C.课程号ORDER BY A.学号GO    (2)查询某个学生的各门必修课成绩,假设该学生的学号为140201001001。代码如下:  USE studentGOSELECT DISTINCT A.学号,A.姓名,C.课程名,B.成绩FROM 学生 AS A
JOIN 课程注册 AS B ON A.学号=B.学号
JOIN 课程 AS C ON B.课程号=C.课程号
JOIN 教学计划 AS D ON C.课程号=D.课程号WHERE A.学号=140201001001 AND (D.课程类型=公共必修 OR D.课程类型=专业必修)GO    (3)查询学生所有必修课的平均分。代码如下:  USE studentGOSELECT A.学号,AVG(B.成绩)AS 平均分FROM 学生 AS A
JOIN 课程注册 AS B ON A.学号=B.学号
JOIN 课程 AS C ON B.课程号=C.课程号
JOIN 教学计划 AS D ON C.课程号=D.课程号WHERE D.课程类型=专业必修 OR D.课程类型=公共必修GROUP BY A.学号GO    (4)查询学生的已获得学分的成绩。代码如下:  USE studentGOSELECT A.学号,A.姓名,C.课程名,B.成绩FROM 学生 AS A
JOIN 课程注册 AS B ON A.学号=B.学号
JOIN 课程 AS C ON B.课程号=C.课程号WHERE B.成绩>=60ORDER BY A.学号GO    (5)查询学生的总学分。代码如下:  USE studentGOSELECT A.学号,SUM(B.学分)AS 总学分FROM 学生 AS A
JOIN 课程注册 AS B ON A.学号=B.学号
JOIN 课程 AS C ON B.课程号=C.课程号GROUP BY A.学号GO    3.查询教师授课信息  (1)查询所有教师授课的课程号和课程名。代码如下:  USE studentGOSELECT DISTINCT A.教师编号,A.姓名,C.课程名,C.课程号FROM 教师 AS A
JOIN 教师任课 AS B ON A.教师编号=B.教师编号
JOIN 课程 AS C ON B.课程号=C.课程号ORDER BY A.教师编号GO    (2)查询某学年某学期所有教师的具体授课信息。假设需要查询2014学年第一学期教师的授课信息,应注意在同一个学期、同一个教师可能会给不同专业的学生授课,所以要按学生的专业代码和专业名称分别列出。代码如下:  USE studentGOSELECT A.教师编号,A.姓名,C.课程号,C.课程名,B.专业学级,D.专业名称FROM 教师 AS A
JOIN 教师任课 AS B ON A.教师编号=B.教师编号
JOIN 课程 AS C ON B.课程号=C.课程号
JOIN 专业 AS D ON B.专业代码=D.专业代码WHERE B.学年=2014 AND B.学期=1ORDER BY A.教师编号,B.专业学级GO    (3)查询某个教师的具体授课信息和选课的学生人数。假设该教师的姓名为“周红梅”。代码如下:  USE studentGOSELECT A.教师编号,A.姓名,C.课程号,C.课程名,B.专业学级,D.专业名称,B.学生数FROM 教师 AS A
JOIN 教师任课 AS B ON A.教师编号=B.教师编号
JOIN 课程 AS C ON B.课程号=C.课程号
JOIN 专业 AS D ON B.专业代码=D.专业代码WHERE A.姓名=周红梅ORDER BY B.专业学级GO练  习  题  1.关系与普通表格、文件有何区别?  2.两个关系做并、交、差、笛卡儿积、选择运算,最后得到的关系的基数是什么?  3.假设一个关系实例的度为7,基数为15,那么该关系有多少属性?关系中目前有多少不同的行?  4.如何用连接运算模拟一个选择运算?  5.等值连接和自然连接的区别和联系是什么?  6.设有三个关系:       学生关系Student(SNO,Sname,Age,Sex,Sdept)       课程关系Course(CNO,Cname,Cdept,Tname)       学习关系SC(SNO,CNO,Grade)  其中Tname表示选修某门课程的学生姓名。试用关系代数表达式表示下列查询语句:  (1)查询“王红梅”老师所讲授课程的课程号与课程名称;  (2)查询年龄大于23岁的男学生的学号与姓名;  (3)查询学号为S074的学生所选修课程的课程名称和任课教师姓名;  (4)查询至少选修“李艳”老师所讲授课程中一门课的女学生姓名;  (5)查询“王刚”同学没有选修的课程(号);  (6)查询至少选修两门课程的学生学号;  (7)查询全部学生都选修的课程的课程号和课程名称;  (8)查询选修课程包含“刘大林”老师所讲授课程的学生学号。  7.某汽车品牌生产数据库中包括供应商、零件、工程项目和供应情况四个关系模式:      供应商(供应商代码,供应商名,状态,所在城市)      零件(零件代号,零件名,颜色,重量)      工程项目(项目代码,项目名,项目所在地)      供应情况(供应商代码,零件代号,项目代码,供应数量)  其中,工程项目表中的供应数量指某供应商供应某种汽配零件给某汽车生产工程项目的数量。现给出下列数据:“供应商”表供应商代码供 应 商 名状    态所 在 城 市S1   三菱20东京S2   天顺10济南S3   旺特30青岛S4   滕势20深圳S5   金辉高科30佛山“零件”表零 件 代 号零  件  名颜    色重    量P1   发动机红色102P2   气门导管黄色  3P3   锂电池银色100P4   水泵蓝色 30P5   电器仪表白色  8P6   压缩机绿色 45“工程项目”表项 目 代 码项  目  名项目所在地J1   新能源轿车A1北京J2   新能源轿车A52长春J3   油电混合越野车S3天津J4   油电混合越野车S5天津J5   1.6L轿车TIDA昆明J6   1.4T轿车K10上海J7   新能源大巴南京“供应情况”表供应商代码零 件 代 号项 目 代 码数    量S1P1J1210S1P1J3105S1P1J4700S1P2J2105S2P3J1435S2P3J2200S2P3J4501S2P3J5400S2P5J1420S2P5J2100S3P1J1201S3P3J1202S4P5J1104S4P6J3303S4P6J4200S5P2J4100S5P3J1201S5P6J2208S5P6J4500    用SQL语句建立以上四张表,并完成如下查询:  (1)求供应工程J2零件的供应商代码;  (2)求供应工程J2零件P5的供应商代码;  (3)求供应工程J1零件为红色的供应商代码;  (4)求没有使用济南供应商生产的红色零件的项目代号;  (5)求至少用了供应商S1所供应的全部零件的项目代号;  (6)求工程项目J3使用的各种零件的名称及其数量;  (7)求深圳厂商供应的所有零件代号;  (8)求使用佛山产的零件的工程名称;  (9)求没有使用东京产的零件的工程代码;  (10)把全部红色零件的颜色改成棕色;  (11)把S5供给J4的零件全部改为由S3供应;  (12)从“供应商”表中删除S2的记录,并从“供应情况”表中删除相应记录;  (13)把(S2,J6,P4,700)插入“供应情况”表。









数据库原理与技术(SQL Server 2012) pdf下载声明

本pdf资料下载仅供个人学习和研究使用,不能用于商业用途,请在下载后24小时内删除。如果喜欢,请购买正版

pdf下载地址

版权归出版社和作者所有,下载链接已删除。如果喜欢,请购买正版!

链接地址:数据库原理与技术(SQL Server 2012)