试图用通俗又通透的语言整理一下SQL语言这块内容的笔记,并没有局限于具体的章节而是把考试中可能要求写SQL语言的知识放在了一起,之后再写习题总结与拾遗。麻烦看官老爷点赞关注支持一下动力猿吧!
大家都知道SQL支持我们在数据库系统基础知识里学习的三级模式结构(感兴趣的朋友可以去看系列文章),但是SQL中的模式概念并不同于“三级模式结构”里的"模式"。其实最贴切的类比如上图,SQL中的表、视图、索引分别对应三级模式结构里的模式、外模式、内模式。
SQL里的模式SCHEMA概念更像是一个储物空间,我们把数据库中的某些关系比较紧密的数据对象(表、视图、索引等)打包在一起,让它们属于某个模式,以后查找和使用起来比较方便。
关于SQL模式我们只需要知道,每一个基本表、视图、索引都是定义在某个具体的模式下的。
(2)基本表:
一个基本表就是一个关系,列是属性,行是元组,当然还有我们看不见的各种约束。我们看基本表定义了数据的逻辑结构、联系、完整性约束等,这正对应数据库三级模式结构中模式的作用。
(3)视图:
顾名思义就是想让用户看到的东西,是从若干张基本表中抽取某些属性给你看的虚表(自己不含数据,显示的数据是从基本表中临时取来的)。和三级模式结构中的外模式一样,视图就是个看人下菜碟的势利眼,不同的用户看到的视图不一样,你是老板整个公司的信息你都能看到,你是员工别人的工资你都看不到。
因为视图看人下菜碟的特性它一定程度上也保护的数据库的安全性,只给你看不重要的信息就行了。
(4)索引:
索引是定义在基本表下的,顾名思义在关系属性A上建立索引可以提高查找在A上具有某个特性值的元组的效率。索引位于三级模式内模式这一层属于物理结构,常见的索引有B+树索引和Hash索引。
索引也不是越多越好。一方面,建立索引的属性虽然提高了查的效率,但是增删改更加复杂了。另一方面,访问更新索引需要磁盘操作。
因此,查询时有具体属性值要求的属性上可以建立索引来提高查询效率,但是对于没有属性值要求的属性以及通配符模糊查询的属性建立索引是无效的纯属浪费。
数据定义指对四种数据对象(模式、表、视图、索引)整体结构上的定义,即“型”上的定义。就拿基本表的数据定义来说,这里的创建、删除(整个表)和修改(比如增加新的属性列或者约束)都是对表的整体结构而言的,而不是对表里面的具体元组进行增删改查,那个叫数据操纵(数据查询+数据更新)。
模式没有修改一说,想改就删除再重新创建。
(1)模式的创建:
(2)模式的删除:
级联(CASCADE):将该模式和该模式下定义的全部对象如表、视图等(模式和表分别对应关系模式和关系)一并删除。
限制 (RESTRICT):只要该模式下有定义的对象就拒绝执行该删除语句。
(2)基本表的删除:
Restrict:表删除有限制条件,不能被其他表的约束所引用,不能有视图、触发器、存储过程或函数。
Cascade:把一个基本表的定义连同表上的所有记录、索引以及由此基本表导出的所有视图都删除,并释放相应的存储空间。
(1)视图的创建:
子查询:视图也是个关系表,因此视图也可以建立在其他视图上,子查询也可是对其他视图的查询。
属性列名:要么全部指定,要么全不指定。在以下三种情况下必须指定:1.某目标列是聚集函数或列表达式。2.多表连接时选出来几个同名列作为视图的字段。3.需要在视图中为某个列启用新的更合适的名字。
with check option子句:若有该字句,对视图进行UPDATE、INSERT、DELETE时要保证更新、插入、删除的行满足视图定义的谓词条件。
(2)视图的删除:
视图的删除是级联的,删除一个基本表/视图后,定义在其上的视图也一并被删除。
(1)索引的创建:
表名、列名: 索引可以建立在该表的一列或多列上,各列名之间用逗号分隔。
次序: 每个<列名>后面还可以用指定索引值的排列次序,可选 ASC(升序)或DESC(降序),默认值为ASC。
UNIQUE /CLUSTER:表明此索引的每一个索引值只对应唯一的数据记录/表示要建立的索引是聚簇索引。
数据字典是关系数据库管理系统内部的一组系统表,它记录了数据库中所有的定义信息,包括关系模式定义、视图定义、索引定义、完整性约束定义、各类用户对数据库的操作权限、统计信息等。
关系数据库管理系统在执行SQL 的数据定义语句时,实际上就是在更新数据字典表中的相应信息。
在进行查询优化和查询处理时,数据字典中的信息是其重要依据。
SQL语言中使用SELECT语句完成数据查询,大家肯定会联想到在第二章关系代数也具有查询功能。通过第二章我们也知道,SQL其实是一种具有关系完备性的关系演算语言,可以替代关系代数的作用。实际上考试题中也经常给一个查询,要求分别使用关系代数和SQL实现。
只要是关系表就可以数据查询,因此数据查询可以用于基本表、视图、派生表。
单表查询太简单我们就不说了,直接分析查询语句的基本结构,不管是什么样的查询都离不开这个。
句意:
根据WHERE字句的条件表达式从FROM字句指定的基本表、视图或派生表中找出满足条件的元组,再按SELECT字句中的目标列表达式选出元组中的属性值形成结果表。
DISTINCT:取消取值重复的行。
目标列 :
是*表示查询全部列。目标列也不只局限于属性名,可以是算数表达式(如2024-Sage)、常量(“YEAR”)、函数等。
通过指定别名可以改变查询结果的列标题,只需在目标列后跟上新的别名即可。
条件表达式:
每个谓词的具体应用可看课本P93,需要熟练掌握。
GROUP BY字句(带HAVING字句):
将结果按<列名1>的值进行分组,该属性列值相等的元组为一个组,通常会在每组中作用聚集函数。只有满足HAVING指定条件的组才能输出。
聚集函数:聚集函数只能用于SELECT后和GROUP BY的HAVING后,不能用于WHERE字句中。其中只有COUNT(*)计算空值(空也占个位置啊),其他操作都不计算空值。DISTINCT/ALL:计算时取消/不取消指定列中的重复值。默认为ALL。
ORDER BY字句:
结果表按<列名2>的值升序或降序排列。
最基础最常用的查询,连接查询就是把两个及以上的表“连接”起来一起查询,和关系代数语言里的连接就是一个意思。连接查询可细分为
内连接:
(1)不同的表连接(等值和非等值连接):只需要记住一句话,表和表之间的联系是通过公共属性实现的。
(2)表和自身连接:需要给表起一个别名,当做两个不同的表连接。
外连接:这个概念可见之前的文章“关系代数和关系完整性约束”,这里我们只需要知道写法即可。
(1)外连接(左右都可以空可以不是左也可以不是右)
(3)右外连接(左边可以空可以不是左)
类比左外连接。
既然一个SELECT语句的查询结果是一个集合,那么SELECT语句可不可以充当起FROM或者WHERE后的成分呢,也就是在一个查询语句中见到两个甚至多个SELECT?
(1)派生表查询:SELECT语句放在FROM后作为一个表,这个表显然不是原本存在在数据库中的而是通过查询派生出来的,所以叫派生表查询。需要注意的是我们必须为派生表指定一个别名。
(2)嵌套查询:SELECT语句放在WHERE语句(或者GROUP BY里的HAVING语句)里充当条件。嵌套查询是最复杂的查询语句了,总体上可分为不相关子查询(子查询和父查询不相关,可以单独先算出来)和相关子查询(子查询和父查询相关,得借助父查询的东西算出来)。呈现出来就是不相关子查询由内向外算,相关子查询由外向内算。
不相关子查询:
子查询结果是单值(有可能用聚集函数),说明可以用等或不等运算符比较,记得属性列名一定要放在运算符前面,SELECT放在后面。
子查询结果是多值集合,谓词应用IN或者比较符+any/all。
相关子查询:
要完全理解这个并穷尽所有情况太难了,我们的原则就是能不用相关子查询就不用,用别的代替不好吗。万一点名要用带EXIST或NOT EXIST的相关子查询,那也逃不出这四种问法:
查询所有选修了1号课程的学生姓名(EXIST符合要求的记录)
查询没有选修了1号课程的学生姓名(NOT EXIST符合要求的记录)
查询选修了全部课程的学生姓名(NOT EXIST一个要求NOT EXIST符合要求的记录)
查询至少选修了学生95002选修的全部课程的学生学号(NOT EXIST一个要求别人能满足但NOT EXIST我符合要求的记录)
两个SELECT语句之间用UNION / INTERSECT / EXCEPT来连接分别表示并交差三种操作。
考试的时候题目是不会有“必须用嵌套查询、必须用集合查询”这种死要求的,每种查询本来就有多种写法,只要写出来言之有理就算对。实际做题中每个正常人想的都是在SELECT的基本结构的每个位置填什么,这个课本上贴心帮我们总结了。我们自己要做的就是归纳这些选项的应用场景,从而看到要求能快速对应起来。
数据更新可以理解为对元组的修改,是对基本表进行的(当然视图也可以)。
数据库系统有五种常用的安全性技术,分别是用户标识与鉴定、存取控制、视图管理、密码存储、审计管理。
存取控制机制包括两部分:定义用户权限和合法权限检查。
存取控制机制分为自主存取控制(不同的用户对于不同的数据库对象各有不同的权限,而且这个权限还可以自主转授给其他用户)和强制存取控制(不同的数据库对象被标以不同的密级,每个用户被授予一定密级的许可证)。
用SQL实现自主存取控制是考试的重点,通过授予和收回权限来实现。
(1)授予
全部权限,使用ALL PRIVILEGES
全部用户,使用 PUBLIC
如果使用了WITH GRANT OPTION选项,说明用户还可以把被授予的权限授予给别人。
(2)收回
CASCADE:级联,回收用户的权限后把该用户转授别人的权限也从别人那里收回。
RESTRICT:如果要回收的权限也被用户转授给他人,拒绝执行回收语句。
(3)角色
挨个为每个用户都分配一个一个权限实在是太麻烦了!直接给用户授予一个角色(和官职一样,是权限的集合),用户是什么角色就有该角色的所有权限。
因为为不同的用户定义不同的视图可以把要保密的数据对无权存取的用户隐藏起来,所以视图机制为数据提供了一定程度上的安全保护。
审计功能把用户对数据库的所有操作自动记录下来放入审计日志。审计员可以利用审计日志监控数据库中的各种行为,重现导致数据库现有状况的一系列事件,找出非法存取数据的人、时间和内容等。
加密的基本思想是根据一定的算法将原始数据(明文)变换为不可直接识别的格式(秘文)。主要包括存储加密和传输加密。
SQL通过在列级定义主码或在表级定义主码定义实体完整性,当主码不止一个属性时只能定义表级主码。
SQL通过在表级定义外码定义参照完整性,FOREIGN KEY定义哪些列为外码,REFERENCES指定这些外码参照哪些表的主码。
因为表与表间存在关联,对其中一个表进行删改是很容易触发参照完整性违约操作的,有三种违约反应来进行处理。
用户自定义的完整性一般有非空、唯一、检查值符合某表达式,详情可见课本。
给某个完整性约束起一个名字,下次增加删除时直接操作名字,非常方便。
可以在建表时定义
也可以建表后删除、增加、修改(就是先删再增)。
有些完整性约束比较复杂可能涉及多个表和聚合操作,不可能仅凭在某一个表的某一列上加个约束来实现,比如“数据库课程最多60名学生选修”。我们想到,如果能对神通广大的SELECT语句进行CHECK判断,不管什么一般性的约束都能满足,这就是断言。
触发器规定的特定事件(触发事件)发生后,判断该触发事件是否满足了某条件,如果真就执行相应的触发动作。
创建触发器
触发器名:触发器名唯一,且触发器名和操作的表名必须在同一模式下。
表名:触发器必须定义在基本表上(视图就不行)。
BEFORE/AFTER: 在触发事件执行前/后激活触发器,注意只是激活触发器,接下来要判断触发条件才能确定是不是要执行触发动作。
触发事件:注意是指激活触发器的事件,不一定满足触发动作的条件。可以是各种增删改混合的操作。
触发器类型:分为语句级触发器(FOR EACH STATEMENT)和行级触发器(FOR EACH ROW)。语句级触发器是说,触发事件语句执行的只会引发一次触发动作,你一条语句我才触发一次。行级触发器不行,触发事件影响了这个表里的几行(几个元组),那么就引发几次触发动作。
触发条件:触发器激活后判断触发事件是否满足触发条件,如果满足就执行触发动作。触发器可以没有触发条件,即触发器被触发事件激活后直接就执行触发动作。
删除触发器
了解即可,一般不作为考点。
SQL语句考察的重点仍然是比较复杂的查询语句,大家应该多训练这一方面的题目,其他的语句只要能默写最基本的格式即可。