继续SQL的深入学习,涉及到SQL查询的复杂形式、视图定义、事务、完整性约束和权限。
1. join表达式
在之前有讲过natural join,因避免遍历计算笛卡尔积而相比较传统的where子句效率更高;在指定关注的属性时使用join … using …句式,此外,join有个很有用的谓词修饰on,对于内连接(inner join)而言,on的意义等同于where:
select *
from student join takes on student.ID = takes.ID;
等效于
select *
from student, takes
where student.ID = takes.ID;
然而,对于外连接(outer join)则不然。外连接分为左外连接(left outer join)、右外连接(right outer join)和全外连接(full outer join),分别对左表、右表或者两个表在内连接运算中丢弃的项进行补齐,丢失的属性用null替代。默认情况下,natural join就是指的natural inner join,而内连接、左外连接、右外连接、全连接都是可以与natural、using和on进行配合。
2. 视图
从数据库存储数据的数据抽象(Data Abstraction)而言,逻辑层提供的关系因为权限等原因并不能直接被用户使用,一般需要再抽象一层视图层,这个在概述中有过提及。事实上,视图是虚拟的表,即该表并不进行具体存储,而是在每次访问时才去执行相关操作,通过逻辑层获得视图层的表,因此称之为虚表。譬如:
create view physics_fall_2015 as
select course.course_id, sec_id, building, room_number
from course, section
where course.course_id = section.course_id
and course.dept_name = 'Physics'
and section.semester = 'Fall'
and section.year = '2009'
也可以显式的定义视图的属性,如:
create view dept_total_salary(dept_name, total_salary) as
select dept_name, sum(salary)
from instructor
group by dept_name;
然而在大数据量存储,尤其是有些应用需要高频访问某些视图时,需要对视图进行物化,即物化视图(Materialized View),然而SQL标准却没有给出具体物化的方式,各个数据库的实现也各有不同。视图作为一种表(尽管是虚表 virtual relation),可以进行插入、删除、更新操作,但是需要满足一下条件:
- from子句中只有一个表
- select子句中只有表属性的名字,不存在聚合操作和distinct等操作
- 查询并不能还有group by和having子句
3. 事务
事务是完成一个逻辑任务的操作序列,但是这个操作序列被视作一个有机整体,要么都做,要么都不做,即原子性(atomic)。当一个事务做完之后,要么进行commit work,要么进行Rollback work,SQL标准并没有给出明确的要求。
4. 完整性约束
数据库的完整性约束指的是对数据库做出的任何更改都不丧失数据库的一致性。除了在建立表格时候,对数据取值范围的约定外,还有not null、unique、check,以及引用完整性约束等。SQL标准规定的deferrable、assertion特性在具体的数据库实现中支持有限。
5. SQL数据类型和模式
SQL除了支持varchar(n)、char(n)、smallint等类型外,还对时间类型进行支持,如date、time、timestamp等,并且可以根据需要自定义类型,如:
create type Dollars as numeric(8,2) final;
create table department(
dept_name varchar(20),
building varchar(15),
budget Dolloars);
如果是相同种基本类型的,可以使用cast e as t进行类型转换;此外,SQL还提供了建立索引机制,在查找关键码时提高了效率:
create index name_idx on user(ID)
可以使用drop type和alter type更改类型,可以使用create domain增加类型的限制,最为方便的是create table … like …句式:
create table temp_instructor like instructor;
创建的temp_instructor具有与instructor相同的schema。SQL和其它的编程语言一样,也有命名空间(namespace)这么一说,即catalogs、schemas、relations可以确定表格而不引起歧义。
6. 权限
用户对数据库进行增删查改的权利称之为权限(privilege),SQL提供下发(grant)和收回(revoke)权限的机制,如:
grant select on department to Amit;
grant update(budget) on department to Amit;
revoke select on department from Amit;
revoke update(budget) on department from Amit;
而对于引用限制:
grant references(dept_name) on department to Mary;
这使得用户Mary可以根据关系department建立外键dept_name;此外,为了传递派生权限的权限,可以通过with grant option实现:
grant select on department to Amit with grant option;
这样用户Amit除了可以对department进行select操作外,还可以向其他用户分派select权限。然而权限分配存在这样一个问题,即如果某位爷给小弟分配了权限,根据继承关系,当这位爷不干了被revoke了权限后,那位倒霉的小弟同样没了权限,这当然太不开心了,为此,SQL指定了role这么个角色,将权限分配给role,再由role继续分派下去,这样即使某位爷离开后,role依然存在,分配的权限自然也存在,所谓“铁打的营盘,流水的兵”:
create role instructor;
grant select on department to instructor with grant option;
这样就很happy了 :)
真心感觉SQL标准这套规则确实纷繁复杂,难怪并没有数据库进行完全实现。