结构化查询语言(Structed Query Language,SQL)是关系数据库的标准语言,也是一个通用的,功能极强的关系数据库语言。
其功能不仅是查询,而且包括数据库模式创建,数据库数据的插入和修改,数据库安全性完整性控制等一系列功能。
目录
1.SQL概述
1.1SQL的产生和发展
1.2 SQL的特点
1.3SQL的基本概念
2.学生-课程数据库
3.数据定义
3.1模式的定义和删除
3.2基本表的定义,删除与修改
1.定义基本表
2.数据类型
3.模式与表关系描述
4.修改基本表
3.3索引的建立与删除
1.建立索引
2.修改索引
3.删除索引
3.4数据字典
4.数据查询
4.1单表查询
1.选择表中若干列
2.选择表中的若干元组
3.order by子句
4.聚集函数
5.Group By子句
4.2连接查询
4.3嵌套查询
1.带有in谓词的子查询
2.带有比较运算符的子查询
3.带有any(some)或all谓词的子查询
4.带有exist谓词的子查询
4.4集合查询
4.5基于派生表的查询
4.6 select语句的一般格式
5.数据更新
5.1插入数据
1.插入元组
2.插入子查询结果
5.2修改数据
5.3删除数据
6.空值的处理
1.空值的产生
2.空值的判断
3.空值的约束条件
7.视图
7.1建立视图编辑
2.删除视图
7.2查询视图
7.3更新视图
7.4视图的作用
目前,没有一个数据系统能够支持SQL标准的所有概念和特性。
许多软件厂商还对SQL基本命令集进行了不同程度的扩充和修改,可以支持标准以外的一些功能特性。
SQL集数据查询(data query),数据操纵(data manipulation),数据定义(data definition)和数据控制(data control)功能于一体。
主要特点包括:
1.综合统一:
数据库系统的主要功能是通过数据库支持的数据语言来实现的。
非关系模型(层次模型,网状模型)的数据语言一般都分为:
(1)模式数据定义语言(schema data definition language,模式DDL)
(2)外模式数据定义语言(subschema data definition language,外模式DDL或子模式DDL)
(3)数据存储有关的描述语言(data storage description language, DSDL)
(4)数据操纵语言(data manipulation language,DML)
它们分别用于定义模式,外模式,内模式和进行数据的存取与处置。
用户在数据库系统投入运行时还可以根据需要随时的,逐步的修改模式,并不影响数据库的运行,从而使系统具有良好的可扩展性。
2.高度非过程化
SQL进行数据操作时,只要提出“做什么”,而无需指明”怎么做“,无需了解存取路径(针对面向过程的语言),存取路径的选择和SQL的操作过程由系统自动完成。
3.面向集合的操作方式
非关系数据模型采用的时面向记录的操作方式,操作对象时一条记录:
例如查找成绩在80分以上的学生姓名,用户必须一条条的把满足条件的学生记录查找出来
(需要说明按照哪条路径,如何循环等)
而SQL采用集合操作方式,插入,删除,更新操作都可以是元组的集合
4.以同一种语法结构提供多种使用方式
SQL既是独立的语言,又是嵌入式语言。
作为独立的语言,它能够独立地用于联机交
互的使用方式,用户可以在终端键盘上直接键入SQL命令对数据库进行操作;
作为嵌入式语言,SQL语句能够嵌入到高级语言(例如C、C++、Java)程序中,
供程序员设计程序。
5.语言简洁,易学易用
核心功能仅仅用9个动词
支持SQL的关系数据库管理系统同样支持关系数据库的三级模式结构。
外模式:若干视图(view)和部分基本表(basic table)
模式:若干基本表
内模式:若干存储文件(stored file)
基本表和视图一样都是关系
视图是一个或几个基本表导出的表,它本身不独立存储在数据库中,即数据库中只存放视图的定义而不存放视图对应的数据,这些数据仍存放在导出视图的基本表中。
视图是一个虚表。
首先要定义一个学生-课程模式S-T
上述关系中画下划线的记为主码
SQL的数据定义功能包括模式定义,表定义,视图和索引的定义
一个关系数据库管理系统中可以建立多个数据库,一个数据库中可以建立多个模式。
一个模式下通常包括多个表,视图和索引等数据对象。
1.定义模式
模式定义语句:
create schema <模式名> authorization <用户名>
如果没有指定<模式名>,那么<模式名>隐含为用户名
定义模式实际上是定义一个命名空间,在在这个空间里可以进一步的定义该模式包含的数据库对象:
基本表,视图和索引等
目前,在CREATE SCHEMA中可以接受CREATE TABLE, CREATE VIEW和GRANT
子句。也就是说用户可以在创建模式的同时在这个模式定义中进一步创建基本表、视图,
授权。即
2.删除模式
其中CASCADE和RESTRICT两者必选其一。
选择了CASCADE (级联),表示在删除模
式的同时把该模式中所有的数据库对象全部删除;
选择了RESTRICT (限制),表示如果该
模式中已经定义了下属的数据库对象(如表、视图等),则拒绝该删除语句的执行。
(只有当
该模式中没有任何下属的对象时才能执行DROP SCHEMA语句。)
(这里的模式名应该是TEST,出版错误)
建表的同时通常还可以定义与该表有关的完整性约束条件,
这些完整性约束条件被存入系统的数据字典中,
当用户操作表中数据时由关系数据库管理系统自动检查该操作是否
违背这些完整性约束条件。
如果完整性约束条件涉及该表的多个属性列,则必须定义在表
级上,否则既可以定义在列级也可以定义在表级。
注意这里有一个表级完整性约束
先修课程号,被参照表是course,被参照列是cno(先修课程号本质上是课程号)
因为主码是由两个属性构成的,所以必须作为表级完整性进行定义
foreign key(sno) references student(sno)
关系模型中很重要的一个概念是域
每一个属性来自于一个域
它的取值必须是域中的值
SQL中,域的概念用数据类型来实现,定于表中的各个属性时需要指明其数据类型及其长度。
一个属性选用哪种数据类型要根据实际情况来决定,一般要从两个方面来考虑,--是
取值范围,二是要做哪些运算。例如,对于年龄(Sage) 属性,可以采用CHAR(3)作为数
据类型,但考虑到要在年龄上做算术运算(如求平均年龄),所以要采用整数作为数据类型,
因为在CHAR(n)数据类型上不能进行算术运算。
每个基本表都属于一个模式,一个模式都包含多个基本表。
当定义基本表时通常一般有3种方法定义它所属的模式:
方法1:在表明种显式的给出模式名
方法二:在创建模式语句时同时创建表
搜索路径的当前默认值是$user,PUBLIC。其含义是首先搜索与用户名相同的模式名,
如果该模式名不存在,则使用PUBLIC模式。
set search_path to "S—T"
随着需求变化,有时也需要修改已建立好的基本表。
SQL语言用alter table语句来修改基本表
add子句用于增加新列(新的列级完整性约束条件和新的表级完整性约束条件)
drop column子句用于删除表中的列
(如果指定了cascade短语,则自动删除引用了该列中的其他对象,如视图)
(如果指定了resrtrict短语,则如果该列被其它对象使用,则拒绝删除该列)
当表的数据量比较大时,查询操作会比较耗时,建立索引是加快查询速度的有效手段。
数据库索引有多种类型
顺序文件上的索引是针对按指定属性值升序或降序存储的关系
(在该属性上建立一个顺序索引文件,索引文件由属性值和相应的元组指针组成)
B+树索引是将索引属性组成B+树的形式,B+树的叶节点为属性值和相应的元组指针
(B+树索引具有动态平衡的优点)
散列索引是建立若干个桶,将索引属性按照散列函数值映射到相应的桶里
(桶中存放索引属性值和相应的元组指针,散列查找具有查找速度快的特点)
位图索引是用位向量记录索引属性中可能出现的值,每个维向量对应一个可能值。
一般来说,建立和删除索引由数据库管理员或表的属主来完成
关系数据库管理系统在窒息感查询时会走动选择合适的索引作为存取路径,用户不必不能显式的选择索引(索引属于内模式的范畴)
注:这里的STUSNO只是索引名
对于已经建立的索引,如果需要对其进行重新命名,可以使用alter index语句
alter index scno rename to scsno
数据字典是关系数据库管理系统内部的一组系统表,它记录了数据库中所有的定义信息,包括关系模式定义,视图定义,索引定义,完整性约束定义。
关系数据库管理系统在执行SQL的数据定义语句时,实际上就是在更新数据字典中相应的信息。
数据查询是数据库核心操作,SQL提供了SELECT语句
implication:
更具where子句的表达式从from子句指定的基本表,视图或派生表中
找出符合条件的元组
再select子句中目标属性
if 存在group by子句,则结果按照列名进行分组,属性值相等的元组为一个组
通常会在每组中作用聚集函数
如果group by子句中带having短语,则只有满足条件的元组才予以输出
即仅涉及一个表的查询
选择表中全部或部分列集关系代数的投影运算
(1)查询指定列
可以根据需要改变列的显示顺序:即可以与表中的顺序不一致
(2)查询全部列
法1:在select关键字后列出所有列名
法2:若不考虑顺序,则可将目标表达式列名定位*,按序输出
(3)查询经过计算的值
select子句的<目标表达式>不仅可以是表中的属性列,
查询全体学生的姓名,出生年份和所在的院系,要求用小写字母表示系名
(1)若stdudent表中没有查询的列名,则自动填充列名和属性下的元组值
(2)小写字母(lower())
用户还可以通过指定别名来改变查询结果的列标题
(1)消除取值重复的行
两个本来不完全相同的元组在投影到在指定的某些列后,可能会变成相同的行。
可以用distinct来消除他们
(2)查询满足条件的元组
查询满足指定条件的元组可以通过where子句实现
关系数据库管理系统执行该查询的一种可能过程是:对Student表
进行全表扫描,取出一个元组,检查该元组在sdept列的值是否等于”CS“,
如果相等,则取出Sname列的值形成一个新的元组输出。重复该过程
如果全校有数万个学生,计算机系的学生人数是全校学生的5%左右,可以在Student表的Sdept列上建立索引,系统会利用该索引找出Sdept='CS'的元组,从中取出Sname列值形成结果关系。这就避免了对Student 表的全表扫描,加快了查询速度。注意如果学生较少,索引查找不一定能提高查询效率,系统仍会使用全表扫描。这由查询优化器按照某些规则来做出选择
这里使用了distinct短语,当一个学生有多门课程不及格,它的学号也只列1次。
确定范围
确定集合
字符匹配(最重要)
%表示任意长度
_表示单个字符
如果用户要查询的字符串本身就含有通配符%或_,这时就要使用escape<>对通配符进行
转义了。
在最后加上escape “\”
更加complicated的:
涉及空值的查询
多重条件查询
用逻辑运算符(and优先级高于or)
用户可以对查询结果的一个或多个属性列的升序(ASC)或降序(DESC)排列,默认值为升序。
空值由具体系统实现来决定
可以对多个属性列进行不同的排序,不过有先后次序之分
主要有以下几种
注意聚集函数是放在select查询里面
聚集函数和多表连接
where后面跟查询条件时可以使用多表连接
聚集函数只能用于select子句和group by中having子句(对不符合条件的元组删除)
学分是课程表的属性,所以要将两个表联系起来。
对查询结果分组后
聚集函数(跟在having后面)将分别作用于每一个组
学号是1号的
选了几门课程号后面跟着成绩
然后对于1号同学进行平均成绩聚集函数计算
如果满足分组后的having条件判断
则输出这组元组
where是对一条记录的描述,而avg是对一组
所以where子句中不能使用聚集函数作为条件表达式
以前的查询都是针对一个表进行的,若一个查询同时涉及两个以上的表,则称之为连接查询。
连接查询是关系数据库中最主要的查询,包括:
等值连接查询,自然连接查询,非等值连接查询
外连接查询和复合条件查询
自然连接就是在select中去掉重复字段的方式实施
自身连接:一个表与其自己进行连接
需要取别名以示区别
左外连接,在等值连接的基础上
Student表全部输出
表的连接其实是外码关系
可以同时输出多个表的属性
记为多表连接
在SQL语言中
一个select-from-where语句称为一个查询块
将一个查询块
嵌套在另一个查询块的
where子句或者
having短语的条件中的查询称为嵌套查询
上层的查询块称为外层查询或父查询
下层查询块称为内层查询或子查询
嵌套查询可以用多个简单查询构成复杂的查询,从而增强SQL的查询能力,以层层嵌套的方式来构造程序正是SQL中结构化的含义所在。
在嵌套查询中,子查询的结果往往是一个集合,所以谓词in是嵌套查询中最常使用的谓词
本查询同样可以用连接查询来实现:
有些嵌套查询可以用连接运算来替代,有些是不能的。
例3.55和例3.56中子查询的查询条件不依赖于父查询,这类子查询称为不相关子查询。
如果子查询的查询条件依赖于父查询,这类子查询称为相关子查询。
然后我们从SC表中取出下一个学号进行课程成绩大于平均成绩查找
求解相关子查询不能像求解不相关查询那样一次将子查询求解出来
内层查询由于与外层查询相关,因此需要反复求值
子查询返回单值时可以用比较运算符
但返回多值时要用any(有时系统用some关键词)或all谓词修饰符
回顾上面谓词
关系数据库管理系统执行此查询时,首先处理子查询,找除CS系中所有学生的年龄,构成一个集合(10,19);然后处理父查询,找出所有不是CS系且年龄小于20或19的学生。
本查询也可用聚集函数来实现,首先用子查询找出CS系中最大年龄(20),然后再父查询中查找所有非CS系且年龄小于20岁的学生:
事实上,用聚集函数实现子查询通常用any或all查询效率要高
对应关系如下:
不看了,理解起来很简单
带有exist谓词的子查询不返回任何数据,只产生逻辑真(true)
或者逻辑假(false)
查询所有选修了1号课程的学生姓名
本查询涉及student表和SC。
可以在student中依次取每个元组的sno值,用此值去检查SC表。
若SC表存在这样的元组,其sno值等于次student.sno值,并且
其cno=“1”
使用存在量词exist后,若内层查询结果非空,则外层
where子句返回where子句返回真值,否则返回假值。
有exists引出的子查询,其目标列表达式通常用*,因为只返回真值或假值,
给出列名无实际意义
本例中子查询的查询条件来自外层父查询的某个属性值(即sno值),因此时
相关子查询。
这个相关子查询的的处理过程是:首先取外层查询中student表的第一个元组
根据它与内层查询相关的属性值(sno值)处理内层查询。
若where子句返回值为真,则取外层查询中该元组的sname放入结果表
然后再取出student表的下一个元组
重复这一过程,直至外层student表全部检查完为止
与存在谓词相对的是not exists存在量词
exist存在谓词的子查询不能被其他形式的子查询等价替换,但所有带in谓词,比较运算符,any和all谓词的子查询都能用带exists谓词的子查询等价替换
如下:
in谓词
exist谓词
我们发现这个逻辑蕴含式在
SQL语言还是非常重要的
虽然很难
p->q它能转化成什么非p和q两者只能一方存在
select语句的查询结果是元组的集合,所以多个select语句的结果可以进行集合操作。
集合操作主要包括
并操作(union),交操作(intersect)和差操作(except)
本查询实际上是求计算机科学系所有学生与年龄不大于19岁学生的并集。
使用union并操作,系统或自动去掉重复元组(记录)
如果要保留重复元组
则用union all操作符
intersect交操作符
子查询不仅可以出现在where子句中,还可以出现在from子句中,
这时子查询生成的临时派生表
(derived table)成为主查询的查询对象。
找出每个学生超过他自己选修课程平均成绩的课程号
这里FROM子句中的子查询将生成一一个派生表Avg_ SC。
该表由avg_ sno 和avg_ grade
两个属性组成,记录了每个学生的学号及平均成绩。
主查询将SC表与Avg. sc按学号相等
进行连接,选出修课成绩大于其平均成绩的课程号。
需要说明的是,通过from子句生成派生表时,as关键词可以省略,
但必须为派生关系指定一个别名。
一般格式:
数据更新操作有三种:
向表中添加若干行数据
修改表中的数据
删除表中若干行数据
sql的数据插入语句insert有两种形式
一种是插入一个元组
另一种是插入子查询结果(可插入多个元组)
在into里面如果没有给出属性值
就要给出空值,然后值与属性名一一对应。
子查询不仅可以嵌套在select语句中用来构造父查询的条件
也可以嵌套在insert语句中用来生成要插入的批量数据
注意我向dept_age表里面插入的是一个子查询结果的元组
delete语句的功能是从指定的表中删除满足where子句条件的所有元组/
删除的是表中的数据,而不是关于表的定义
表的定义仍在字典中
插入,修改等
属性定义时
有not null约束条件不能取空值
加了码的属性也不能取
视图的特点
1.虚表,是从一个或几个基本表(或视图)导出的表
2.只存放视图的定义,不存放视图对应的数据
3.基表中的数据发生变化,从视图中查询出的数据也
随之改变
子查询可以是任意的select语句
with check option表示视图进行更新,插入和删除的行要满足视图定义的
谓词条件(即子查询中条件表达式)
省略了视图is_student的列名,隐含了由子查询中select子句中的三个列名组成。
以后对该视图进行增删改时,关系数据库系统会自动加上
sdept=“IS”的条件
上例中建立视图
是由单个基本表导出的,并且只是去掉了基本表的某些行和某些列,但保留了主码
则称这类视图为行列子集视图。
视图删除后视图的定义将从数据字典上删除,如果该视图上还导出来其他视图,
及使用cascade级联删除语句把该视图和由他导出的所有视图一起删除。
视图定义后,用户就可以像对基本表一样对视图进行查询了
关系数据库管理系统执行对视图的查询时,首先会进行有效的检查,检查
设局的表,视图是否存在,如果存在。
则从数据字典中取出视图的定义,坝顶语中的子查询和用户查询
结合起来,转换成等价的对基本表的查询。
这一转换过程称为视图消解
即转换过后查询语句为
但是在使用时如果视图中出现了
聚集函数属性,则
会出现where子句中不能出现条件表达式为聚集函数(selec和having里面)的
转换查询语法错误。
定义视图并查询视图与基于派生表的查询是由区别的。
视图一旦定义,其定义将永久保存在数据字典中。
在之后的所有查询都可以直接引用该视图。
而派生表只是在语句执行时临时定义,语句执行后即被删除。
更新视图是指通过视图来
插入,删除和修改数据
由于视图是不实际存储数据的虚表,
实质上是转换为对基本表的更新操作。
我们可以加上with check option
这样在视图上增删改数据时,系统会检查视图定义的条件
若不满足条件则拒绝执行。
有些视图是不可更新的。
视图最终是定义在基本表上的,对
视图的一切操作最终也要转换为对
基本表的操作。
那么为什么还要定义视图呢?
这样尽管数据库的逻辑结构改变了(变为SX和SY两个表),但应用程序不必修改。
因为新建立的视图仍为用户原来的关系,若使用户的外模式保持不变,
用户的应用程序通过视图仍能够通过视图查找数据。