中级SQL
第三章的延续
连接表达式
☆视图------给谁看
立规矩
事务------
☆完整性约束
SQL数据类型与模式
索引定义
授权
☆ 左右连接
连接操作
AB拼在一起 谁留谁去
自然连接(还有内联和外联)
类似笛卡尔积+where 找到符合匹配条件的笛卡尔积出来的结果
student和takes的主键是同一个,因此可以自然将主键匹配在一起(这是自动连接的)

问题;
只有两张表的主键都存在的人才会被留下来,如果一个学生没选课,那么join表会清除他
NATURAL JOIN 是会自动按照"所有名字相同的列"进行匹配融合,而不仅仅是主键。
这是一个非常关键的区别,也是 NATURAL JOIN 在实际生产中极少被推荐使用的主要原因
- 逻辑错误:它把"居住城市"和"发货城市"强行匹配,把"用户更新时间"和"订单创建时间"强行匹配。这通常不是你想要的数据关系。
Using语句 严格按照course_id匹配
解决按照"所有名字相同的列"进行匹配融合的问题
select name,title
from (student natural join takes) join course using (course_id)
将二级表于course严格按照course_id匹配,但这样就严格要求两个表这两列都是course_id了
其他相同名字的列就会被系统自动别名a.dept_name b.dept_name
On语句 如果要匹配两张表名字不一样但需要匹配的列
select *
from student join takes on student_ID = takes_ID
如果希望某些数据A表有,B表没有,合成后肯定没有,但如果我们想要保留:
外联
如果用内联,就会丢失,因此要外联:对连接的扩展避免"信息的损失"
先内连接,将能找到的匹配数据输出,然后候补,把孤儿元组强行捞回到输出中,系统会用null属性补全缺失的部分

如果两个表都有对方没有的数据,就需要看保留哪边的数据了:
左联就算保留左边,右链就是保留右边
☆左联:
course natural left outer join prereq【期中要考】
右联:
course natural right outer join prereq
全外连接【左右都要保留】
course natural full outer join prereq

ON和Where的筛选机制 on保留null where丢弃null
筛选条件放在where,如果筛选条件不满足,就会被干掉,而如果在on中,就会变成null
假设你有两张表:
- 左表(用户表):张三、李四
- 右表(订单表):张三买了苹果,李四没有订单。
你的目标是:列出所有用户,以及他们金额大于 100 元的订单。
情况 1:筛选条件放在 ON 中(正确做法)
sql
SELECT *
FROM 用户表
LEFT JOIN 订单表
ON 用户表.id = 订单表.user_id AND 订单表.金额 > 100;
情况 2:筛选条件放在 WHERE 中(错误做法)
1SELECT *
2FROM 用户表
3LEFT JOIN 订单表
4ON 用户表.id = 订单表.user_id
5WHERE 订单表.金额 > 100;
- 逻辑 :
- 先执行
LEFT JOIN:此时内存里生成了两行数据,李四的那一行,订单金额是NULL。 - 再执行
WHERE:数据库开始检查每一行,看"金额"是否大于 100。 - 关键点 :李四那行的金额是
NULL。在 SQL 中,NULL > 100的结果是"未知"(即不成立)。 - 后果 :
WHERE子句直接把李四这行数据**过滤(干掉)**了。
- 先执行
- 最终显示 :只剩下张三。(这就变成了内连接,违背了"列出所有用户"的初衷)
自然连接和内联的区别
| 连接类型 | 核心特点 | 匹配方式 | 没匹配上的数据怎么办? |
|---|---|---|---|
| 内连接 | 只要交集 | 手动用 ON 指定 |
直接丢弃 |
| 外连接 | 保全某张表 | 手动用 ON 指定 |
保留并填充 NULL |
| 自然连接 | 全自动、去重列 | 自动找同名列 | 默认丢弃(即自然内连接) |
on using 自然考虑的是用哪些列连接(表内)
内外连考虑的是不匹配的列如何处理(表外)
先看要保留什么列?再看如何连接。
总结:
保全谁谁作为主,这里要确保显示没有老师的系,所以要把汉dept_name的表作为主表
on和where
内外连和自然链和onusing
视图
不同的人看到不同的表
按需暴漏,避免员工看到所有人的工资
可以将一个select语句封装为一个视图,这样之后就不需要敲sql查询,实现复用了。
可以理解为快捷方式 CREATE VIEW
CREATE VIEW v AS <select...from...where>
create view faculty as
select ID,name,dept_name
from instructor
select name
from faculty
where dept_name="BIO"
创建一个包含各学院总工资的视图
create view department_total_salary(dept_name,total_salary) as--如果属性没有继承原表,要别名!!!不能凭空创造一列
select dept_name, sum(salary)
from instructor
group by dept_name;
视图依赖
使用一个视图定义其他视图


