目前,没有一个数据库系统能够支持SQL标准的所有概念和特性
许多软件厂商对SQL基本命令集还进行了不同程度的扩充和修改,有可以支持标准以外的一些功能特性
SQL集数据查询(data query)、数据操纵(data manipulation)、数据定义(data definition)和数据控制(data control)功能于一体。
SQL集数据定义语言、数据操纵语言、数据控制语言的功能于以梯,语言风格统一,可以独立完成数据库生命周期中的全部活动,包括以下一系列操作要求:
定义和修改、删除关系模式,定义和删除视图,插入数据,建立数据库
对数据库中的数据进行查询和更新
数据库重构和维护
数据库安全性、完整性控制,以及事务控制
嵌入式SQL和动态SQL定义
高度非过程化
非关系数据模型的数据操纵语言是面向过程的与i眼,用过程化语言完成某项请求必须指定存取路径
SQL进行数据操作时,只要提出“做什么”,而无须知名“怎么做”,因此无需了解存取路径。存取路径的选择以及SQL的操作过程由系统自动完成
面向集合的操作方式
以同一种语法结构提供多种使用方式
语言简介,易学易用
使用学生-课程数据库为例
Student
Sno | Sname | Ssex | Sage | Sdept |
---|---|---|---|---|
201215121 | 李勇 | 男 | 20 | CS |
201215122 | 刘晨 | 女 | 19 | CS |
201215123 | 王敏 | 女 | 18 | MA |
201215125 | 张立 | 男 | 19 | IS |
Course
Cno | Cname | Cpno | Ccredit |
---|---|---|---|
1 | 数据库 | 5 | 4 |
2 | 数学 | 2 | |
3 | 信息系统 | 1 | 4 |
4 | 操作系统 | 6 | 3 |
5 | 数据结构 | 7 | 4 |
6 | 数据处理 | 2 | |
7 | PASCAL语言 | 6 | 4 |
SC
Sno | Cno | Grade |
---|---|---|
201215121 | 1 | 92 |
201215121 | 2 | 85 |
201215121 | 3 | 88 |
201215122 | 2 | 90 |
201215122 | 3 | 80 |
SQL的数据定义语句
操作对象 | 创建 | 删除 | 修改 |
---|---|---|---|
模式 | CREATE SCHEMA | DROP SCHEMA | |
表 | CREATE TABLE | DROP TABLE | ALTER TABLE |
视图 | CREATE VIEW | DROP VIEW | |
索引 | CREATE INDEX | DROP INDEX | ALTER INDEX |
SQL标准不提供修改模式定义和修改视图定义的操作。用户如果想修改这些队形,只能先将它们删除然后重建。
一个关系数据库管理系统的实例中可以建立多个数据库,一个数据库中可以建立多个模式,一个模式下通常包括多个表、视图和索引等数据库对象
代码
CREATE SCHEMA<模式名>AUTHORIZATION<用户名>
如果没有指定模式名,那么模式名隐含为用户名
调用创建模式命令必须有CREATE SCHEMA的权限
目前,在CREATE SCHEMA中可以接受CREATE TABEL,CREATE VIEW和GRANT子句。也就是说用户可以在创建模式的同时在这个模式定义中进一步创建基本表、视图,即
CREATE SCHEMA <模式名> AUTHORIZATION <用户> [<表定义子句>|<视图定义子句>|<授权定义子句>]
DROP SCHEMA <模式名><CASCADE|RESTRICT>
其中CASCADE和RESTRICT两者必须选其一。
CASCASDE(级联),表示在删除模式的同时把该模式种所有的数据库对象全部删除;
RESTRICT(限制)表示如果该模式中已经定义了下属的数据库对象(如表、视图等),则拒绝改删除语句的执行,只有当该模式中没有任何下属的对象时才能执行DROP SCHEMA语句
语法格式
CREATE TABLE<表名>(<列名><数据类型>[列级完整性约束条件]
,<列名><数据类型>[列级完整性约束条件]
……
[,<表级完整性约束条件>])
关系模型中有一个很重要的概念是域。每一个属性来自一个域,它的取值必须是域中的值。
SQL中域的概念用数据类型来实现。定义表的各个属性时需要指明其数据类型及长度。
每一个基本表都属一某一种模式,一个模式包含多个基本表。当定义基本表时一般有三种方法定义它所属的模式
ALTER TABLE<表名>
[ADD [COLUMN]<新列名><数据类型>[完整性约束]]
[ADD<表级完整性约束>]
[DROP [COLUMN]<列名>[CASCADE|RESTRICT]]
[DROP CONSTRAINT<完整性约束名> [RESTRICT|CASCADE]]
[ALTER COLUMN<列名><数据类型>]
表名是要修改的基本表
ADD用于增加新列、新的列级完整性约束条件和新的表级完整性约束条。
DROP COLUMN子句用于删除表中的列,如果指定了CASCADE,则自动删除引用了该列的其他对象,比如视图。如果指定了RESTRICT短语,则如果改列被其他对象引用,RDBMS将拒绝删除该列。
DROP CONSTRAINT用于删除指定的完整性约束条件
ALTER COLUMN用于修改原有的列定义,包括修改列明和数据类型
DROP TABLE<表名>[RESTRICT|CASCADE]
RESTRICT该表的删除是有限制条件的。欲删除的基本表不能被其他表的约束所引用,不能有视图,不能有触发器,不能有存储过程或者函数
CASCADE该表的删除没有限制条件。在删除基本表的同时,相关的依赖对象,如视图,都将被一起删除
先声明一下,此处是按照王珊老师的数据库系统概论写的,但是如果用sql server运行的话指令是没法运行的
当表的数据量比较大时,查询操作会比较耗时。建立索引是加快查询速度的有效手段。
常见的索引包括
在sql语言中,建立索引使用CREATE INDEX语句
格式
CREATTE [UNIQUE][CLUSTER] INDEX <索引名>
ON <表名>(<列名>[<次序>][,<列名>[<次序>]]……)
表名是要建立索引的基本表的名字。索引可以建立在该表的一列或多列上,各列名之间用逗号分隔。
每个列名后面还可以用次序指定索引值的排列次序,可选ASC(升序)或DESC(降序),默认值为ASC
UNIQUE表明此索引的每一个索引值只对应唯一的数据记录
CLUSTER表明要建立的索引是聚簇索引
对于已经建立的索引,如果需要对其重新命名,可以使用ALTER INDEX语句
格式
ALTER INDEX <旧索引名> RENAME TO <新索引名>
这段代码是会报错的,比如
这个地方错因在于alter不能改变索引名,如若改变索引名就需要调用存储过程将上面的代码改成这个即可
EXEC sp_rename @objname = 'scno', @newname = 'scsno', @objtype = 'index';
索引一旦建立就由系统使用和维护,不需要用户干预,建立索引是为了减少查询操作的时间,但如果数据增、删、改频繁。系统会花费许多时间来维护索引,从而降低了查询效率,这样可以删除一部分不必要的索引
在SQL中,删除索引使用的是DROP INDEX语句
格式
DROP INDEX <索引名>
删除索引时,系统会同时从数据字典中删除有关该索引的描述
是关系数据库管理系统内部的一组系统表,记录了数据库中所有的定义信息,包括关系模式定义、视图定义、索引定义、完整性约束定义、各类用户对数据库的操作权限、统计信息等。关系数据库管理系统在执行SQL的数据定义语句时,实际上就是在更新数据字典中的相应信息。在进行查询优化和查询处理是啊,数据字典中的信息是其重要依据
格式
SELECT [ALL|DISTINCT]<目标列表达式>[,<目标列表达式>]…
FROM <表名或视图名>[,<表名或视图名>…]|(<SELECT语句>)[AS]<别名>
[WHERE<条件表达式>]
[GROUP BY<列名1>[HAVING<条件表达式>]]
[ORDER BY<列名2>[ASC|DESC]]
根据where子句的条件表达式从from子句指定的基本表、视图或派生表中找出满足条件的元组,再按select子句中的目标列表达式选出元组中的属性值形成结果表
若有group by子句,则将结果按<列名1>的值进行分组,该属性列值相等的元组为一个组。通常会在每组中作用聚集函数。如果group by子句带having短语,则只有满足指定条件的组才予以输出
如果有order by子句,则结果表还要按<列名2>的值的升序或者降序排序
select语句即可完成简单的单表查询,也可以完成复杂的连接查询和嵌套查询。
SELECT <目标列表达式>
SELECT *
SELECT子句的目标表达式不仅可以实表中的属性列,也可以是表达式(如通过出生年份计算年龄)
两个本来并不完全相同的元组在投影到指定的某些列上后,可能会变成相同的行。可以用DISTINCT消除它们
例
原
SELECT Sno
FROM SC
使用DISTINCT后
SELECT DISTINCT Sno
FROM SC
查询满足指定条件的元组可以通过WHERE子句实现。WHERE子句常用的查询条件如表所示
查询条件 | 谓词 |
---|---|
比较 | =,>,<,>=,<=,!=,<>,!>,!<;NOT+上述比较运算符 |
确定范围 | BETWEEN AND, NOT BETWEEN AND |
确定集合 | IN, NOT IN |
字符匹配 | LIKE, NOT LIKE |
空值 | IS NULL, IS NOT NULL |
多重条件(逻辑运算) | AND, OR, NOT |
用于进行比较的运算符一般包括=(等于),>(大于),<(小于),>=(大于等于),<=(小于等于),!=(不等于),<>(不等于),!>(不大于),!<(不小于)
关系数据管理系统执行查询的一种可能的过程是:对全表进行扫描,取出一个元组,检查该元组是否符合条件,如果符合则取出,并形成一个新的元组输出,否则跳过该元组,取下一个元组。重复该过程,知道处理完所有元组
第二种方法系统,利用索引找出满足条件的索引,加快查询速度。
ps:如果学生较少,索引查询不一定能提高查询效率,系统仍会使用全表扫描。这由查询优化器按照某些规则或估计执行代价来作出选择
BETWEEN……AND……和NOT BETWEEN……AND……可以用来查找属性值在(或者不在)指定范围内的元组,其中BETWEEN后是范围的下限(即低值),AND后是范围的上限(即高值)
IN用来查找属性值属于指定集合的元组
用LIKE可以进行字符串的匹配,格式
[NOT] LIKE'<匹配串>'[ESCAPE '<换码字符>']
查找指定的属性列与<匹配串>相匹配的元组。匹配串可以是一个完整的字符串,也可以是含有通配符%和_
如果用户要查询的字符本身就含有通配符 % 或 _ 需要用
ESCAPE '<换码字符>'
对通配符进行转意
WHERE GRADE IS [NOT]NULL
逻辑运算符AND和OR可用来连接多个查询条件。AND的优先级高于OR,但用户可以用括号改变优先级
用户可以用ORDER BY子句对查询结果按照一个或多个属性列的升序(ASC)或降(DESC)排序,默认值为升序
对于空值,排序时显示的次序由具体系统实现来决定。例如,按升序排,含空值的元组最后显示,按降序排,空值的元组最先显示,各个系统的实现可以不同,只要保持一致就行
为了进一步方便用户,增强检索功能,SQL提供了许多聚类函数
COUNT(*) 统计元组个数
COUNT([DISTINCT|ALL]<列名>) 统计一列中值的个数
SUM([DISTINCT|ALL]) 计算一列值的总和(此列必须是数值型)
AVG([DISTINCT|ALL]<列名>) 计算一列值的平均值(此列必须是数值型)
MAX([DISTINCT|ALL]<列名>) 求一列值中的最大值
MIN([DISTINCT|ALL]<列名>) 求一列值中的最小值
如果指定DISTINCT短语,则表示在计算时要取消指定列中的重复值。如果不指定或者指定ALL短语,则表示不取消重复值
当据类函数遇到空值时,除COUNT( * )外,都跳过空值而只处理非空值,COUNT( * )是对元组进行技术,某个元组的一个或者部分列取空值不影响COUNT的统计结果
ps:WHERE子句中是不能用聚类函数作为条件表达式的。聚类函数只能用于SELECT子句和GROUP BY中的HAVING子句
将查询结果按照某一列或多列的值分组,值相等的为一组。
对查询结果分组的目的是为了细化据类函数的作用对象。如果未对查询结果分组,聚类函数将作用与整个查询结果
分组后聚类函数将作用于每一个组,即每一个组都有一个函数值。可以搭配count聚类函数实现对满足某些条件的元组进行数量统计
若一个查询同时涉及两个以上的表,则称之为连接查询。连接查询是关系数据库中最主要的查询,包括等值连接查询、自然连接查询、非等值连接查询、自身连接查询、外连接查询和复合条件连接查询
连接查询的WHERE子句中用来连接两个表的条件称为连接条件或连接谓词,其一般格式为
[<表名1>.]<列名1><比较运算符>[<表名2>.]<列名2>
其中比较运算符主要有=、>、<、>、+、<=、!=(或<>)等
此外连接谓词还可以使用下面形式:
[<表名1>.]<列名1>BETWEEN[<表名2>.]<列名2>AND[<表名2>.]<列名3>
当连接运算符为=时,称为等值连接。使用其他运算符称为非等值连接
连接谓词中的列名称为连接字段,连接条件中的各连接字段类型必须是可比的,但名字不必相同
关系数据库管理系统执行连接操作的一种可能过程是:首先在表1中找到第一个元组,然后从头开始扫描第二个表,注意查找与第一个表中第一个元组的列1相等的第二个表的元组,找到后与将第一个表中的第一个元组与该元组拼接起来,形成结果表中一个元组。第二个表中全部查找完毕后,再照第一个表中第二个元组,然后从头开始扫描第二个表,逐一查找满足连接条件的元组,找到后将第一个表中的第二个元组与该元组拼接起来,形成结果表中一个元组,重复上述操作,直到第一个表中全部元组处理完毕位为止,这就是嵌套循环连接算法的基本思想。
如果在建立了索引的表中,就不需要每次全表扫描了,根据表中的值通过索引找到相应的元组。
ps:用索引查询通常回避全表扫描快
若在等值连接中把目标列中重复的属性列去掉则为自然连接
一条SQL语句可以同时完成选择和连接查询,这时的WHERE子句是由连接谓词和选择谓词组成的复合条件,此种查询是一种优化(高效)的执行过程
一个表与其自身进行连接,称为表的自身连接
取别名
select * from dbo.sc "first",dbo.sc "second"
此时要为表取两个别名,一个是FIRST,另一个是SECOND
SELECT "first".Cno,"second".Cpno
FROM dbo.sc "first",dbo.sc "second"
WHERE "first".Cpno="second".Cno
将悬浮元组保存在结果关系中的连接称为外连接(悬浮元组的值为NULL)
select student.sno,sname,ssex,sage,adept,cno,grade
from student left outer join sc on (student.sno=sc.sno)
也可以使用USING来去掉结果中的重复值:FROM Student LEFT OUTER JION SC USING (Sno)
左外连接列出左边关系中的所有元组,右外连接列出右边关系中所有的元组
连接操作除了可以两表连接、一个表与其自身连接外,还可以是两个以上的表进行连接,后者通常称为多表连接
过程理解:
通常是先进行两个表的连接操作,再将连接结果与第三个表进行连接。
在SQL语言中,一个SELECT-FROM-WHERE语句称为一个查询块,将一个查询块嵌套在另一个查询块的WHERE子句或HAVING短语的条件中的查询称为嵌套查询
上层的查询块称为外层查询或父查询
下层的查询块称为内层查询或子查询
嵌套查询使用户可以用过个简餐查询构成复杂的查询,从而增强SQL的查询能力。以层层嵌套的方式来构造程序正是SQL中“结构化”的含义所在
在嵌套查询中,子查询的结果往往是一个集合,所以谓词IN是嵌套查询中最经常使用的谓词
子查询的查询条件不依赖于父查询,称为不相关子查询
有些嵌套查询可以用连接运算替代,有些是不能替代的
查询涉及多个关系时,用嵌套查询逐步求解层次清楚,易于构造,具有结构化程序设计的优点,再实际应用中,能够用连接运算表达的查询尽可能采用连接运算
如果子查询的查询条件依赖于父查询,这类子查询称为相关子查询,整个查询语句称为相关嵌套查询语句
带有比较运算符的查询是指父查询与子查询之间用比较运算符进行连接。当用户能确切知道内层查询返回的是单个值时,可用比较运算符连接
子查询返回单值时可以用比较运算符,但返回多值要用ANY(有的系统用SOME)或ALL谓词修饰符。而是用ANY或ALL谓词时则必须同时使用比较运算符
表达式 | 含义 |
---|---|
>ANY | 大于子查询结果中的某个值 |
>ALL | 大于子查询结果中的所有值 |
小于子查询结果中的某个值 |
|
小于子查询结果中的所有值 |
|
>=ANY | 大于等于子查询结果中的某个值 |
>=ALL | 大于等于子查询结果中的所有值 |
<=ANY | 小于等于子查询结果中的任意值 |
<=ALL | 小于等于子查询结果中的所有值 |
=ANY | 等于子查询结果中的某个值 |
=ALL | 等于子查询结果中的所有值(通常没有实际意义) |
!=(<>)ANY | 不等于子查询结果中的某个值 |
!=(<>ALL) | 不等于查询结果中的任何一个值 |
ANY(SOME)、ALL谓词与聚类函数、IN谓词的等价转换关系
= | <>或!= | < | <= | > | >= | |
---|---|---|---|---|---|---|
ANY | IN | – | <=MAX |
>MIN |
>=MIN |
|
ALL | – | NOT IN | <=MIN |
>MAN |
>=MAX |
|
带有EXISTS谓词的子查询不返回任何数据,只产生逻辑真值“true”或逻辑假值“false”
使用存在两次NOT EXISTS后,则相反
集合操作主要包括
并操作 UNION
交操作 INTERSECT
差操作 EXCEPT
参加集合操作的各查询结果的列数必须相同;对应项的数据类型也必须相同
子查询不仅可以出现在WHERE子句中,还可以出现在FROM子句中,这时子查询生成的临时派生表称为著查询的查询对象
FROM Student,(SELECT Sno FROM SC WHERE Cno='1') AS SC1
通过from子句生成派生表时,as关键字可以省略,但是必须为派生关系指定一个别名,而对于基本表,别名是可选项
SELECT [ALL|DISTINCT]<目标列表达式>[别名][,<目标列表达式>[别名]]……
FROM<表名或视图名>[别名][,<表明或视图名>[别名]]…|(<SELECT语句>)[AS]<别名>
[WHERE<条件表达式>]
[GROUP BY<列名1>[HAVING<条件表达式>]]
[ORDER BY<列名2>[ASC|DESC]]
插入语句INSERT通常有两种形式,一种是插入一个元组,另一种是插入子查询结果。后者可以一次插入多个元组
INSERT
INTO <表名>[(<属性列1>[,<属性列2>]…)]
VALUES(<常量1>[,<常量2>…)
INTO子句中没有出现的属性列,心猿族再这些列上将取空值。但必须注意的是,在表定义事说明了NOT NULL的属性列不能取空值,否则会出错
如果INTO子句中没有指明任何属性列表,则新插入的元组必须再每个属性列上均有值
ps:字符串常数要用单引号(英文括号)括起来
INSERT
INTO<表名>[(<属性列1>[,<属性列2>…])]
子查询
UPDATE<表名>
SET<列名>=<表达式>[,<列名>=<表达式>]…
[WHERE<条件>]
修改指定表中满足WHERE子句条件的元组。其中SET子句给出<表达式>的值用于取代相应的属性列值。如果省略WHERE子句,则表示要修改表中的所有元组
DELECT
FROM <表名>
[WHERE <条件>]
DELETE语句删除的是表中的数据,而不是关于表的定义
所谓空值就是不知道或者不存在或者无意义的值,SQL语言中允许某些元组的某些属性再一定情况下取空值。一般有一下几种情况
主键不能为空值!!!!
判断一个属性是否为空值使用
IS NULL
IS NOT NULL
不能为空值的情况
空值与另一个值的算术运算的结果为空值,空值与另一个值得比较运算的结果为UNKNOWN
有了UNKNOWN后,传统的逻辑运算中二值(TRUE,FALSE)逻辑就扩展成了三值逻辑
视图是从一个或几个表(或视图)导出的表,它与基本表不同,是一个虚表。数据库中只存放视图的定义,而不存放视图对应的数据,这些数据仍存放在原来的基本表中
CREATE VIEW<视图名>[(<列名>)[,<列名>…]]
AS<子查询>
[WITH CHECK OPTION]
子查询可以实人一的SELECT语句,是可以含有ORDER BY子句和DISTINCT短语,则取决于具体系统的实现
下列情况必须明确指定组成视图的所有列名:
CREATE VIEW IS_Student
AS
SELECT Sno,Sname,Sage
FROM Student
WHERE Sdept='IS'
WITH CHECK OPTION
由于加上了WITH CHECK OPTION子句,以后对该视图进行插入、修改和删除操作时,关系数据库管理系统会自动加上Sdept='IS’的条件。
若一个视图是从单个基本表导出的,并且只是去掉了基本表的某些行和某些列,但保留了主码,则称这类视图为行列子集视图
视图不仅可以建立在一个或多个基本表上,也可以建立在一个或多个已定义好的视图上,或建立在基本表与视图上
定义基本表时,为了减少数据库中的冗余数据,表中只存放基本数据,由基本数据经过各种计算派生出的数据一般是不存储的。由于视图中的数据并不实际存储,所以定义视图时可以根据应用的需要设置一些派生属性列。这些派生属性由于在基本表中并不实际存在,也称它们为虚拟列。带虚拟列的视图也称为带表达式的视图
带有聚类函数和GROUP BY子句的查询来定义视图,这种视图称为分组视图
如果视图对应得基本表发生了更改,视图将无法正常工作,修改基本表后应该删除由该基本表导出得视图,然后重建这个视图
DROP VIEW <视图名> [CASCADE]
视图删除后视图的定义将从数据字典中删除。如果该视图上还到处了其他视图,则使用CASCADE级联删除语句把该视图和由它导出的所有视图一起删除
基本表删除后,由该基本表导出的所有视图均无法使用了,但是视图的定义没有从字典中清除。删除这些视图定义需要显式地使用DROP VIEW语句
如果由于该视图还导出了其他视图需要使用级联删除语句
DROP VIEW IS_S1 CASCADE
关系数据库关系系统执行对视图的查询时,首先进行有效检查,检查查询中涉及的表、视图等是否存在。如果存在,则从数据字典中取出视图的定义,把定义中的子查询和用户查询结合起来,转换为等价的对基本表的查询,然后再执行修正了的查询。这一转换过程称为视图消解
因为WHERE子句中是不能用聚类函数作为条件表达式的,因此执行修正后的查询将会出现语法错误
目前多数关系数据库系统对行列子集视图的查询均能进行正确转换。但对非行列子集视图的查询就不一定能做转换了
定义视图并查询与基于派生表的查询是有区别的,派生表只是在语句执行时临时定义,语句执行后该定义即被删除
更新视图是指通过插入、删除和修改数据
由于视图是不实际存储数据的虚表,因此对视图的更新最终要转换为对基本表的更新
为了防止用户通过视图对数据进行增加、删除、修改时,有意无意地对不属于视图范围内的基本表数据进行操作,可在定义视图时加上WITH CHECK OPTION子句。这样在视图上增、删、改数据时,关系数据库管理系统会检查定义中的条件,若不满足条件则拒绝执行该操作
关系数据库中,并不是所有的视图都是可更新的,因为有些视图的更新不能唯一地有意义地转换成对相应基本表的更新
一般地,行列子集视图是可更新的。
个人博客:http://www.awsg.online
博客园:https://www.cnblogs.com/AWSG-Shaodw/
CSDN:https://blog.csdn.net/AngleWithShotgun/
简书:https://www.jianshu.com/u/df7323cbc116
微信公众号: