4.1 SQL概述
4.1.1 SQL的产生和发展
1.产生
1974年,SQL语言的雏形最早由美国IBM公司的Raymond F. Boyce和Donald D. Chamberlin提出
1975-1979年,在System R上首次实现,由IBM的San Jose研究室研制,称为SEQUEL
2.发展
1986年推出了SQL-86标准,正式命名为"SQL: Structured Query Language"
1989年ANSI / ISO推出了SQL-89标准,它是数据库语言SQL的标准集合
1992年进一步推出了SQL-92标准,也称为SQL2,是SQL-89的超集,增加了许多新特性
1999年推出了SQL-99标准,也称为SQL3,对面向对象的一些特征予以支持
4.1.2 SQL的特点
(1)综合统一
(2)高度非过程化
(3)面向集合的操作方式
(4)语言简捷,易学易用
(5)以同一种语法结构提供两种使用方式:独立和嵌入。
4.1.3 SQL的基本概念
SQL与DBMS的关系
SQL的方言问题
SQL语言的功能组件
DML数据操纵语言
DDL数据定义语言
DCL数据控制语言
4.1.4 SQL基本数据类型
一、数值类型
(1)准确型:指在计算机中能够精确存储的数据
(2)近似型:指近似的数值数据类型
二、文本类型
(1)普通字符编码(每个英文字符占一个字节存储空间,每个汉字占两个字节存储空间)
(2)Unicode字符编码(每个英文字符和汉字都占两个字节存储空间)
三、日期时间类型
四、二进制类型
4.2 学生选课数据库
此部分只简单罗列库中四张表的结构:学生表、教师表、课程表、选课表
学生表:
教师表:
课表:
选课表:
4.3 数据定义
4.3.1 模式的定义与删除
1.模式的概念
数据库模式是一种逻辑分组对象,数据库模式是数据库对象的集合,这个集合包含了各种对象如:表、视图、存储过程、索引等。
可以想象一个模式作为对象的容器。
数据库模式可以作为一个命名空间,能防止来自不同模式的对象名称冲突。
2.模式创建的语法
创建模式的语法:
Create schema <模式名>
authorization <用户名>
定义模式实际上是定义一个命名空间,在这个空间中可以进一步定义该模式包含的数据库对象,例如基本表,视图,索引等
用sa账户登录,创建一个名为StudentDB的数据库,然后创建名为Sch1的模式。
准备工作:
sqlCreate database StudentDB Use StudentDB Go CREATE LOGIN Zhou1 WITH PASSWORD = 'MyPassword123' Go CREATE USER Zhou1 FOR LOGIN Zhou1
模式创建与删除
sqlCreate schema Sch1 authorization Zhou1 Drop Schema Sch1
4.3.2 表操作
一、创建表
创建表的SQL语法的简化版是:
sql
Create Table 表名
(
字段1 数据类型1(长度),
字段2 数据类型2(长度),
字段3 数据类型3(长度)
)
注意:不是所有类型都需要长度,逗号用来分隔开多个字段。
创建一张名为Users的表,包含用户名vUserName和密码vPassword两个字段。用户名最大允许长度18个字符,密码最大允许长度20个字符。
sqlCreate Table Users ( vUserName varchar(18) Not NULL, vPassword varchar(20) Not NULL )
创建学生表
sqlCREATE TABLE Student ( Sno char(10) NOT NULL Constraint PK_Stu_No Primary Key , Sname char(20) NOT NULL, Ssex char(2) NOT NULL Constraint CK_Stu_Sex Check(Ssex in ('男','女')), Smajor char(20) NOT NULL, Sdept char(20) NOT NULL, Sage tinyint Constraint CK_Stu_Age Check(Sage between 1 and 80), Tel char(15) NOT NULL, EMAIL varchar(30) NOT NULL )
二、修改表
修改学生表结构
删除Sage年龄字段,增加dBirth字段。
另外将Smajor字段从目前的char(20)修改为varchar(20)。
sqlAlter Table Student Drop Constraint CK_Stu_Age --删除Sage字段上的约束 Alter Table Student Drop Column Sage Alter Table Student Add dBirth datetime Alter Table Student Alter Column Smajor varchar(20)
三、删除表
删除表的语法为:
sql
Drop Table 表名
要删除先前的学生表,执行下面语句即可:
sql
Drop Table Student
4.4 数据查询
4.4.1 查询语句的基本结构
sql
SELECT select_list [ INTO new_table ]
[ FROM table_source ]
[ WHERE search_condition ]
[ GROUP BY group_by_expression ]
[ HAVING search_condition ]
[ ORDER BY order_expression [ ASC | DESC ] ]
说明:ASC代表升序,DESC代表降序。
4.4.2 单表查询
检索Student表的所有行和列。
sqlSelect * from Student
说明:"Select * from 表名"的语法形式,可以让用户快速了解一张表的数据样式。
投影运算:从Student表检索学号、姓名、性别、年龄、专业这五列信息。
sqlSelect Sno,Sname,Ssex,Sage,Smajor from Student
说明:只显示部分的列,是在Select之后给出要显示的字段的列表,并用逗号分隔开。
友好列标题:从Student表检索学号、姓名、性别、年龄、专业这五列信息,要求使用友好列标题。
sqlSelect Sno as 学号,Sname as 姓名,Ssex as 性别,Sage as 年龄 ,Smajor as 专业 from Student
说明:在原始字段名之后跟上as,然后就可以给一个友好列标题了。
top关键字:从Student表检索前三行数据
sqlSelect Top 3 * from Student
说明:使用Top n 语法来说明只显示前n条数据。
选择运算 :从Student表检索年龄为20岁的学生信息。
sqlSelect * from Student where Sage=20
说明:用where条件来实现行上的选择,此处需要使用比较运算符。
And连接多个条件:从Student表检索年龄大于21岁的女学生信息。
sqlSelect * from Student where Ssex='女' and Sage>21
Or连接多个条件:从Student表检索专业是"计算机应用"或"石油工程"的学生。
sqlSelect * from Student where Smajor='计算机应用' or Smajor='石油工程'
说明:当要满足的条件有多个的时候,需要用And或者Or来连接。And表示同时满足,Or表示满足一个条件即可。
Between...And:检索学号在J2016001到J2016004之间的学生信息,显示学号、姓名、性别、年龄。
sqlSelect Sno,Sname,Ssex,Sage from Student where Sno between 'J2016001' and 'J2016004'
说明:要比较的值是介于某个范围,并且包含边界值,则可以使用between...and语法。值可以是字符串,也可以是数字。
检索年龄不在19到21岁之间的学生信息,显示学号、姓名、性别、年龄。
sqlSelect Sno,Sname,Ssex,Sage from Student where Sage not between 19 and 21
说明:可以在between...and语法之前使用not进行取反。
In关键字:从Teacher表中检索职称为教授或副教授的教师信息。
sqlSelect * from Teacher where Tprot in ('教授','副教授')
说明:要检索的信息是一系列取值列表,可以使用in。
DISTINCT关键字:显示Teacher表中有哪些职称,要求显示结果不能有重复数据。
sqlSelect DISTINCT Tprot from Teacher
说明:可以在字段名之前使用DISTINCT关键字,表示检索时显示不重复的信息。
Like模糊查询:查询Student表中姓刘的学生信息。
sqlSelect * from Student where Sname like '刘%'
说明:可以使用like关键字进行模糊查询。
查询Student表专业中含有"学"字的学生的姓名及专业。
sqlSelect Sname,Sdept from Student where Sdept like '%学%'
说明:只要在Sdept的任何位置,出现"学"字,就检索出来。
查询Student表中邮箱地址满足在@左侧有且仅有四个字符的学生信息,结果显示姓名、院系、邮箱地址三列。
sqlSelect Sname,Sdept,EMAIL from Student where EMAIL like '____@%'
说明:@符号之前是四个紧密相连的下划线符号"_",一个下划线代码与一个字符匹配。
IS NULL:检索Master数据库中spt_values表里low字段为空的数据行。
sqlselect * from spt_values where low IS NULL
说明:执行此语句,需要先转到Master数据库。
IS NOT NULL:检索Master数据库中spt_values表里high字段不为空的数据行。
sqlselect * from spt_values where high IS NOT NULL
说明:IS NOT NULL表示检索某列不为空的数据行。
Order by排序:显示Course表的所有行,要求按照课程名称的降序显示。
sqlSelect * from Course Order by Cname Desc
说明:使用Order by对显示的数据进行排序。
显示Course表的所有行,按照课程学分的降序排列,学分相同时再按照课程号的升序排列。
sqlSelect * from Course Order by Ccredit Desc,Cno Asc
说明:可以用逗号隔开多个排序的列或表达式,升序排列时Asc可以省略。
算术表达式:计算3乘以5的结果,及根号2的值。
sqlSelect 3*5,SQRT(2)
说明:Select语句之后,可以是算术表达式,或者是函数。
对Course表,显示课程号、课程名、学分,另外额外增加一列"学时",学时是等于学分乘以16。
sqlSelect Cno,Cname,Ccredit, Ccredit*16 as 学时 from Course
说明:从Course表中检索数据时,额外增加一个原来不存在的列,通过计算得到。
COUNT()函数:统计Teacher表中教授的数量。
sqlSelect COUNT(*) from Teacher where Tprot='教授'
说明:COUNT()函数返回匹配指定条件的行数。COUNT(*) 函数返回表中的记录数,COUNT(column_name)函数返回指定列的值的数目(NULL不计入)。
集合函数:显示Teacher表中教师的最大、最小、平均年龄。
sqlSelect MAX(Tage),MIN(Tage),AVG(Tage) from Teacher
说明:集合函数MAX、MIN、AVG可以用来计算某个字段的最大值、最小值、平均值
对Course表中的必修课的学分进行求和。
sqlSelect SUM(Ccredit) from Course where XKLB='必修'
说明:SUM函数用于求和。
Group By分组:对Course表,按照必修和选修进行分类,统计每种类别的课程数量。
sqlSelect XKLB as 类别,COUNT(Cname) as 数量 from Course Group by XKLB
说明:"Group By"从字面意义上理解就是根据"By"指定的规则对数据进行分组
对Student表,按照专业和性别进行分组,显示每个专业、每种性别的学生数量。按照学生数量的降序显示结果。
sqlSelect Smajor,Ssex,COUNT(sNo) from Student Group by Smajor,sSex order by COUNT(sNo) Desc
说明:在指定分组字段时,可以不止一个分组字段。
对Teacher表,显示职称及对应的人数,要求只有统计人数大于等于5人才显示。
sqlSelect Tprot ,COUNT(Tprot) from Teacher Group by Tprot Having COUNT(Tprot)>=5
4.4.3 多表连接查询
一、连接查询分类
多表连接查询实际上是通过各个表之间共同列的关联性来查询数据的,它是关系数据库查询最主要的特征。
连接查询可分为三大类,分别是内连接、外连接,交叉连接。
1.内连接
内连接是最典型、最常用的连接查询,它根据表中共同的列 来进行匹配,只有满足匹配的条件的数据才能被查询出来。通常,两个表存在主外键关系时会使用到内连接查询。
内联结常使用"="比较运算符来判断两列数据是否相等,通过使用Inner Join关键字进行表之间的关联。
对SC和Student表进行内连接,显示学生的学号、姓名、课程号、分数。
sql--方法一 Select Student.Sno,Student.Sname, SC.Cno,SC.Grade from SC Join Student On SC.Sno=Student.Sno --方法二 Select Student.Sno,Student.Sname, SC.Cno,SC.Grade from SC,Student where SC.Sno=Student.Sno
将SC和Student内连接起来,显示相应的信息,其实可以理解为,对SC表中的每一个学号,到Student表中根据学号查找到对应的姓名。
2.外连接
在内连接中,只有满足连接条件的元组才能作为结果输出。但有时我们也希望输出哪些不满足连接条件的元组信息,这时就需要使用外连接。外连接可分为:左连接、右连接、完全外连接。
(1)左连接 left join 或 left outer join
(2)右连接 right join 或 right outer join
(3)完全外连接 full join 或 full outer join
3.交叉连接
交叉连接就是表之间没有任何关联条件,查询将返回左表与右表逐个连接的所有行,就是左表的的每一行与右表的所有行一一组合,相当于两个表相乘。
没有 WHERE 子句的交叉连接将产生连接所涉及的表的笛卡尔积 。第一个表的行数乘以第二个表的行数等于笛卡尔积结果集的大小。
三张表连接:显示学生的学号,姓名,课程名,考试分数。
sql--方法一 Select Student.Sno,Student.Sname,Course.Cname ,SC.Grade from SC Join Student On SC.Sno=Student.Sno Join Course On SC.Cno=Course.Cno --方法二 Student.Sno,Student.Sname, Course.Cname ,SC.Grade from SC,Student,Course where SC.Sno=Student.Sno and SC.Cno=Course.Cno
本质就是对SC表,将其中的一些编号,翻译成对应的含义。将学号翻译为了学生的姓名,将课程号翻译为了课程名。三张表的连接,需要两个连接条件。
4.4.4 嵌套查询
1.使用IN的子查询
过IN(或NOT IN)引入的子查询结果是包含零个值或多个值的列表。
子查询返回结果之后,外部查询将利用这些结果。
2.用ANY、ALL修改的比较运算符
可以用ALL或ANY关键字修改引入子查询的比较运算符。SOME是与ANY等效的ISO标准。
以>比较运算符为例,>ALL表示大于每一个值。换句话说,它表示大于最大值。例如,>ALL(1,2,3)表示大于3。
ANY表示至少大于一个值,即大于最小值。因此>ANY(1,2,3)表示大于1。
3.使用EXISTS的子查询
使用EXISTS关键字引入子查询后,子查询的作用就相当于进行存在测试。
外部查询的WHERE子句测试子查询返回的行是否存在。
子查询实际上不产生任何数据,它只返回TRUE或FALSE值。
等于单个值:查询有某科目考试分数为48分的学生信息:
sqlSelect * from Student Where Sno = (Select sNo from SC where Grade=48)
In列表:查询在SC表中选修了课程的学生的信息。
sqlSelect * from Student Where Sno in (Select Distinct Sno from SC)
说明:子查询得到学生的学号,外部查询根据学号找到学生。
Not In:查询没有选修过任何课程的学生的信息。
sqlSelect * from Student Where Sno Not In (Select Distinct Sno from SC)
说明:Not In表示字段的值不在后面的子查询返回结果中。
ALL:在教师表中,检索比任何一个女教师年龄都大的男教师的信息。
sqlSelect * from Teacher Where Tsex ='男' and Tage > ALL(Select Tage from Teacher where Tsex='女')
分析:子查询得到每一位女教师的年龄,外层查询使用">ALL"的语法,即比集合中最大值还大。
exists:查询选修了B004课程的学生的基本信息。
sqlSelect * from Student where exists (Select * from SC where Sno=Student.Sno and Cno='B004')
查询没有选修X001课程的学生的基本信息。
sqlSelect * from Student where not exists (Select * from SC where Sno=Student.Sno and Cno='X001')
查询与王国在同一个专业学习的所有学生的基本信息。
sqlSelect Sno,Sname, Smajor from Student S1 where exists (Select * from Student S2 Where S1.Smajor = S2.Smajor and S2.Sname='王国')
4.4.5 集合查询
1.集合查询简介
SELECT语句查询的结果是元组的集合,所以多个SELECT语句的查询结果可进行集合操作,包括并 (Union)、 交 (Intersect) 、差 (Except)。
这三种运算能够进行的前提,是SELECT语句必须拥有相同数量的列 ,且类型兼容。
2.并运算
将学生的学号、姓名,与教师的教工号、姓名,在一个检索结果中显示出来。
sqlSelect Sno,Sname from Student Union select Tno ,Tname from Teacher
注意:并运算有UNION和UNION ALL两种用法
UNION:将多个查询结果合并起来时,系统自动去掉重复元组
UNION ALL:将多个查询结果合并起来时,保留重复元组
3.交运算
对专业名以计算机开头的学生,及年龄是21的学生,用交运算求二者的交集。
sqlSelect Sno,Sname,Sage ,Smajor from Student where Smajor like '计算机%' Intersect Select Sno,Sname,Sage ,Smajor from Student Where Sage=21
- 差运算
查询专业名以计算机开头的学生,但不包括年龄是21的学生。
sqlSelect Sno,Sname,Sage ,Smajor from Student where Smajor like '计算机%' Except Select Sno,Sname,Sage ,Smajor from Student Where Sage=21
4.5 数据更新
4.5.1 插入数据
插入数据分为插入单个元组、插入子查询结果及直接从查询结果创建新表。
(1)插入数据(插入单个元组),语法:
sql
INSERT [INTO] table_or_view [(column_list)] data_values
(2)插入数据(插入子查询结果) 在INSERT语句中使用SELECT子查询。
(3)插入数据(直接从查询结果创建表) SELECT INTO 语句用于创建一个新表
插入单行数据:在Course中插入一行数据,四项数据为('X004','计算机前沿',2,'选修')。
sqlInsert Into Course(Cno,Cname,Ccredit,XKLB) Values('X004','计算机前沿',2,'选修')
如果不是对表中的所有字段都给出值,或者是要更改列出现的顺序,则必须在表名后面出现字段名的列表。如果是要对表中的所有字段赋值,则可以省略字段名。
查询创建新表:将Teacher中职称为教授的信息,存入到一张目前还不存在的Experts表。
sqlSelect * Into Experts from Teacher Where Tprot='教授'
说明:语法是"Select 选择列表 Into 新表名 from 原始表"。
4.5.2 更新数据
更新数据也叫做修改数据。修改数据分为修改符合一定条件元组的值、修改所有元组的值及带子查询的修改。
(1)修改符合一定条件元组的值,语法:
sql
Update table_or_view set column=data_values WHERE search_condition
(2)修改数据(修改所有元组的值),不指定Where字句即可。
(3)带子查询的修改
修改特定行:将Course表中编号是B002的课程,学分修改为3分。
sqlUpdate Course set Ccredit=3 Where Cno='B002'
说明:通过Where字句限定行,通过"set 字段名=新值"进行数据修改。
带子查询的修改:对学生表,将现有的专业字段,用来存放该学生选修的第一门课程的编号。
sqlUpdate Student set Smajor=(Select top 1 Cno from SC Where SC.Sno=Student.Sno)
说明:要能成功执行,Smajor必须允许非空
4.5.2 删除数据
删除数据分为删除符合一定条件的元组、删除所有元组及带子查询的删除。
(1)删除符合一定条件的元组,语法:
sql
DELETE table_or_view FROM table_sources WHERE search_condition
(2)删除所有元组
sql
DELETE FROM 表名
(3)带子查询的删除
删除满足条件的行:删除Course表中编号为B009的记录。
sqlDelete from Course Where Cno='B009'
说明:根据主关键字,找到特定的行,并进行删除。
带子查询的删除: 对Course表中,没有任何学生选修过的课程,执行删除操作。
sqlDelete from Course Where Cno not in (Select Cno from sc)
4.6 视图
4.6.1 定义视图
利用CREATE VIEW语句可以创建视图,该命令的基本语法如下:
sql
CREATE VIEW [ schema_name . ] view_name
[ (column [ ,...n ] ) ]
[ WITH ENCRYPTION ]
AS SELECT_statement
[ WITH CHECK OPTION ]
创建视图的Select的限制
① 定义视图的用户必须对所参照的表或视图有查询权限,即可执行SELECT语句。
② 不能使用COMPUTE或COMPUTEBY子句。
③ 不能使用ORDERBY子句。
④ 不能使用INTO子句。
⑤ 不能在临时表或表变量上创建视图。
创建视图:创建一个名为vwScs的视图,是将学生表中院系是计算机科学学院的学生的学号,姓名,性别,专业四个字段显示出来。
sqlCreate view vwScs As Select Sno,Sname,Ssex,Tel,EMAIL from Student Where Sdept='计算机科学学院'
创建名为vwScore的视图,显示学生的学号、姓名、课程号、考试分数。
sqlCreate view vwScore As Select Student.Sno,Student.Sname, SC.Cno, SC.Grade from SC,Student where SC.Sno=Student.Sno
4.6.2 更新视图
更新视图是指,通过视图对基本表中的数据进行修改。更新视图有以下三条规则:
(1) 若视图是基于多个表使用联接操作而导出的,那么对这个视图执行更新操作时,每次只能影响其中的一个表。
(2) 若视图导出时包含有分组和聚合操作,则不允许对这个视图执行更新操作。
(3) 若视图是从一个表经选择、投影而导出的,并在视图中包含了表的主键字或某个候选键,这类视图称为"行列子集视图",对这类视图可执行更新操作。
通过视图修改数据:通过vwScs视图进行数据更新,将杨华的电话修改为13966667777。
sqlUpdate vwScs set tel='13966667777' where Sname='杨华'
4.6.3 查询视图
视图建立完成后,就可以像访问表一样访问视图了。如针对向先前创建的视图,可以执行下面的SQL:
sql
Select * from vwScore Select * from vwScore Where Grade <85
4.6.4 视图的优点
视图隐藏了底层的表结构,简化了数据访问操作。
因为隐藏了底层的表结构,所以大大加强了安全性,用户只能看到视图提供的数据。
使用视图,方便了权限管理,让用户对视图有权限而不是对底层表有权限进一步加强了安全性。
视图提供了一个用户访问的接口,当底层表改变后,改变视图的语句来进行适应,使已经建立在这个视图上客户端程序不受影响。
4.6.5 视图修改与加密
对于已经创建的视图,要修改封装在其中的SQL代码,使用"Alter View 视图名 As..."的语法即可。
视图要进行加密,只需要在创建视图的时候,在视图名称之后使用"WITH ENCRYPTION"即可。
创建视图代码加密:创建名为vwScore2的视图,能显示学生的学号、姓名、课程名、分数。要求创建视图的源代码要加密。
sqlCreate View vwScore2 With Encryption As Select Student.Sno,Student.Sname, Course.Cname ,SC.Grade from SC,Student,Course where SC.Sno=Student.Sno and SC.Cno=Course.Cno
4.7 索引
4.7.1 索引概述
在关系数据库中,索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单
索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容。
建立索引的一般原则:如果某属性或属性组经常出现在查询条件 中,则考虑为该属性或属性组建立索引;如果某个属性经常作为分组的依据列 ,则考虑为该属性建立索引; 如果某属性和属性组经常出现在连接操作的连接条件中,则考虑为该属性或属性组建立索引。
索引的分类:
主键索引:当创建表时指定的主键列,会自动创建主键索引,并且拥有唯一的特性。
唯一索引(UNIQUE):每一行的索引值都是唯一的(创建了唯一约束,系统将自动创建唯一索引)
聚集索引(CLUSTERED):聚集索引就相当于使用字典的拼音查找,因为聚集索引存储记录是物理上连续存在 的,即拼音a过了后面肯定是b一样。
非聚集索引(NONCLUSTERED):非聚集索引就相当于使用字典的部首查找,非聚集索引是逻辑上的连续,物理存储并不连续。
4.7.2 建立与删除索引
聚集索引:对Course2表,将Cno字段设置为聚集索引和主关键字字段。
sqlAlter Table Course2 Add Constraint PK_Course2_Cno Primary Key Clustered (Cno)
说明:通过修改表结构的语句,来指定主关键字的字段名称。
唯一索引:对Course2表,将Cname字段设置为唯一索引。
sqlCreate unique index idxCourseName on Course2(Cname)
说明:在Create和Index之间使用Unique关键字。
删除索引:对Course2表,删除创建的索引idxCourseName。
sqldrop index idxCourseName On Course2 drop index Course2.idxCourseName
说明:使用上述两种方法之一,都可以删除对应的索引。