中级SQL
1. 连接
什么是连接:将多个表中的元组经过特定方式结合在一起,以便进行特定的查询
为什么使用连接:笛卡尔积会生成大量无意义的元组组合
1.1 NATURAL JOIN
自动基于两个表中同名的属性来匹配元组
1 | select student.name |
relation1 natural join relation2,relation3不等价于relation1 natural join relation2 natural join relation3,因为前者是与relation3的笛卡尔积,后者是与relation3的自然连接
1.2 INNER JOIN
inner join...on <谓词>:设置通用的谓词来明确连接条件
1 | -- 内连接 |
join缺省情况下是内连接inner join
1.3 OUTER JOIN
自然连接和内连接的局限性:仅保留匹配的记录,而丢失其他元组,但有时候我们又希望保留部分不匹配元组
left/right/full outer join...on <谓词>:不仅返回满足连接条件的行,还会返回部分未匹配的行,自动用空值填充缺失的属性
- 左外连接:只保留出现在左边的关系中的元组
- 右外连接:只保留出现在右边的关系中的元组
- 全外连接:保留出现在两个关系中的元组
使用左外连接
使用右外连接
1.4 USING
JOIN USING (<属性列表>):用于指定连接两个表时使用的相同列名,使得查询更加简洁
1 | -- 列出所有被选课程的信息 |
1.5 总结
实际上,连接可以分为连接类型和连接条件,任意的连接类型可以和任意的连接条件进行组合
以下四种方式是等价的
1 | -- 自然连接 |
2. 视图
create view <视图名> as <查询表达式>:视图是虚拟表,不存储数据,每次查询时动态生成结果,目的是用户可以不必重复编写复杂的SQL语句来访问同一个表
普通视图可以看做成是永久性的with语句
1 | -- 创造物理系在2017年秋季开设的所有课程信息视图 |
物化视图(materialized view):是一种特殊类型的视图,它在数据库中存储实际的数据,而不是简单地存储查询定义,同时物化视图需要持续刷新来保持数据的最新状态
如果视图满足下列可更新条件,对视图的更新会反映到基表中
- 简单视图:没有GROUP BY、DISTINCT、ODDERED BY和HAVING等
- 单一表:定义视图时不允许使用连接,嵌套子查询,集合运算
- 没有计算列:没有计算列、表达式和聚集函数
3. 约束
3.1 NOT NULL
非空约束:某些属性的值不允许为空
1 | -- 姓名和预算不允许为空 |
主码始终满足非空约束
3.2 UNIQUE
唯一性约束:关系中没有两个元组在某些属性上的取值相同
1 | -- 同一学期同一建筑同一房间同一时间不允许有两个课程 |
3.3 CHECK
检查约束:指定一个谓词,关系中的每个元组都必须满足这个谓词
1 | -- 学期必须是四个季节之一 |
3.4 REFERENCES
引用约束:确保在一个表中引用另一个表的行时,引用的值在被引用的表中是有效的
1 | -- 系名必须存在于系表中 |
3.5 CASCADE
级联约束:用在外码中,当主表中的记录被删除/更新时,自动删除/更新外表中相关的记录
1 | foreign key (dept_name) references department(dept_name) |
3.6 CONSTRAINT
约束命名:给上述约束起名字,当违反约束时可以根据名称来明确错误类型
1 | -- 给check约束命名为min_salary |
3.7 assertion
断言约束:用于定义跨多个表或行的全局条件,确保数据库中的数据满足特定的规则
1 | -- 用于检查所有学生的总学分是否与他们实际获得的学分一致 |
SQL不提供for all X, P(X)的结构,所以一般采用not exists X that not P(X),即对全部X都有P==不存在X不满足P
4. 数据处理
4.1 日期和时间
数据类型
DATE:存储年月日,YYYY-MM-DDTIME:存储时分秒,HH:MM:SSDATETIME/TIMESTAMP:存储时间戳,YYYY-MM-DD HH:MM:SS
内置函数
CURDATE():返回当前年月日CURTIME():返回当前时分秒NOW():返回当前时间戳
1 | -- 创建一个事件表 |
4.2 类型转换
4.2.1 CAST
cast(expression as type):将表达式e转换为类型t
1 | -- 将字符串 '123' 转换为整数 123 |
4.2.2 FORMAT
format(number, decimal):格式化数字,添加千位分隔符并指定小数位数
1 | -- 返回 '1,234,567.89' |
4.2.3 COALESCE
coalesce(column, value):用于提供默认值或处理空值
1 | -- 显示教师的ID和工资,但是将空工资显示为-1 |
处理后的值必须符合属性数据结构
4.3 DEFAULT
用于插入数据时,指定某些属性的初始值/缺省值
1 | -- 学生的初始学分为0 |
4.4 LOB
- 字符大对象(CLOB):用于存储大量的文本数据
- 二进制大对象(BLOB):用于存储大量的二进制数据,如图像、音频、视频等
1 | book_review clob(10KB) |
4.5 自定义
create type type_name as data_type:自定义一个数据类型
1 | -- 创建美元数据类型并使用 |
create domain domain_name domain_definition:自定义一个域类型
1 | -- 不仅可以设置数据类型,还可以添加约束条件 |
4.6 AUTO_INCREMENT
为主码生成唯一的、递增的值,而不是人为去一个个设置
1 | -- MySQL |
MySQL会为AUTO_INCREMENT设置一个计数器,计数器是单调递增的,即如果删除元组不会导致计数器回退,如果数据库发现当前id已经被占用,则继续递增
5. 授权
5.1 GRANT
grant <权限列表> (<属性列表>) on <对象列表> to <用户/角色列表>;
(属性列表)是可选的,不是所有数据库都支持- 对象可以是表、视图、数据库
- 关键字
all previleges表示授予全部权限 - 关键字
public表示公开,即授权给全部人
1 | -- 给数据库用户Amit授予了在department关系上的选择权限 |
5.2 ROLE
不必给每一个用户都使用相同命令来设置权限,而是先给角色授予权限,再给用户授予角色即可
1 | -- 授予用户权限 |
角色可以授予用户,也可以授予其他角色,用户可以有多重身份
5.3 视图权限
- 如果当前用户希望创建一个视图,必须在视图引用的底层表上至少有选择权限
- 可以给其他用户授予使用视图的权限
- 用户对视图的权限不会自动继承到底层表
1 | -- 创建视图 |
5.4 引用权限
用户必须拥有某个表的引用权限才能在新表中定义对该表的外键约束
1 | -- 允许dasi引用department关系的dept_name属性 |
5.5 转移权限
用户可以不仅赋予它使用的权限,还赋予它授权别人的权利
1 | -- 授予Amit在department上的选择权限,并且允许Amit将该权限授予其他用户 |
5.6 收回权限
restrict是禁止级联收权,如果权限已经转移,则收权失败cascade是允许级联收权,会收回其他用户的权限
1 | -- 非级联 |





