day39
1.视图
1.视图.png

1 """""" 2 """ 3 '''视图''' 4 1.什么是视图? 5 一个查询语句的结果是一张虚拟表,将这种虚拟表保存下来 6 它就变成了一个视图 7 8 2.为什么要使用视图? 9 当频繁需要用到多张表的连表结果,那你就可以事先生成好视图 10 之后直接调用即可,避免了反复写连表操作的sql语句 11 12 3.如何使用? 13 create view teacher_course as select * from teacher inner join course on teacher.id = course.teacher_id; 14 15 4.视图的特点? 16 1.视图只有表结构,视图中的数据还是来源于原来的表 17 2.不要改动视图表中的数据 18 3.一般情况下不会频繁的使用视图来写业务逻辑(防止资源消耗) 19 20 """
2.触发器

"""""" """ 创建表 CREATE TABLE cmd ( id INT PRIMARY KEY auto_increment, USER CHAR (32), priv CHAR (10), cmd CHAR (64), sub_time datetime, #提交时间 success enum ('yes', 'no') #0代表执行失败 ); CREATE TABLE errlog ( id INT PRIMARY KEY auto_increment, err_cmd CHAR (64), err_time datetime ); 补充:NEW对象指代的就是当前记录 delimiter $$ create trigger tri_after_insert_cmd after insert on cmd for each row begin if NEW.success = 'no' then insert into errlog(err_cmd,err_time) values(NEW.cmd,NEW.sub_time); end if; end $$ delimiter ; delimiter $$ # 只对当前窗口有效 create trigger tri_after_insert_user after insert on user for each row begin insert into user(name,password) values('老子翻车了','123'); end $$ delimiter ; drop trigger tri_before_insert_user; """
2.触发器.png

1 """""" 2 """ 3 ## 触发器 4 5 在满足对某张表数据的增、删、改的情况下,自动触发的功能称之为触发器 6 7 #### 为何要用触发器 8 9 触发器专门针对我们对某一张表数据增insert、删delete、改update的行为,这类行为一旦执行 10 就会触发触发器的执行,即自动运行另外一段sql代码 11 12 错误 触发器 insert 与 SQL 关键字不一致 13 delimiter $$ 14 create trigger tri_before_insert_user before select on userinfo for each row 15 begin 16 select name,password from userinfo; 17 end $$ 18 delimiter ; 19 """ 20 """ 21 触发器: 22 到达某个条件,自动触发 23 24 当你对数据进行 增删改 的情况下 会自动触发触发器的运行 25 26 触发器的分为六种情况: 27 trigger 触发 28 固定语法结构: 29 create trigger 触发器的名字 after/before insert /update/delete on 表名 for each row 30 begin 31 sql语句 32 end 33 34 增前 35 each row 每行 36 delimiter // # 修改结束符 37 可以修改MySQL 默认的结束符(;) 38 只对当前窗口 ,当前库有效 39 40 delimiter $$ 41 create trigger tri_before_insert_user before insert on userinfo for each row 42 begin 43 44 insert into userinfo(name,password) values('hpp',123); 45 end $$ 46 delimiter ; 47 48 增后 49 delimiter $$ 50 create trigger tri_after_insert_user after insert on userinfo for each row 51 begin 52 insert into userinfo(name,password) values('hpp',123); 53 end $$ 54 delimiter ; 55 删前 56 delimiter $$ 57 create trigger tri_bef_del_user before delete on userinfo for each row 58 begin 59 delete from userinfo where name = 'llx'; 60 end $$ 61 delimiter ; 62 删后 63 delimiter $$ 64 create trigger tri_aft_del_user after delete on userinfo for each row 65 begin 66 delete from userinfo where name = 'llx'; 67 end $$ 68 delimiter ; 69 改前 70 delimiter $$ 71 create trigger tri_bef_upd_user before update on userinfo for each row 72 begin 73 update userinfo set name = 'llx' where id =3; 74 end $$ 75 delimiter ; 76 改后 77 delimiter $$ 78 create trigger tri_after_upd_user after update on userinfo for each row 79 begin 80 update userinfo set name = 'llx' where id =3; 81 end $$ 82 delimiter ; 83 84 85 86 """
2.触发器 -增后.png
2.触发器 修改.png
2.触发器 删除.png
修改结束符.png
3.事务
3.事务.png

