MySQL >>> 功能
1. 视图
什么是视图?
一个查询语句的结果是一张虚拟表,将这种虚拟表保存下来
它就变成了一个视图
一个查询语句的结果是一张虚拟表,将这种虚拟表保存下来
它就变成了一个视图
为什么要用视图?
当频繁需要用到多张表的连表结果,你就可以事先生成好视图
之后直接调用即可,避免了反复写连表操作的 sql 语句
当频繁需要用到多张表的连表结果,你就可以事先生成好视图
之后直接调用即可,避免了反复写连表操作的 sql 语句
创建视图表语法:
create view teacher_course as select * from teacher INNER JOIN course
on teacher.tid = course.teacher_id;
1. 视图只有表结构,没有表数据文件;视图中的数据还是来源于原来的表
2. 不要改动视图表中的数据
3. 一般情况下不会频繁的使用视图来写业务逻辑
2. 触发器
概念:在满足对某张表数据的 增、删、改 的情况下,自动触发 的功能称之为触发器
为什么使用???
触发器专门针对我们对某一张表数据增 insert、删 delete、改 update 的行为,这类行为一旦执行
就会触发触发器的执行,即自动运行另外一段 sql 代码
就会触发触发器的执行,即自动运行另外一段 sql 代码
创建触发器语法:
触发器分为六种情况 >>> (增前、增后 改前、改后 删前、删后)
但语法固定,如下:
create trigger 触发器名 after / before 增删改操作(insert / update / delete) on 表名 for each row
begin
sql 语句
end
ps:触发器名有一定的规律,要做到见名知意;如:
tri_before _insert_t1 >>> 表示在插入表1数据之前的触发器
tri_after_insert_t1 >>> 表示在插入表1数据之后的触发器
tri_before_update_t1 >>> 表示在修改表1数据之前的触发器
tri_after_update_t1 >>> 表示在修改表1数据之后的触发器
tri_before_delete_t1 >>> 表示在删除表1数据之前的触发器
tri_before_delete_t1 >>> 表示在删除表1数据之后的触发器
例子用法:
# 创建表
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') # no代表执行失败 ); CREATE TABLE errlog ( id INT PRIMARY KEY auto_increment, err_cmd CHAR (64), err_time datetime );
# 创建触发器
补充:NEW对象指代的就是当前记录 delimiter $$ # 将mysql默认的结束符由;换成$$(因为你的sql语句中可能有多个 ; ,而原本的操作是只要遇到一个 ; 就结束了)
# 只对当前窗口有效 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_after_insert_cmd;
3. 事务
事务包含一大堆 sql 语句,这些 sql 要么同时成功,要么一个也别想成功
作用:保证了对数据操作的数据安全性
特性:事务应该具有4个属性,这四个属性通常称为 ACID 特性
原子性(atomicity):
一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
一致性(consistency):
事务必须是使数据库从一个一致性状态变到另一个一致性状态。
一致性与原子性是密切相关的。
隔离性(isolation):
一个事务的执行不能被其他事务干扰。
即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
持久性(durability):
持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。
接下来的其他操作或故障不应该对其有任何影响。
开启事务:start transaction
事务回滚:rollback
永久更改:commit
例子用法:
# 修改数据之前先开启事务操作 start transaction; # 修改操作 update user set balance=900 where name='wsb'; #买支付100元 update user set balance=1010 where name='egon'; #中介拿走10元 update user set balance=1090 where name='ysb'; #卖家拿到90元 # 回滚到上一个状态 rollback; # 开启事务之后,只要没有执行commit操作,数据其实都没有真正刷新到硬盘
"""开启事务检测操作是否完整,不完整主动回滚到上一个状态,如果完整就应该执行commit操作""" try: update user set balance=900 where name='wsb'; #买支付100元 update user set balance=1010 where name='egon'; #中介拿走10元 update user set balance=1090 where name='ysb'; #卖家拿到90元 except 异常: # 异常如何检测?????---> 下面的存储过程 rollback; else: commit;
4. 存储过程
存储过程包含了一系列可执行的 sql 语句,存储过程存放于 MySQL 中,通过调用它的名字可以执行其内部的一堆 sql
如何创建存储过程??
# 语法 delimiter $$ create procedure 过程名( in m int, # in表示这个参数只能是传入,不能被返回 in n int, out res int # out表示这个参数可以被返回出去 inout res int # inout表示这个参数既可以传入,也可以被返回出去 一般不使用 ) # 关键字in/out/inout 值 类型 begin select 字段名 from 表名 where 条件; # 如:select tname from teacher where tid > m and tid < n; set res = 0 # 修改可以返回出去的值,再进行查看,就可以知道有没有存储成功 end $$ delimiter ;
如何使用??
# 大前提:存储过程是在哪个库下面创建的,就只能在对应的库下面使用! # 使用一:直接在mysql中调用 set @res = 10 # res的值是用来判断存储过程是否被执行成功的依据 # 所以需要先定义一个变量@res存储10 call p1(2,4,10) # 报错 call p1(2,4,@res) #使用 call + 过程名字(参数) 来调用存储过程 # 查看结果 select @res; # @res发生了变化,则表示存储过程执行成功 # 使用二:在python程序中调用 # pymysql连接mysql # 产生的游标 cursor.callproc('p1',(2,4,10))
# 内部的原理:@_p1_0 = 2 @_p1_1 = 4 @_p1_2 = 10; # 0、1、2对应的为括号内第二个参数索引位置 cursor.execute('select @_p1_2;') # 查看是否有变化
5. 函数
mysql 内置的函数只能在 sql 语句中使用!
参考博客:<http://www.cnblogs.com/linhaifeng/articles/7495918.html#_label2>
CREATE TABLE blog ( id INT PRIMARY KEY auto_increment, NAME CHAR (32), sub_time datetime ); INSERT INTO blog (NAME, sub_time) VALUES ('第1篇','2015-03-01 11:31:21'), ('第2篇','2015-03-11 16:31:21'), ('第3篇','2016-07-01 10:21:31'), ('第4篇','2016-07-22 09:23:21'), ('第5篇','2016-07-23 10:11:11'), ('第6篇','2016-07-25 11:21:31'), ('第7篇','2017-03-01 15:33:21'), ('第8篇','2017-03-01 17:32:21'), ('第9篇','2017-03-01 18:31:21'); select date_format(sub_time,'%Y-%m'),count(id) from blog group by date_format(sub_time,'%Y-%m');
6.流程控制
# if条件语句 delimiter // CREATE PROCEDURE proc_if () # 关键词 procedure 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 ;
7. 索引与慢查询优化
知识回顾:数据都是存在硬盘上的,那查询数据不可避免的需要进行IO操作
*索引在MySQL中也叫做 “键”,是存储引擎用于快速找到记录的一种数据结构。
* primary key
* unique key
* index key
* unique key
* index key
注意:foreign key 不是用来加速查询用的,不在我们研究范围之内,
上面三种 key 前两种除了有加速查询的效果之外还有额外的约束条件:
(primary key:非空且唯一,unique key:唯一),而index key没有任何约束功能只会帮你加速查询
索引就是一种数据结构,类似于书的目录。意味着以后再查数据应该先找目录再找数据,而不是用翻页的方式查询数据
**本质都是:通过不断地缩小想要获取数据的范围来筛选出最终想要的结果,同时把随机的事件变成顺序的事件
也就是说,有了这种索引机制,我们可以总是用同一种查找方式来锁定数据。
**索引的影响:
* 在表中有大量数据的前提下,创建索引速度会很慢
* 在索引创建完毕后,对表的查询性能会大幅度提升
* 在索引创建完毕后,对表的查询性能会大幅度提升
#### b+树 <https://images2017.cnblogs.com/blog/1036857/201709/1036857-20170912011123500-158121126.png> 只有叶子结点存放真实数据,根和树枝节点存的仅仅是虚拟数据 查询次数由树的层级决定,层级越低次数越少 一个磁盘块儿的大小是一定的,那也就意味着能存的数据量是一定的。如何保证树的层级最低呢?一个磁盘块儿存放占用空间比较小的数据项 思考我们应该给我们一张表里面的什么字段字段建立索引能够降低树的层级高度>>> 主键id字段
#### **聚集索引(primary key)** 聚集索引其实指的就是表的主键,innodb引擎规定一张表中必须要有主键。先来回顾一下存储引擎。 myisam在建表的时候对应到硬盘有几个文件(三个)? innodb在建表的时候对应到硬盘有几个文件(两个)?frm文件只存放表结构,不可能放索引,也就意味着innodb的索引跟数据都放在idb表数据文件中。 **特点:**叶子结点放的一条条完整的记录
#### 辅助索引(unique,index) 辅助索引:查询数据的时候不可能都是用id作为筛选条件,也可能会用name,password等字段信息,那么这个时候就无法利用到聚集索引的加速查询效果。就需要给其他字段建立索引,这些索引就叫辅助索引 **特点:**叶子结点存放的是辅助索引字段对应的那条记录的主键的值(比如:按照name字段创建索引,那么叶子节点存放的是:{name对应的值:name所在的那条记录的主键值})
select name from user where name='jason';
上述语句叫覆盖索引:只在辅助索引的叶子节点中就已经找到了所有我们想要的数据
select age from user where name='jason'; 上述语句叫非覆盖索引,虽然查询的时候命中了索引字段name,但是要查的是age字段,所以还需要利用主键才去查找