一、多表查询

1.1 使用子查询(不推荐)

例如:查询妻子时,要求显示其丈夫的内容

  1. select (select husband_name from husband_info where fk_wife_id = w.id) ,wife_name, gender from wife_info as w;

例如:查询丈夫时,要求显示其妻子的内容

select id,husband_name,gender,(select wife_name from wife_info where id = h.fk_wife_id) as wife_name from husband_info as h;

1.2 使用子查询(in)

例如:查询 妻子名称是“小” 开头的,丈夫的信息

select id,husband_name,gender from husband_info where fk_wife_id in (select id from wife_info where wife_name like '小%');

in 的执行流程:
1、先进行子查询
2、将子查询的结果和 外部查询语句 进行 笛卡尔乘积匹配 : 300(内) X 30000(外) = 9000000
3、将匹配后的结果,使用where 去做条件筛选,将匹配的留下,将不匹配的剔除

1.3 使用子查询(exists)

例如:查询 妻子名称是“小” 开头的,丈夫的信息

select id,husband_name,gender from husband_info as h where exists (select w.id from wife_info as w where h.fk_wife_id = w.id and w.wife_name like '小%');

exists 的执行流程:
1、先查询外部的SQL语句,将查询结果,逐一和 子查询的结果集根据条件进行匹配
2、如果匹配上了,就显示外表的数据;如果没匹配上,就不显示外表的数据
3、进入外部的下一条数据进行匹配

1.4 in与exists使用场合

in 比较适合于 内表的数据 比 外表的数据 少的情况下
exists 比较适合于 内表的数据 比 外表的数据 多的情况下
**

1.5 in 和 exists 谁性能最高?(面试题)

1、当内部表 和 外部表 数据量一样,两个几乎差不多
2、当内部表 数据量 大于 外部表时 exists 的性能高于in
3、当内部表 数据量 小于 外部表时 in 的性能高于exists

只需记住:内部表数据少,用in
**

1.6 not in 和 not exists 谁性能更高?(面试题)

任何场合下:not exists 性能都是最高的,原因是:not in 一定是全表检索,而not exist 至少 内部可以使用索引

1.7 union 与 union all (联合查询)(面试题)

该关键字的使用场景: 当多张表的表结构相同,但是数据不相同,用户又需要同时显示多张表的内容时

-- 将2个表的数据,联合到一起,并针对重复数据去重
select id,wife_name from wife_info union select id,wife_name from wife_02_info;
-- 将2个表的数据,联合到一起,不会针对重复数据去重
select id,wife_name from wife_info union all select id,wife_name from wife_02_info;

使用union会对重复数据去重,union all不会去重
**

二、联表查询(重点)

例如:查询 妻子名称是“小” 开头的,丈夫的信息

2.1 外联查

2.1.1 left [outer] join

以左表为基础,进行右表数据匹配,右边有数据则显示数据,右边没有数据,则显示为NULL
29 - Mysql(多表查询、联表查询、视图、触发器、事务) - 图1
当然,一般情况下,都需要添加:数据筛选条件
例如:

select * from husband_info as h left join wife_info as w on h.fk_wife_id = w.id where w.wife_name like '小%';

2.1.2 right [outer] join

以右表为基础,进行左表数据匹配,左边有数据则显示数据,左边没有数据,则显示为NULL
29 - Mysql(多表查询、联表查询、视图、触发器、事务) - 图2
当然,一般情况下,都需要添加:数据筛选条件
例如:

select * from husband_info as h right join wife_info as w on h.fk_wife_id = w.id where w.wife_name like '小%';

2.2 内联查(inner join)

内联查,显示的中间交集的数据
29 - Mysql(多表查询、联表查询、视图、触发器、事务) - 图3
当然,一般情况下,都需要添加:数据筛选条件
例如:

select * from husband_info as h inner join wife_info as w on h.fk_wife_id = w.id where w.wife_name like '小%';

使用最多的是left join | inner join

2.3 简化inner join(最常用)

省略:inner join on 使用where 去做 表之间的连接

select * from husband_info as h,wife_info as w where h.fk_wife_id = w.id and w.wife_name like '小%';

三、视图(常用)

面临更多的表联表,为了简化联表操作,需要使用Mysql中的视图

3.1 视图的概念

视图:就是一张虚拟表,它的所有的数据都是来自于其他表的联合,它不是一张真真的表,因为它没有任何的表文件存在

3.2 视图的创建

连表超过3张表以上,就可以采用 视图!
语法结构:

create view 视图的名字 as select 连表查询内容

举例:

create view v_player_game as select p.id as p_id,p.player_name,g.id as g_id,g.game_name from player_info as p, player_game as pg, game_info as g where p.id = pg.fk_player_id and pg.fk_game_id = g.id

使用:

select game_name,count(*)  from v_player_game  group by game_name;

不能针对视图,去修改,去删除
**

四、触发器(trigger 重点了解)

当数据库中,某一个表的内容发生改变时,需要其他表也同样做出改变时,可以使用它
触发器的应用场合:
1、卖家卖出一件商品之后, 库存量 - 1
2、系统新注册一个用户, 用户统计量 + 1
3、删除妻子时,自动将丈夫也销毁掉

4.1 触发器的类型

新增触发器 在新增数据时,进行触发
修改触发器 在修改数据时,进行触发
删除触发器 在删除数据时,进行触发

4.2 触发器的触发时机

1、在数据变化之前,触发 before
如果在触发器,需要使用数据变化之前的数据,我们可以使用关键字old来获取
2、在数据变化之后,触发 after
如果在触发器,需要使用数据变化之后的数据,我们可以使用关键字new来获取

4.3 触发器的语法

create trigger 触发器的名字 触发的时机 触发器的类型 on 作用在哪张表
for each row begin
    -- 触发的内容
end;

举例(1):

create trigger trgger_wife_delete before delete on wife_info 
for each row BEGIN
    delete from husband_info where fk_wife_id = old.id;
end;

举例(2):

create trigger trgger_user_info_new after insert on user_info 
for each row BEGIN
    update user_count set nums = nums + 1 where id = '1';
end;

鸡肋:高手认为这个东西很不错,菜鸟就 会莫名其妙的发现数据被修改,被删除了!!!

五、事务(重点)

事务: 一段具有明确开始和结束标记的 并且执行顺序是有序的一个过程

事务举例: 1天的生活 :7:00 起床 7:30 出门 —> 9:20 上课 —> 12:20 吃饭
—> 2:00 上课 —> 6:00 吃饭 —> 6.40 上晚自习 —> 8:30 放学 —> 10:00 到家
—> 12:00 上床 —> 2:00 看手机

出生 —> 3岁(幼儿园) —> 6岁(小学) —> 12岁(初中)—>15(高中)—> 18(上大学) —> 23(大学毕业,走向社会,被社会毒打) —> 27(结婚) —> 29(养小孩) —>
55岁(退休,带小孩) —> 死亡

张三给李四转钱 5000元
1、张三查账 余额是否 > 5000
2、从张三的卡中,扣除5000
3、将5000元,添加到李四的账号中
4、李四查账,看是否收到5000元

从页面发起一个请求,也是一个完整的事务!

5.1 事务的4个特性(ACID)

原子性atomicity:
事务是一个完整的个体,不能再分 对于数据库的事务来讲:就是指事务 是完整的,要么统一成功,要么统一失败
一致性consistency:
在事务处理的过程中,数据必须要保证一致性,也就是不能出错。初中:能量守恒
隔离性isolation:
事务与事务之间是相互隔离的,互不干扰的。
持久性durability:
事务一旦确认,那么它的结果就应该持久化到硬盘中,并且同一事务不能再次对它进行修改。

5.2 事务的处理方式

确认事务 commit
回滚事务 rollback

5.3 MySQL 中如何操作事务(了解)

29 - Mysql(多表查询、联表查询、视图、触发器、事务) - 图4

5.4 事务的隔离级别

多个事务,可能操作同一批数据,为了保证该数据的一致性问题,数据库同样会针对数据进行上锁
29 - Mysql(多表查询、联表查询、视图、触发器、事务) - 图5
1、可串行化(serializable)
将事务按照排队的方式,依次去操作数据,同一时刻只有一个事务可以操作它。
这种隔离级别:数据的一致性最好,它一定能保证数据是准确的
但是:它的性能也是最低的
2、可重复读(repeatable-read)
这隔离级别,仅次于可串行化,它此时就允许少量的事务,同一时刻操作相同的数据
性能上有所提升,但是:数据的一致性上,稍微有所下降
它会造成一种错觉:幻读
幻读:A事务在本次事务中,对自己未操作过的数据多次读取,第一次读取时,记录不存在,第二次读取时候,记录出现了。(insert)
即:(读取了提交的新事物,insert)
A 先查询一帮数据,并且针对这一大帮做了修改,或删除。B在A修改,或删除之后,他也修改了其中的某一条数据,A再次查询数据库时,将会有一种幻象,感觉他自己没修改完,或删除完
3、读已提交(read-committed)
这隔离级别,又比可重复读低一些,它此时就允许大量的事务,同一时刻操作相同的数据,
性能上有了进一步的提升,但是:数据的一致性上,造成的问题更大
它会造成一种错误:不可重复读
不可重复读:A事务在本次事务中,对自己未操作过的数据多次读取,出现了数据不一致或记录不存在的情况。
即:(读取了提交的新事物,update,delete)
举例:你和你女朋友 2个人 公用1张卡,卡里有1000元钱, 你现在请你的朋友吃饭,在你吃饭期间,你女朋友买个一个包花费了800元,等你吃完饭需要结账时:发现卡里只有200元,你可能就不够了,你就尴尬了,你就没法再做任何处理了……
4、读未提交(read-uncommitted)
它的隔离级别最低,它就相当于没有上锁,同一时刻所有的事务都可以操作相同的数据,
性能最高,但是一致性最差,造成的问题最严重
它会造成一种错误:脏读
脏读: A事务还未提交,B事务读取到了A事务中的数据(破坏了隔离性)
即:(读取了未提交的新事物,然后被回滚了)
举例:你有一张银行卡,银行卡中突然多了500W , 你就承诺 给你所有的朋友借钱(打了包票),然后又莫名其妙的500W又消失了,现在问你,你该咋办?
你拿着数据库可能 回滚的数据,在做业务,这是最危险的!!!

当然:4种隔离级别:可串行化 读未提交 几乎没有人使用,使用最多的是:
可重复读

六、InnoDB 与 MyIsam的区别(面试题)

存储引擎:就类似于游戏系统中的游戏引擎,它是整个RDBMS中最核心的东西,它决定了数据如何存储,如何获取,如何控制事务,如何控制外键 等一系列的功能
在MySQL中使用最多的是:InnoDB MyIsam
1、InnoDB 是MySQL 默认使用一种存储引擎,表的存储上,它是将一张表划分为2个文件:XXX.frm (表的表结构文件) XXX.ibd (数据和索引文件)
MyIsam 表的存储上,它是将一张表划分为3个文件:XXX.frm (表的表结构文件) XXX.MYD (数据文件) XXX.MYI (索引文件)
2、InnoDB 支持数据库的事务,而MyIsam 不支持数据库的事务
3、MyIsam 在做CRUD时,性能远高于 InnoDB
4、InnoDB 支持外键约束,但是MyIsam 连外键约束都不支持