1 """""" 2 """ 3 事务*** 4 1.事务:包含一大堆SQL语句,要么同时成功,要么一个也别想成功 5 6 例: 7 手拿建行卡去交行ATM给工行转钱 8 9 2.事物的四大特性:ACID: 10 A:原子性 : 11 原子性是指事务是一个不可再分割的工作单位,是一个整体, 12 一大堆SQL语句要么同时成功 ,要么同时失败 13 C:一致性 14 指事务发生前后,数据的总额依然匹配 15 I:隔离性 16 事务执行时,有单独的空间,其他事务无法访问 17 D:持久性 18 当事物完成后,其影响会一直保留,修改需要使用新事物 19 20 3.如何开启事务? 21 开启事务 (start transaction) 22 (执行SQL操作) 23 rollback:回滚 24 commit :提交上面的SQL,让其生效 25 show full tables; 显示全部类型 26 27 start transaction; 28 update user set balance = 1500 where name = 'wsb'; 29 update user set balance = 500 where name = 'egon'; 30 commit; 31 show full tables; 32 33 """
4.存储过程

1 import pymysql 2 3 conn = pymysql.connect( 4 host = '127.0.0.1', 5 port = 3306, 6 user = 'root', 7 password = 'llx20190411', 8 database = 'day38', 9 charset = 'utf8', 10 autocommit = True 11 ) 12 cursor = conn.cursor(pymysql.cursors.DictCursor) 13 14 # call t5() mysql 中调用 15 # callproc() pymyssql 中调用 16 17 cursor.callproc('t5',(2,6,11)) 18 19 """ 20 @_t5_0 = 2 21 @_t5_1 = 6 22 @_t5_2 = 11 23 24 @_存储过程名_索引值 25 """ 26 cursor.execute('select @_t5_0') 27 print(cursor.fetchall()) 28 cursor.execute('select @_t5_1') 29 print(cursor.fetchall()) 30 cursor.execute('select @_t5_2') 31 print(cursor.fetchall()) 32 33 """ 34 值: 35 [{'@_t5_0': 2}] 36 [{'@_t5_1': 6}] 37 [{'@_t5_2': 0}] 38 """

1 """""" 2 """ 3 存储过程: 4 1.定义 5 就类似于Python的自定义函数 6 7 内部封装了操作数据库的SQL语句,后续想要实现相应的操作 8 只需要调用存储过程即可 9 10 2.语法结构: 11 delimiter $$ 12 create procedure t1() 13 begin 14 select * from user; 15 end $$ 16 delimiter; 17 例: 18 mysql> delimiter $$ 19 mysql> create procedure t1() 20 -> begin 21 -> select * from user; 22 -> end $$ 23 Query OK, 0 rows affected (0.13 sec) 24 25 mysql> delimiter; 26 27 28 3.# 带参数的 29 delimiter $$ 30 create procedure t3( 31 in m int, 32 # 不能被返回出去 33 # in表示这个参数必须只能是传入不能被返回出去 34 in n int, 35 out res int, # 可以被返回 36 #inout xxx int, 37 # 既可以进又可以出 38 # out表示这个参数可以被返回出去,还有一个inout表示即可以传入也可以被返回出去 39 inout xxx int 40 ) 41 begin 42 select * from user; 43 end $$ 44 delimiter; 45 46 例: 47 -> c 48 mysql> delimiter $$ 49 mysql> create procedure t3( 50 -> in m int, # 不能被返回出去 51 -> in n int, 52 -> out res int, # 可以被返回 53 -> #inout xxx int, # 既可以进又可以出 54 -> inout xxx int 55 -> ) 56 -> begin 57 -> select * from user; 58 -> end $$ 59 Query OK, 0 rows affected (0.04 sec) 60 61 mysql> delimiter; 62 -> c 63 mysql> 64 65 66 67 4.赋值变量名,调用存储空间 68 delimiter $$ 69 create procedure t5( 70 in m int, 71 # in 表示 这个参数必须只是传入不能不凡返回去 72 in n int, 73 out res int # out 表示 这个参数 可以被返回去,还有一个inout表示既可以传入也可以被返回去 74 ) 75 76 begin 77 select tname from teacher where tid > m and tid < n; 78 set res = 0 ; 79 # 就类似于一个标志位用来标识存储其是否执行成功 80 end $$ 81 delimiter ; 82 83 set @res = 10 84 # 设置一个变量与值的绑定关系 85 86 调用存储过程 将变量@res传入 87 call t4(1,2,10) 88 89 之后通过 90 select @res 91 查看存储过程执行完成后的返回结果 92 93 ps: 94 存储过程在哪个库下面定义 95 就只能在哪个库下面使用 96 97 98 """ 99 100 """ 101 例: 102 mysql> delimiter $$ 103 mysql> create procedure t5( 104 -> in m int, 105 -> # in 表示 这个参数必须只是传入不能不凡返回去 106 -> in n int, 107 -> out res int # out 表示 这个参数 可以被返回去,还有一个inout表示既可以传入也可以被返回去 108 -> ) 109 -> 110 -> begin 111 -> select tname from teacher where tid > m and tid < n; 112 -> set res = 0 ; 113 -> # 就类似于一个标志位用来标识存储其是否执行成功 114 -> end $$ 115 Query OK, 0 rows affected (0.00 sec) 116 117 mysql> delimiter ; 118 mysql> 119 mysql> call t5(1,5,10) 120 -> ; 121 ERROR 1414 (42000): OUT or INOUT argument 3 for routine day38.t5 is not a variable or NEW pseudo-variable in BEFORE trigger 122 mysql> set @res = 10; 123 Query OK, 0 rows affected (0.00 sec) 124 125 mysql> select @res; 126 +------+ 127 | @res | 128 +------+ 129 | 10 | 130 +------+ 131 1 row in set (0.00 sec) 132 133 mysql> 134 135 """ 136 """ 137 例 138 mysql> 139 mysql> delimiter // 140 mysql> create PROCEDURE p5( 141 -> OUT p_return_code tinyint 142 -> ) 143 -> BEGIN 144 -> DECLARE exit handler for sqlexception 145 -> BEGIN 146 -> -- ERROR 147 -> set p_return_code = 1; 148 -> rollback; 149 -> END; 150 -> 151 -> 152 -> DECLARE exit handler for sqlwarning 153 -> BEGIN 154 -> -- WARNING 155 -> set p_return_code = 2; 156 -> rollback; 157 -> END; 158 -> 159 -> START TRANSACTION; 160 -> update user set balance=900 where id =1; 161 -> update user123 set balance=1010 where id = 2; 162 -> update user set balance=1090 where id =3; 163 -> COMMIT; 164 -> 165 -> -- SUCCESS 166 -> set p_return_code = 0; #0代表执行成功 167 -> 168 -> 169 -> END // 170 Query OK, 0 rows affected (0.04 sec) 171 172 mysql> delimiter ; 173 174 175 176 """

