数据库-子查询、关联查询 和 TCL 语言
标题目录
- 子查询
- 使用场景
- 子查询分类
- 在 DQL 中使用子查询
- 单行单列子查询
- 多行单列子查询
- 在 DML 中使用子查询
- 在 DDL 中使用子查询
- 视图
- 关联查询
- 关联关系的分类
- 连接条件
- 主外键关联
- N 表关联查询
- 关联查询中使用聚合函数
- TCL 语言
- 事务的特性(ACID)
- 在事务中控制DML操作
子查询
- 子查询:SubQuery
- 嵌套在其他SQL语句中的一条DQL语句被称为子查询
使用场景
- 在DQL语句中使用
- 可以在SELECT子句中将子查询结果当作字段使用
- 可以在FROM子句中将子查询的结果当作表使用(视图)
- 可以在WHERE子句中将子查询结果当作过滤条件使用
- 在DML语句中使用
- 将查询结果用于增删改操作
- 在DDL语句中使用
- 可以将子查询结果集当作表创建
- 可以将子查询当作视图创建
子查询分类
- 单行单列子查询
- 结果集只有一个值
- 常用于DQL,DML
- 多行单列子查询
- 结果集有多个值
- 常用于DQL,DML
- 多行多列子查询
- 结果集是一个表
- 常用于DQL和DDL
在 DQL 中使用子查询
单行单列子查询
查看比王老师工资高的老师都有谁
SELECT name,salary
FROM teacher
WHERE salary>(SELECT salary FROM teacher WHERE name='王老师')
查看哪些老师的工资高于平均工资
SELECT name,salary
FROM teacher
WHERE salary>(SELECT AVG(salary) FROM teacher)
多行单列子查询
- 子查询的结果有多个值
- 进行等值判断时要配合 IN 或者 NOT IN 使用
- 如果进行关系运算(>,>=,<,<=)
- >ANY(列表):大于列表里其中之一(>最小值即可)
- <ANY(列表):小于列表里其中之一(<最大值即可)
- >ALL(列表):大于列表中所有值(>最大值)
- <ALL(列表):小于列表中所有值(<最小值)
查看与"张三"和"李四"在同一个班的学生都有谁
SELECT name,class_id
FROM student
WHERE class_id IN(SELECT class_id FROM student WHERE name IN('张三','李四'))
查看比科目2和科目4老师工资都高的老师都有谁
SELECT name,salary
FROM teacher
WHERE salary>ALL(SELECT salary FROM teacher WHERE subject_id IN(2,4))
在 DML 中使用子查询
给与张三负责同一科目的所有老师工资涨500
UPDATE teacher
SET salary=salary+500
WHERE subject_id=(SELECT subject_id FROM teacher where name='张三')
将李四的工资改为与张三一致
UPDATE teacher
SET salary=(SELECT salary FROM teacher WHERE name='张三')
WHERE name='李四';
删除与张三教同一科目的所有老师
DELETE FROM teacher
WHERE subject_id=(SELECT subject_id FROM teacher WHERE name='张三');
在 DDL 中使用子查询
- 可以将一个子查询结果集当做表创建出来
- 语法
- CREATE TABLE 表名
AS
子查询
- CREATE TABLE 表名
创建一张表,表中记录每个科目老师的工资情况
CREATE TABLE t_teacher_salary_info
AS
SELECT subject_id,MIN(salary) min_salary,MAX(salary) max_salary,SUM(salary) sum_salary,AVG(salary) avg_salary
FROM teacher
GROUP BY subject_id
视图
- 视图(VIEW)也被称作虚表,即虚拟的表,是一组数据的逻辑表示
- 视图对应于一条SELECT语句,结果集被赋予一个名字,即视图名字
- 视图本身并不包含任何数据,他只包含映射到基表的一个查询语句,当基表数据发生变化,视图数据也随之变化
视图的作用
- 简化复杂查询
如果需要经常执行某项复杂查询,可以基于这个复杂查询建立视图,此后查询此视图即可 - 限制数据访问
视图本质上就是一条SELECT语句,所以当访问视图时,只能访问到所对应的SELECT语句中涉及到的列,对基表中的其他列起到安全和保密的作用
语法:
- CREATE VIEW 视图名
AS
子查询
创建一个视图,展示老师的信息,隐藏工资等敏感信息
CREATE VIEW v_teacher_info
AS
SELECT id,name,title,gender,age,subject_id
FROM teacher
- 视图可以查看结构
DESC v_teacher_info
- 查看视图数据
SELECT * FROM v_teacher_info
(此时无法查看到老师的敏感数据)
关联查询
- 联合多张表查询数据,意味着查询的结果集中字段来自多张表
- 表与表中的数据会产生对应的关系,这样的关系被称为关联关系
关联关系的分类
- 两张表就可以产生对应的关联关系
- 一对一关系:A表的1条记录只能对应B表的1条记录
- 一对多关系:A表的1条记录可以对应B表的多条记录
- 多对多关系:A表与B表双向都是一对多时就是多对多关系
连接条件
- 连接条件用于关联两张表中数据的对应关系
- 注意事项
- 在关联查询中通常两张表之间要指定连接条件,否则会产生笛卡尔积,这通常是一个无意义的结果集,开销大,除非必要通常要避免
- 连接条件的数量:N 张表关联查询至少要有 N-1 个连接条件
- 语法:
SELECT 表A.字段,表B.字段,…
FROM 表A,表B,…
WHERE 表A与表B的连接条件
AND 过滤条件
查看每个老师和所教科目的名字
SELECT teacher.name,teacher.salary,subject.name
FROM teacher,subject
WHERE teacher.subject_id=subject.id;
查看每个班级的班主任
SELECT class.name,teacher.name
FROM class,teacher
WHERE class.teacher_id=teacher.id;
- SELECT 子句中标注字段来自哪张表时,表名可以使用别名来进行简化
查看每个班级的班主任
SELECT c.name,t.name
FROM class c,teacher t
WHERE c.teacher_id=t.id;
主外键关联
两张表中的记录存在关联关系时,那么就会在在两张表中分别定义主键和外键
- 主键:
- 主键通常是表中的第一个字段,名字一般为 " id "
- 主键的特点:非空且唯一,可以使用主键约束进行定义
- 主键用来标识表中每一条记录
- 外键:
- 外键是用来记录另一张表主键字段值的一个字段
- 设计有外键字段值的表在关联关系中处于关联关系一对多中 " 多 " 的那一方
张三是哪个班的班主任
SELECT t.name,c.name
FROM teacher t,class c
WHERE t.id=c.teacher_id
AND t.name='张三'
查看来自南京的学生都是谁,列出城市名称,学生名字,年龄,性别
SELECT s.name,s.age,s.gender,l.name
FROM student s,location l
WHERE s.location_id=l.id
AND l.name='南京'
N 表关联查询
- N 张表关联查询至少要有 N-1 个连接条件
查看张三所带班级的学生都有谁
SELECT s.name,c.name,t.name
FROM student s,teacher t,class c
WHERE s.class_id=c.id AND c.teacher_id=t.id
AND t.name='张三'
查看1年级1班的同学以及来自的城市
SELECT s.name,c.name,l.name
FROM student s,class c,location l
WHERE s.class_id=c.id AND s.location_id=l.id
AND c.name='1年级1班'
关联查询中使用聚合函数
查看张三所带班级的学生共有多少人
SELECT COUNT(*)
FROM student s,class c,teacher t
WHERE s.class_id=c.id AND c.teacher_id=t.id
AND t.name='张三'
查看教每门课的老师的平均工资
SELECT t.name,su.name,AVG(t.salary)
FROM teacher t,subject su
WHERE t.subject_id=su.id
GROUP BY su.name
TCL 语言
- 事务控制语言(TCL):Transaction Control Language
- 用于保数据库的一致性和完整性
- 语法:
- BEGIN:开始一个事务
- ROLLBACK:回滚本次事务到BEGIN的位置
- COMMIT:提交本次事务,将BEGIN后的所有操作更新到数据库中
事务的特性(ACID)
ACID四大特性是指数据库事务的四个基本特性,分别是原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)
- 原子性(Atomicity):原子性确保事务是一个不可分割的工作单位,事务中的所有操作要么全部完成,要么全部不执行。如果事务在执行过程中发生错误,会被恢复到事务开始前的状态,就像这个事务从来没有执行过一样
- 一致性(Consistency):一致性保证事务的执行将数据库从一个一致的状态转变到另一个一致的状态。这意味着事务开始之前和结束之后,数据库的完整性没有被破坏
- 隔离性(Isolation):隔离性是指当多个事务同时对数据库进行操作时,每个事务都是独立的,一个事务的操作不会影响到其他事务。事务隔离分为不同级别,包括读未提交、读提交、可重复读和串行化
- 持久性(Durability):持久性意味着一旦事务被提交,它对数据库的修改就是永久性的,即使系统发生故障也不会丢失
在事务中控制DML操作
- 启动一个事务
BEGIN
- 执行任意的DML操作
DELETE FROM teacher
WHERE subject_id=(SELECT subject_id FROM teacher WHERE name='张三');
上述操作没有真实删除,只是数据库记录了该操作,但是在本次事务过程中后续所有操作都基于 上述DML效果之后模拟
SELECT * FROM teacher
查询时发现和 ’ 张三 ’ 教同一科的老师都被删除了
- 当实际业务处理完毕后,我们可以根据实际业务处理结果选择是提交事务,还是回滚事务
COMMIT; -- 提交事务,那么BEGIN到COMMIT之间的所有DML操作就真实进行了.
ROLLBACK ; -- 回滚事务,那么BEGIN到COMMIT之间的所有DML操作全部作废.