《数据库系统概念(第6版)》读书笔记——第5章:中级SQL

中级SQL

标签(空格分隔):数据库


复杂的SQL查询:连接

典型的连接表达式

1.连接表达式
    1.  select * from student join takes using(ID)
    2.  select * from student join takes on student.ID = takes.ID
    3.  select * from student natural join takes 
    4.  select * from student,takes where student.ID = takes.ID
    (一般不把where子句作为连接条件)
    分析:
    1.  查询结果1和3等价,2和4等价
    2.  2,4查询结果中ID属性出现两次,1,3只出现一次

on和where在连接中的不同表现

同:
    1.  使用方法:后面跟谓词
    2.  查询结果:相同的属性出现两次
异:
    3.  在外连接中两者表现不同
        1)select * from student left outer join takes on student.ID = takes.ID
        2)select * from student left outer join takes on true where student.ID = takes.ID
        上述两条SQL语句的查询结果不同.只有语句1才会保留student关系中不匹配的元祖.记住:on子句是外连接声明的一部分.作为连接条件和连接类型一起构成了连接表达式.而where子句是在连接结果中筛选满足其谓词的元祖.
    4.  用途:
        on子句作为连接条件,是外连接声明的一部分.where子句作为筛选条件。
        因此,我们常常在on子句中指定连接条件,并在where子句中指明其余的条件,这样的SQL更清晰易懂。

什么是内连接?

默认连接。使用inner join显式声明内连接
不保留两个关系中的任何元祖,严格按照连接条件筛选

什么是外连接?

1. 左外连接(left outer join)

只保留出现在左外连接运算之前(左边)的关系中的元祖

2. 右外连接(right outer join)

只保留出现在右外连接运算之后(右边)的关系中的元祖

3. 全外连接(full outer join)

保留出现在两个关系中的元祖

总结: 连接类型与连接条件(4 * 3)

连接类型

 1. inner join
 2. left outer join
 3. right outer join
 4. full outer join

连接条件

1. natural
2. on 
3. using 

补充: 实现连接效果的另一种手段

-- 相关子查询 + 集合并运算 
select * from student natural full outer join takes
/* can be rewritten as follows */
    select * from student natural join takes
union
    select ID, name, dept name, tot cred, NULL, NULL, NULL, NULL, NULL
    from student S1
    where not exists 
        (select ID from takes T1 where T1.id = S1.id)
union
    select ID, NULL, NULL, NULL, course id, section id, semester, year, grade
    from takes T1
    where not exists
        (select ID from student S1 whereT1.id = S1.id)

视图

1. 需求:为什么要有视图?

没有视图的弊:

我们在逻辑模型层的任何操作所导致的变化都会被映射到数据库底层,引起底层数据的变化。

有了视图的利:

1. 安全性:
让所有用户都看到整个逻辑模型(数据表)是不合适的。出于安全考虑,需要向用户隐藏特定的数据,比如:工资
2. 个性化:
用户希望能创建符合其要求的个性化的关系集合。
例如:教务处希望有一个“各个系每年的秋季学期所开设的课程列表”。这样的关系集合在逻辑模型层并不存在,需要用户创建。如果没有视图,意味着每次使用时,都要手动SQL查询,及其不方便。而有了视图,可以“一次定义,终身使用”。

2. 使用:视图定义与使用

视图定义

0. 概念
    虚关系:通过SQL查询定义,在概念上包含查询的结果
    视图:不是逻辑模型的一部分,但作为“虚关系”对用户可见的关系
1. 标准视图定义
create view v as 
其中:
    :任何合法的查询表达式
     v:视图别名

2. 显式指定视图的属性名
create view dept_total_salary(dept_name, total_salary) as 
    select dept_name, sum(salary)
    from instrctor
    group by dept_name;

在SQL查询中使用视图

在SQL查询中,视图可以出现在关系名可以出现的任何地方。

3. 深入:视图的存储,更新与维护

视图存储

当我们定义一个视图时,数据库系统存储视图的定义本身,而不存储定义该视图的查询表达式的计算结果。一旦视图出现在查询中,它就会被已存储的查询表达式所替代。因此,无论我们何时执行这个查询,视图关系都被重新计算。

物化视图

0. 概念
某些数据库存储视图关系(即查询表达式的计算结果),但保证:一旦用于定义视图的实际关系改变,视图也随之改变
1. 必要手段:视图维护
保持物化视图一直在最新状态的过程。
不同的数据库有不同的视图维护策略
    1. 周期性视图维护(可能访问到旧数据)
    2. 视图被访问时,才执行视图维护
    3. 数据库管理员自控制
2. 应用场景
    1. 频繁使用视图的应用
    2. 需要快速响应 基于大关系上聚集计算的特定查询
3. 利弊
在某些情况下,聚集结果要比定义视图的大关系小得多,所以,利用物化视图来回答查询就快得多,它避免了读取大的底层关系。
当然,这种好处需要权衡存储代价和更新开销。

视图更新

1.  为什么一般不允许对视图关系进行修改?
    1.  不满足数据表的定义(主要是完整性约束)
    2.  “伪更新操作”
        视图:
            create view instructor_info as 
                select ID, name, building 
                from instructor, building
                where instructor.dept_name = building.dept_name;
        操作:
            insert into instructor_info
                values(‘69987’, 'White', 'Taylor');
        问题:
        这个更新并没有产生所需的结果。
        因为新插入的元祖并不满足视图关系的选择条件,故仍然不包含元祖