1 """""" 2 """ 3 函数:(内置函数)--bbs重点讲 4 注意与存储过程的区别,mysql内置的函数只能在sql语句中使用! 5 6 参考博客:<http://www.cnblogs.com/linhaifeng/articles/7495918.html#_label2> 7 """ 8 """ 9 例: 10 11 mysql> delimiter ; 12 mysql> CREATE TABLE blog ( 13 -> id INT PRIMARY KEY auto_increment, 14 -> NAME CHAR (32), 15 -> sub_time datetime 16 -> ); 17 Query OK, 0 rows affected (0.27 sec) 18 19 mysql> 20 mysql> INSERT INTO blog (NAME, sub_time) 21 -> VALUES 22 -> ('第1篇','2015-03-01 11:31:21'), 23 -> ('第2篇','2015-03-11 16:31:21'), 24 -> ('第3篇','2016-07-01 10:21:31'), 25 -> ('第4篇','2016-07-22 09:23:21'), 26 -> ('第5篇','2016-07-23 10:11:11'), 27 -> ('第6篇','2016-07-25 11:21:31'), 28 -> ('第7篇','2017-03-01 15:33:21'), 29 -> ('第8篇','2017-03-01 17:32:21'), 30 -> ('第9篇','2017-03-01 18:31:21'); 31 Query OK, 9 rows affected (0.02 sec) 32 Records: 9 Duplicates: 0 Warnings: 0 33 34 mysql> 35 mysql> select date_format(sub_time,'%Y-%m'),count(id) from blog group by date_format(sub_time,'%Y-%m'); 36 +-------------------------------+-----------+ 37 | date_format(sub_time,'%Y-%m') | count(id) | 38 +-------------------------------+-----------+ 39 | 2015-03 | 2 | 40 | 2016-07 | 4 | 41 | 2017-03 | 3 | 42 +-------------------------------+-----------+ 43 3 rows in set (0.13 sec) 44 45 mysql> 46 47 48 # 自定义打印格式 49 select date_format(sub_time,'%Y-%m'),count(id) from blog group by date_format(sub_time,'%Y-%m'); 50 """

1 """""" 2 """ 3 流程控制的两种? 4 if 5 while 6 7 """ 8 """ 9 if: 10 # if条件语句 11 delimiter // 12 CREATE PROCEDURE proc_if () 13 BEGIN 14 15 declare i int default 0; 16 if i = 1 THEN 17 SELECT 1; 18 ELSEIF i = 2 THEN 19 SELECT 2; 20 ELSE 21 SELECT 7; 22 END IF; 23 24 END // 25 delimiter ; 26 27 """ 28 """ 29 while: 30 31 delimiter // 32 CREATE PROCEDURE proc_while () 33 BEGIN 34 35 DECLARE num INT ; 36 SET num = 0 ; 37 WHILE num < 10 DO 38 SELECT 39 num ; 40 SET num = num + 1 ; 41 END WHILE ; 42 43 END // 44 delimiter ; 45 """
7.b+树.png

