mysql视图、事务、触发器、索引
视图
什么是视图 ?
一个查询语句的结果是一张虚拟表,将这种虚拟表保存下来,它就变成了一个视图。
为什么要用视图?
当频繁需要用到多张表的连表结果,你就可以事先生成好视图,之后直接调用即可,避免了反复写连表操作的sql语句。
如何使用视图?
create view teacher_course as select * from teacher INNER JOIN course on teacher.tid = course.teacher_id;
1、视图只有表结构,视图中的数据还是来源于原来的表
2、不要改动视图表中的数据
3、一般情况下不会频繁的使用视图来写业务逻辑
#需要强调的点 """ 1.在硬盘中,视图只有表结构文件,没有表数据文件 2.视图通常是用于查询,尽量不要修改视图中的数据 """ #需要思考的点:开发过程中会不会去使用视图? """ 不会,视图是MySQL的功能,如果你的项目里大量的使用到了视图,那意味着你后期想要扩张某个功能的时候这个功能恰巧又需要对视图进行修改,意味着你需要先在mysql这边将视图先修改一下,然后再去应用程序中修改对应的sql语句,这就涉及到跨部门沟通的问题,所以通常不会使用视图,而是通过重新修改sql语句来扩展功能 """
#总结 #创建语法:create view 视图名称 as SQL语句
##多张表连接的视图尽量不要修改和删除 #修改语法:alter view 视图名称 as SQL语句 #删除语法:drop view 视图名称
触发器
什么是触发器?
在满足对某张表数据的增、删、改的情况下,自动触发的功能称之为触发器
注意点(触发器无法由用户直接调用,一定是在对表的【增/删/改】操作时触发的)
为什么要用触发器?
触发器专门针对我们对某一张表的增insert、删delete、改update的行为,这类行为一旦执行就会触发触发器的执行,即自动运行另一段sql代码。
怎么用触发器?
触发器分为六种情况:增前、增后、删前、删后、改前、改后。
固定语法
create trigger 触发器的名字 after/before insert/update/delete on 表名 for each row begin sql语句 end #触发器的名字 tri_(before/after)_(insert/update/delete)_表名 #触发器的名字之后先写前后(before/after) #写完之后再写是什么操作(insert/update/delete)
MySQL结束符的修改
#Mysql的结束符(;)是可以修改的
delimiter $$ 只对当前窗口有效
#使用完之后最好修改回来
delimiter ;
案例
#写一个触发器,在给CMD表插入数据之后触发,然后判断插入的success是yes还是no,如果是no,就往errlog里插一条数据 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 ;
#触发器的删除 drop trigger tri_before_insert_user;
事物
事务包含一大堆sql语句,这些sql要么同时成功,要么一个也别想成功
事务的四大特性:ACID
A:原子性(atomicity),一个事务是一个不可分割的工作单位,事务中包括的诸多操作,要么都做,要么都不做。
C:一致性(consistency),事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
I:隔离性(isolation),一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事物是隔离的,并发执行的各个事务之间不能互相干扰。
D :持久性(durability),持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中的改变就应该是永久性的,接下来的其他操作或故障不应该对其有任何影响。
事务的使用
#如何开启事务 start transaction(也可以用begin) #事务回滚 rollback #永久性更改 commit ##可以用set 来改变MySQL的自动提交模式 set autocommit=0(禁止自动提交) set autocommit=1(开启自动提交) ##一旦使用commit再使用回滚也不能回到之前的状态了
存储过程
就类似于python中的自定义函数,内部封装了操作数据库的sql语句,后续想要实现相应的操作,只需要调用存储过程即可。
# 语法结果 delimiter $$ create procedure p1() begin select * from user; end $$ delimiter ; #带参数的 delimiter $$ create procedure p1( in m int, # 不能被返回出去 in n int, out res int, # 可以被返回 inout xxx int, # 既可以进又可以出 ) begin select * from user; end $$ delimiter ;
#调用
call p1()
#实例 delimiter $$ create procedure p1( in m int, # in表示这个参数必须只能是传入不能被返回出去 in n int, out res int # out表示这个参数可以被返回出去,还有一个inout表示即可以传入也可以被返回出去 ) begin select tname from teacher where tid > m and tid < n; set res=0; # 就类似于是一个标志位 用来标识存储器是否执行成功 end $$ delimiter ; call p1() # 调用存储过程并传参 ##传参,将标志位直接传进去会报错 set @res = 10 # 设置一个变量与值的绑定关系 之后通过 select @res 查看存储过程执行完成后的返回结果
注意:存储过程在那个库下面定义就只能在那个库下面使用。
通过pymysql调用存储过程
import pymysql conn = pymysql.connect( host = '127.0.0.1', port = 3306, user = 'root', password = '123', database = 'day38', charset = 'utf8', autocommit = True ) cursor = conn.cursor(pymysql.cursors.DictCursor) # call p1() mysql中调用 # callproc() pymysql中调用 cursor.callproc('p1',(1,5,10)) # 内部自动用变量名存储了对应的值 print(cursor.fetchall()) """
@_p1_0=1 @_p1_1=5 @_p1_2=10 #这是在你传值之后mysql内部自动用这种变量名帮你存取这三个值 @_存储过程名_索引值(传值括号内的索引) """ cursor.execute('select @_p1_0') print(cursor.fetchall()) cursor.execute('select @_p1_1') print(cursor.fetchall()) cursor.execute('select @_p1_2') print(cursor.fetchall())
#删除存储过程 drop procedure proc_name;
函数
自定义函数
#!!!注意!!! #函数中不要写sql语句(否则会报错),函数仅仅只是一个功能,是一个在sql中被应用的功能 #若要想在begin...end...中写sql,请用存储过程 """ delimiter // create function f1( i1 int, i2 int) returns int BEGIN declare num int; set num = i1 + i2; return(num); END // delimiter ; """ delimiter // create function f5( i int ) returns int begin declare res int default 0; if i = 10 then set res=100; elseif i = 20 then set res=200; elseif i = 30 then set res=300; else set res=400; end if; return res; end // delimiter ; """
流程控制
条件语句if
delimiter // CREATE PROCEDURE proc_if () BEGIN declare i int default 0; if i = 1 THEN SELECT 1; ELSEIF i = 2 THEN SELECT 2; ELSE SELECT 7; END IF; END // delimiter ;
循环语句while
delimiter // CREATE PROCEDURE proc_while () BEGIN DECLARE num INT ; SET num = 0 ; WHILE num < 10 DO SELECT num ; SET num = num + 1 ; END WHILE ; END // delimiter ;
索引
知识回顾:数据都是存在硬盘上的,查询数据不可避免的需要进行IO操作
索引在MySQL中也叫作"键",是存储引擎用于快速找到记录的一种数据结构。
- primary key
- unique key
- index key
因为foregin key不是用来加速查询用的,所以不在我们的研究范围内,上面三种key中,前两种除了有加速查询的效果之外还有额外的约束条件(primary key:非空且唯一;unique key:唯一),而index key没有任何约束功能只会帮你加速查询。
索引本质就是一种数据结构,类似书的目录,意味着我们在查数据的时候应该先找目录再找数据,而不是用翻页的方式查询数据。
本质:都是通过不断缩小想要获取数据的范围来筛选出最终想要的结果,同时把随机的时间变成顺序的时间,也就是说,有了这种索引机制,我们可以总是用同一种查找方式来锁定数据。
索引的影响
- 在表中有大量数据的前提下,创建索引速度会很慢
- 在索引创建完毕后,对表的查询性能会大幅度提高,但是写的性能会降低
B+树
只有叶子节点存放真实数据,根和树枝节点存的仅仅是虚拟数据,查询次数由树的层级决定,层级越低次数越少。
我们知道一个磁盘的大小是一定的,也就是存放的数据量也是一定的,我们在每一个数据项内存放的数据越多那么分的层就越少,查询的速度也快,那么在一张表里,用什么字段建立的索引能够降低树的层级高度>>>主键id字段。
聚集索引(primary key)
聚集索引指的就是表的主键,innodb引擎规定一张表中必须要有主键。
我们回顾一下存储引擎建表,myisam在建表的时候有三个文件,而innodb在建表是有两个文件,frm文件只存放表结构,不能存放索引,也就是说innodb的索引跟数据都放在idb表数据文件中。
特点:叶子节点放一条条完整的记录
辅助索引(unique,index)
辅助索引:查询数据的时候不可能都是用id作为筛选条件,也可能会用name,password等字段信息,那么这个时候就无法利用聚集索引的加速查询效果。就需要给其它字段建立索引,这些索引就交辅助索引。
特点:叶子结点存放的是辅助索引对应的那条记录的主键的值
select name from user where name='jason'; #上述语句叫覆盖索引:只在辅助索引的叶子节点中就已经找到了所有我们想要的数据 select age from user where name='jason'; #上述语句叫非覆盖索引,虽然查询的时候命中了索引字段name,但是要查的是age字段,所以#还需要利用主键才去查找