2.  什么情况下我们可以对视图关系进行修改?
可更新(updatable)的视图
    1.  from子句中只有一个数据库关系
    2.  select子句中只包含关系的属性名,不包含任何表达式,聚集或者distinct声明
    3.  任何没有出现在select子句中的属性可以取空值(即这些属性上没有not null约束,也不构成主码的一部分)
    4.  查询中不含有group by 或 having子句
3.  修改视图会带来哪些影响?
    即便是向可更新的视图进行插入操作,新插入的元祖可能仍不会被包含在视图中,因为其不满足视图关系的选择条件
    (在视图定义的末尾加上with check option子句加以解决)

完整性约束

域约束

1)not null:
    禁止在该属性上插入空值;主码默认not null
2)unique:
    unique(Pi, Pj...Pz);     //指定一个候选码
3)check()
    check(budget > 0);

参照完整性约束

1.  参照完整性
    一个关系中给定属性集上的取值也在另一关系的特定属性集的取值中出现
2.  外码约束
    令关系r1和r2的属性集分别为R1和R2,主码分别为K1和K2。如果要求对r2中任意元祖t2,均存在r1中元祖t1使得t1.K1=t2.a,我们称R2的子集a为参照关系r1中k1的外码
3.  参照完整性约束
    上述外码约束中的K1不必为主码(r1中可能有不止一个元素在K1取值相同)(一般要求K1为候选码)

如何处理破坏参照完整性约束的操作

一般数据库系统拒绝执行。
特殊处理:
        create table prereq
        (course id varchar(8),
        prereq id varchar(8),
        primary key (course id, prereq id),
        foreign key (course id) references course
            on delete cascade,
        foreign key (prereq id) references course
            on delete set null); 

分析说明:

    1)on delete on cascsde     '级联删除'
    如果删除course中的元祖导致此参照完整性约束被违反,那么删除并不会被拒绝,而是对prereq关系作“级联”删除,即删除参照了被删除系的元祖。更新同理。

    2)on delete set null       '置属性为null'
    如果删除course中的元祖导致此参照完整性约束被违反,那么删除并不会被拒绝,而是将prereq关系的prereq_id属性设置为NULL,即将参照了被删除系的元祖的某个属性置空。更新同理。

    3)深入
    如果存在涉及到多个关系的外码依赖链,则在链的一段所做的删除、更新可能传到整个链。如果一个级联更新或删除导致的对约束的违反不能通过进一步的级联操作解决,则系统终止该事务。该事务所做的所有改变与级联动作被撤销。

事务中对完整性约束的违反

考虑情景:
    事务可能会暂时违反约束,但后面某一步就会消除该违反
解决方案:
    initially deferred子句,在事务结束时检查约束,而不是默认的立即检查

复杂check条件

check(

); //SQL标准约定,谓词P可以是包含子查询的任意谓词 例如: check(time_slot_id in (select time_slot_id from time_slot)); 检测开销: 本表和check中关联的表一旦更新时都要检测,因此开销较大,普遍不支持。

断言

概念:
    一个断言就是一个谓词,它表达了我们总希望数据库满足的一个条件
类型:
    1)*域约束
    2)*参照完整性约束
    3)更复杂的约束。例如:对于student关系中每个元祖,它在属性total_cred
    上的取值必须等于该生所成功修完课程的学分总和
语句:
    create assertion  check ;
代价:
    检测和维护断言的开销很大,因此普遍不支持。

复杂约束代码示例:

create assertion credits_earned_constraint check
    (not exists 
    (select ID from student where tot_cred 
        < > 
    (select sum(credits) from takes natural join course 
        where grade is not null and grade <> 'F')));

SQL的数据类型和模式

日期和时间类型

- date:形如'2001-04-25'
- time:形如'09:30:00';time(p),指定小数点后的数字位数,默认为0;time with timezone,把时区信息连同时间一同存储
- timestamp:形如'2001-04-2509:30:00.45';timestamp(p),默认6位;timestamp with timezone,存储时区信息;

常用的时间函数(略)

创建索引

create index studentID_index on student(ID);

大对象类型

clob:字符数据的大对象数据类型
    book_review clob (10KB)
blob:二进制数据的大对象数据类型
    image blob(10MB)
    moive blob(2GB)
若查询结果中包含大对象(MB级),把大对象放入内存中,非常低效。应用通常用一个SQL查询检索一个大对象的“定位器”,然后在宿主语言中用定位器来操纵大对象。

用户定义类型

create table的拓展

create table table_a like table_b;//创建模式相同的表
create table table_a as     //把查询的结果存储成一个新表 
    (select *
     from instructor
     where dept_name = ''Music)
with data;

目录,模式与环境

  • 目录->模式(关系,视图)
  • 每个用户有默认的目录和模式
  • 唯一表示一个关系:catelog4.schama5.course

授权

4种基本权限

select/delete/update/insert(后两者可以指定属性)
all privileges(一个创建了新关系的用户自动被授予该关系上的所有权限)

权限作用的数据对象

数据部分: 属性,关系,视图(不允许对一个关系的指定元祖授权)
数据模式: 允许创建/删除/修改关系

语句

--授权
grant <权限列表>
on <数据对象>
to <用户/角色列表>

--回收权限
revoke <权限列表>
on <数据对象>
from <用户/角色列表>

为什么要有角色?

如果没有角色?
    每次单独为新用户授予权限
有了角色?
    只需为新用户授予角色 
语句?

角色的权限?

角色链:
    角色可以拥有角色


(public: 系统所有的当前用户和将来用户)

你可能感兴趣的:(数据库)