1 """""" 2 """ 3 索引与慢查询索引: 4 5 知识回顾: 6 数据都是存在硬盘上的,那查询数据不可避免的需要进行IO操作 7 8 *索引: 9 在MySQL中也叫做“键”, 10 是存储引擎用于快速找到记录的一种数据结构。* 11 相当于书的目录. 12 13 三种索引关键字 14 - primary key 主键索引 15 - unique key 唯一索引 16 - index key 普通索引 17 18 ps: 19 foreign key 外键 (关联) 20 注意foreign key不是用来加速查询用的,不在我们研究范围之内, 21 22 上面三种key前两种除了有加速查询的效果之外 23 还有额外的约束条件 24 ( 25 primary key:非空且唯一, 26 unique key:唯一 27 ), 28 而index key没有任何约束功能只会帮你加速查询 29 30 索引详解; 31 索引就是一种数据结构, 32 类似于书的目录。 33 意味着以后再查数据应该先找目录再找数据, 34 而不是用翻页的方式查询数据 35 36 索引的本质 37 **本质都是: 38 通过不断地缩小想要获取数据的范围来筛选出最终想要的结果, 39 同时把随机的事件变成顺序的事件, 40 也就是说,有了这种索引机制, 41 我们可以总是用同一种查找方式来锁定数据。** 42 43 **索引的影响:** 44 45 - 1.在表中有大量数据的前提下,创建索引速度会很慢 46 - 2.在索引创建完毕后,对表的查询性能会大幅度提升,但是写的性能会降低 47 """ 48 """ 49 了解 50 b+树 51 52 只有叶子结点存放真实数据,根和树枝节点存的仅仅是虚拟数据 53 54 查询次数由树的层级决定,层级越低次数越少 55 56 一个磁盘块儿的大小是一定的, 57 那也就意味着能存的数据量是一定的。 58 如何保证树的层级最低呢? 59 一个磁盘块儿存放占用空间比较小的数据项 60 61 思考我们应该给我们一张表里面的什么字段字段建立索引能够降低树的层级高度>>> 主键id字段 62 63 **聚集索引(primary key)** 64 65 聚集索引其实指的就是表的主键, 66 innodb引擎规定一张表中必须要有主键。先来回顾一下存储引擎。 67 68 myisam在建表的时候对应到硬盘有几个文件(三个)? 69 表结构 ,数据,索引 70 71 innodb在建表的时候对应到硬盘有几个文件(两个)? 72 表结构 表数据(包含索引) 73 74 frm文件只存放表结构,不可能放索引,也就意味着innodb的索引跟数据都放在idb表数据文件中。 75 76 **特点:**叶子结点放的一条条完整的记录 77 78 辅助索引(unique,index) 79 80 辅助索引: 81 查询数据的时候不可能都是用id作为筛选条件, 82 也可能会用name,password等字段信息, 83 那么这个时候就无法利用到聚集索引的加速查询效果。 84 就需要给其他字段建立索引,这些索引就叫辅助索引 85 86 **特点: 87 **叶子结点存放的是辅助索引字段对应的那条记录的主键的值(比如:按照name字段创建索引, 88 那么叶子节点存放的是:{name对应的值:name所在的那条记录的主键值}) 89 90 select name from user where name='jason'; 91 92 上述语句叫覆盖索引:只在辅助索引的叶子节点中就已经找到了所有我们想要的数据 93 94 select age from user where name='jason'; 95 96 上述语句叫非覆盖索引,虽然查询的时候命中了索引字段name,但是要查的是age字段,所以还需要利用主键才去查找 97 98 99 测试索引 100 101 **准备** 102 103 #1. 准备表 104 create table s1( 105 id int, 106 name varchar(20), 107 gender char(6), 108 email varchar(50) 109 ); 110 111 #2. 创建存储过程,实现批量插入记录 112 delimiter $$ #声明存储过程的结束符号为$$ 113 create procedure auto_insert1() 114 BEGIN 115 declare i int default 1; 116 while(i<3000000)do 117 insert into s1 values(i,'jason','male',concat('jason',i,'@oldboy')); 118 set i=i+1; 119 end while; 120 END$$ #$$结束 121 delimiter ; #重新声明 分号为结束符号 122 123 #3. 查看存储过程 124 show create procedure auto_insert1G 125 126 #4. 调用存储过程 127 call auto_insert1(); 128 129 130 # 表没有任何索引的情况下 131 select * from s1 where id=30000; 132 # 避免打印带来的时间损耗 133 select count(id) from s1 where id = 30000; 134 select count(id) from s1 where id = 1; 135 136 # 给id做一个主键 137 alter table s1 add primary key(id); # 速度很慢 138 139 select count(id) from s1 where id = 1; # 速度相较于未建索引之前两者差着数量级 140 select count(id) from s1 where name = 'jason' # 速度仍然很慢 141 142 143 """ 144 """ 145 范围问题: 146 # 1.并不是加了索引,以后查询的时候按照这个字段速度就一定快 147 select count(id) from s1 where id > 1; # 速度相较于id = 1慢了很多 148 select count(id) from s1 where id >1 and id < 3; 149 select count(id) from s1 where id > 1 and id < 10000; 150 select count(id) from s1 where id != 3; 151 152 alter table s1 drop primary key; # 删除主键 单独再来研究name字段 153 select count(id) from s1 where name = 'jason'; # 又慢了 154 155 # 创建 索引 156 create index idx_name on s1(name); # 给s1表的name字段创建索引 157 select count(id) from s1 where name = 'jason' # 仍然很慢!!! 158 """ 159 """ 160 b+树的原理: 161 数据需要区分度比较高,而我们这张表全是jason, 162 根本无法区分 163 那这个树其实就建成了“一根棍子” 164 """ 165 """ 166 例: 167 select count(id) from s1 where name = 'xxx'; 168 # 这个会很快,我就是一根棍,第一个不匹配直接不需要再往下走了 169 select count(id) from s1 where name like 'xxx'; 170 select count(id) from s1 where name like 'xxx%'; 171 select count(id) from s1 where name like '%xxx'; # 慢 最左匹配特性 172 173 # 区分度低的字段不能建索引 174 drop index idx_name on s1; 175 176 # 给id字段建普通的索引 177 create index idx_id on s1(id); 178 select count(id) from s1 where id = 3; # 快了 179 select count(id) from s1 where id*12 = 3; # 慢了 索引的字段一定不要参与计算 180 181 drop index idx_id on s1; 182 select count(id) from s1 where name='jason' and gender = 'male' and id = 3 and email = 'xxx'; 183 # 针对上面这种连续多个and的操作,mysql会从左到右先找区分度比较高的索引字段,先将整体范围降下来再去比较其他条件 184 create index idx_name on s1(name); 185 select count(id) from s1 where name='jason' and gender = 'male' and id = 3 and email = 'xxx'; # 并没有加速 186 187 drop index idx_name on s1; 188 # 给name,gender这种区分度不高的字段加上索引并不难加快查询速度 189 190 create index idx_id on s1(id); 191 select count(id) from s1 where name='jason' and gender = 'male' and id = 3 and email = 'xxx'; # 快了 先通过id已经讲数据快速锁定成了一条了 192 select count(id) from s1 where name='jason' and gender = 'male' and id > 3 and email = 'xxx'; # 慢了 基于id查出来的数据仍然很多,然后还要去比较其他字段 193 194 drop index idx_id on s1 195 196 create index idx_email on s1(email); 197 select count(id) from s1 where name='jason' and gender = 'male' and id > 3 and email = 'xxx'; # 快 通过email字段一剑封喉 198 ``` 199 200 联合索引 201 202 select count(id) from s1 where name='jason' and gender = 'male' and id > 3 and email = 'xxx'; 203 # 如果上述四个字段区分度都很高,那给谁建都能加速查询 204 # 给email加然而不用email字段 205 select count(id) from s1 where name='jason' and gender = 'male' and id > 3; 206 # 给name加然而不用name字段 207 select count(id) from s1 where gender = 'male' and id > 3; 208 # 给gender加然而不用gender字段 209 select count(id) from s1 where id > 3; 210 211 # 带来的问题是所有的字段都建了索引然而都没有用到,还需要花费四次建立的时间 212 create index idx_all on s1(email,name,gender,id); # 最左匹配原则,区分度高的往左放 213 select count(id) from s1 where name='jason' and gender = 'male' and id > 3 and email = 'xxx'; # 速度变快 214 ``` 215 216 总结: 217 上面这些操作,你感兴趣可以敲一敲,不感兴趣你就可以不用敲了,权当看个乐呵。理论掌握了就行了 218 219 慢查询日志 220 221 设定一个时间检测所有超出改时间的sql语句,然后针对性的进行优化! 222 """