实例化视图
将虚表变为实例
这是真的把表存起来,而不是宏定义一段sql。
但是由于存下来了,假如牵扯的关系更新了,就会outdated;了,就需要更新视图maintain维护视图。

☆考点 试图更新
新来的老师只能操作faculty的三列内容
insert into faculty
value("333","green""music")
但是faculty是依赖底层的instructor的,其中的salry字段是教务处给定的,因此加入后这个地方会引发歧义,一般填充null。
另一种严重的情况,假设学院无法填入,那么应该将这个老师分配给哪个学院呢?
这就出问题了,多表连接产生的视图是不可被更新的!!!
☆ 允许更新的情况
1.from子句只有一个数据库的关系(只依赖一张表)
2.select不含任何sum distinct 、聚集函数、表达式,比如增加1000元,如何分配给底层instructor
3.底层隐藏列必须可以设置为null,不然都插不进去(所有没出现在select中的属性允许null)
4.不可以having或groupby子句,底层表和select表必须一一对应!!!
事务
为了保证原子性,要用事务
一段select语句开始执行,就开始了事务
一种是"提交",永久更新数据库的更改
一种是"回滚",撤销修改
完整性约束
人操作失误了,就需要约束
安全性约束------防止未授权用户越权访问
notnull非空约束
primary主键约束------主键不可为空
Unique唯一性约束------(A1,A2,A3。。。)这组超码,要求没有两行在所有的超码上一致,可以为空
check(P)------关系中每一行都满足P的条件**(特别的,只有在false的时候不放行,而如果是null也会放行,最好加个notnull)**
foreign key (deptname) references department (deptname)
primary key(ID,)
check(sex in ('nan','nv'))
完整性约束------合法权限的用户手滑
引用完整性------外键
保证引用的属性值,在另一个表中为主键
foreign key (dept_name) referneces department (dept_name)
级联操作 cascade操作
如果引用完整性被破坏了,默认拒绝操作,比如插入不存在的属性"magic"
或者被引用的主键要被删除了,也会拒绝
或者引用的主键要改名了,会使用
方案: 拒绝 级联更改 置空
delete cascade 铁索连环,把关联的所有外键也删除了:
forign key(dept_name) referneces department
on delete cascade
on update casede 字符串替换
或者设定特殊值:
set null
set default
事务中对完整性约束的违反
暂时闭上眼睛:set constraints <list> deffered 推迟完整性约束的检查
复杂check条件 但是不可以跨表
check(time_slot in(select time_slot_id from time_slot))
断言assertion------全局的约束工具
不依附于任何一张表
create assertion <assertionname> check (条件)
一般与Not exist unique使用
但是如果每次都触发一次assert,就会拖垮整个系统
数据类型和数据模式
如何扩充词汇量
日期:date '2006-02-19'
时间:time '09:09:09'
时间戳:timestamp '2005-8-8 09:00:00'
interval区间:interval '1' day
时间-时间是一个区间
大对象类型
photos videos
blob:一大堆不可解释的二进制数据
clob:一大堆字符数据
当查询结果是一个大对象时,返回的是指向该对象的指针
备份会是灾难,会污染缓存池、
原数据与载体分离,数据库只存储URL,视频放在云存储中。
用户自定义类型
create type Dollars as numeric(12,2) final

域 domain
想把约束也打包进去
域包括约束和类型,自动检查约束
create domain degree_level varchar(10)
constraint degree)level_test
check (value in('bacholar',;master;));

索引INDEX
很多查询只涉及数据库的一小部分
快速得到结果
如何制作索引?:从需求出发,只对最频繁的属性建索引
create index student_ID_INDEX on student(ID)

授权
数据级权限(对表的操作):
Read------读取
Insert------插入,但不可以改
Update------允许更新,不能删
Delete------删除
模式级权限(对schema数据库操作):DBA做的
Index------允许创建和删除索引
Resources------允许创建新关系
Alteration------允许添加或删除关系的列
Drop------允许删除关系(表和schema一起删了)


授权 <Privilege>Read(select) Insert Update Delete:
我们可以在数据库的某些特定部分(比如一个关系或视图)上授予用户所有这些类型的权限
grant <Ptivilege> on <Table> to <sb/role>
revoke <Privilege> on <Table> from <sb/role>
create role <name>
grant <role> to <sb>
如果多个DBA给同一个用户权限,则需要多次收回才行。、
权力依赖链如果断了,下面的人的权力都会被收回。
角色
区分不同的权限群体
create role <>
create role instructor
然后将角色分配给某个人
grant instructor to NM
然后可以授权
grant read on takes to instructor(授权给某个角色,这个角色包含了NM)
权限可以通过角色继承:
create role assistant
grant assistant to instructor 将教师的权限继承给助教
角色链:
create role dean
grant instructor to dean
grant dean to LSC.
拥有转授能力 with grant option
grant select on department to AMY with grant option
revoke select on departmet from AMY, Satoshi cascade(会从头把整个转授链的人的权限都收回)
revoke select on departmet from AMY, Satoshi restrict(会检测是否把权限转手给了别人,如果有转授,就终止收回防止收回崩溃)
CREATE ROLE-GRANT 权限 ON 表 TO role-GRANT role TO user
REVOKE 权限 ON 表 FROM 人..cascade
视图授权
让地理系的老师看不了其他系老师的信息,行级的约束
底层使用的是视图的权限
视图的创建者必须要有在instructor表的权限。

问题一:如果 geo_staff 没有在 instructor 上的 select 权限?
答案:查询依然可以成功执行。
解析:
这正是视图的核心价值 所在------逻辑独立性与权限隔离。
- 机制 :视图充当了一个"安全代理"或"中间人"。
geo_staff用户只需要拥有对视图geo_instructor的SELECT权限(图片中已通过grant select on geo_instructor to geo_staff赋予了该权限)。 - 结果 :当
geo_staff查询视图时,数据库系统会检查他对视图的权限,而不是对底层基表的权限。数据库引擎会代替他去读取底层的instructor表。 - 意义:这就像你(用户)只需要有"前台窗口"的钥匙,就能拿到数据,而不需要拥有"后台仓库"(基表)的钥匙。这防止了用户看到不该看的数据(比如其他系的老师信息)。
问题二:如果视图的创建者没有在 instructor 上的权限?
答案:视图创建失败(或者无法被正确创建)。
解析:
这是数据库的定义时权限检查机制。
- 机制 :在 SQL 中,执行
CREATE VIEW语句的用户(创建者),必须对SELECT语句中涉及的所有底层对象(这里是instructor表)拥有相应的权限(这里是SELECT权限)。 - 结果:如果创建者没有权限,数据库会直接报错,拒绝创建这个视图。因为如果允许没有权限的人创建视图,那就意味着他可以通过视图"间接"窃取数据,这将是一个巨大的安全漏洞。
- 补充 :只有视图创建成功了,才能进行后续的
GRANT授权操作。如果创建者都没权限看instructor表,他就无法定义出这个视图。
总结
- 对用户(geo_staff):不需要基表权限,只需要视图权限即可查询。
- 对创建者:必须先拥有基表权限,才能创建视图。

什么时候必须用外连接而非内连接?需要保留任意一张表的所有元组
自然连接为什么容易出错?自然连接会自动匹配所有同名字段,不管其实际意义是否一致,且串联自然连接同一个属性会产生歧义
Using On如何规避?Using显示声明要匹配的字段,但要求列的名字是相同的。On可以添加不同名但相同意义的匹配。
视图为什么能查不一定能改?视图是虚表,并非实体的表,增删改必须要能转译(要满足四个条件:)
check、unique,foreign、key防止的是什么错误?check------单号业务逻辑的错误(非法字符串、越界)、unique------唯一性约束(邮箱号不能冲突,但是可以为空);FK------防止跨表语义断裂,引用不存在的属性;
grant、revoke、role在团队治理中扮演什么角色?下放、剥夺、创建角色。
1.from子句只有一个数据库的关系(只依赖一张表)
2.select不含任何sum distinct 、聚集函数、表达式,比如增加1000元,如何分配给底层instructor
3.底层隐藏列必须可以设置为null,不然都插不进去(所有没出现在select中的属性允许null)
4.不可以having或groupby子句,底层表和select表必须一一对应!!!
允许插入视图的条件:不变列,只变行
单表 无聚合 无distinct 无groupby
练习题:
select name,title
from student
join takes using (ID)
join course using(course_id)
select name, course_id,sec_id,year
from instructor I join teaches T on (I.ID=T.ID)
select student.name, takes.course_id
from student S left outer join takes T on T.ID=S.ID
select coalsece(S.name, "N/A") AS sname
from student left out join takes
create view cs_student as
select *
from student
where dept_name=''
select name
from cs_student
where
create table instructor(
ID varchar2(5),
name varchar(5) notnull
salary nueri(5,2)
check(salary>29000),
primary key(),
foreign key(deptname)
refernece department
on delete cascade【可改为set null】
)
如果不用cascade会怎么样?
comit rollback
BEGIN;
UPDATE...
COMMIT;
CREATE ROLE-GRANT 权限 ON 表 TO role-GRANT role TO user
REVOKE 权限 ON 表 FROM 人..cascade
启发:如果用了分桶,groupby X那么select的内容要么是X要么是聚集函数count sum
如果有null,就要用count(id) 否则会把null统计进来
create index只能对实表建索引 不能对view建
