zoukankan      html  css  js  c++  java
  • MySQL了解知识点

    视图

    • 什么是视图

      • 视图就是通过查询得到的一张虚拟的表,然后保存下来,下次可直接使用
    • 创建视图的语句

      • create view 视图名 as sql语句
      create view student_score as select * from student inner join score on student.sid = score.student_id;
      
    • 作用就是:如果要频繁的使用一张虚拟表,可以不用重复查询,可直接使用

    注意:创建出来的视图是只有表结构的,他没有数据,显示的数据依然还是来源于源表,而且不要修改视图中的数据,如果需要修改数据,要修改原表中的数据


    触发器

    • 什么是触发器

      • 当满足修改一张表数据的增、删、改的情况下,自动触发的功能称之为触发器
    • 为什么要使用触发器

      • 触发器专门针对对某一张表数据的增、删、改的行为,这类行为一旦执行就会触发触发器,即自动运行另外一段SQL语句
    • 创建触发器的语法

      trigger
      -- 完整语法
      create trigger 触发器名字 before/ after insert/ update/ delete for each row
      begin
      	sql语句...
      end
      -- 触发器的命名规律
      	tri_before_insert_t1
      	
      -- 删除触发器
      drop trigger 触发器名字;
      --------------------------------------------------------------------------
      -- 针对插入
      	-- 增前
      	create trigger tri_after_insert_t1 after insert on 表名 for each row
      	begin
      		sql语句...
      	end
      	-- 增后
      	create trigger tri_before_insert_t2 before insert on 表名 for each row
      	begin
      		sql语句...
      	end
      -- 针对修改
      	-- 改前
      	create trigger tri_after_update_t1 after update on 表名 for each row
      	begin
      		sql语句...
      	end
      	-- 改后
      	create trigger tri_before_update_t1 before insert on 表名 for each row
      	begin
      		sql语句...
      	end
      -- 针对删除
      	-- 删前
      	create trigger tri_after_delete_t1 after delete on 表名 for each row
      	begin
      		sql语句...
      	end
      	-- 删后
      	create trigger tri_before_delete_t1 before delete on 表名 for each row
      	begin
      		sql语句...
      	end
      
    • 知识点补充

      • sql语句默认是以分号";"结束的,但我们可以修改结束符为任意符号
      • delimiter $ 但是是临时修改,只在当前库有效,并且当前窗口一旦关闭,重新进入就失效
      -- 案例
      CREATE TABLE cmd(
      	id INT PRIMARY KEY auto_increment,
      	user VARCHAR(20),
      	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);
      
      
      delimiter $ -- 将MySQL默认的结束符由;改为$
      CREATE TRIGGER tri_after_insert_cmd AFTER INSERT ON cmd FOR EACH ROW
      BEGIN
      	IF NEW.success = 'no' THEN -- 新纪录都会被MySQL封装成NEW对象
      		INSERT INTO errlog(err_cmd, err_time) VALUES(NEW.cmd, NEW.sub_time);
      	END IF;	-- 这个地方必须是分号
      END $	-- 结束符号
      delimiter ;	-- 结束之后记得再改回来,不然后面结束符就都是$了
      
      
      -- 往表cmd中插入记录,触发触发器,根据IF的条件决定是否插入错误日志
      INSERT INTO cmd(user, priv, cmd, sub_time, success)
      VALUES('egon','0755','ls -l /etc',NOW(),'yes'),
      			('egon','0755','cat /etc/passwd',NOW(),'no'),
      			('egon','0755','useradd xxx',NOW(),'no'),
      			('egon','0755','ps aux',NOW(),'yes');
      
      -- 查询errlog表记录
      SELECT * FROM errlog;
      -- 删除触发器
      DROP TRIGGER tri_after_insert_cmd;
      

    事务

    • 什么是事务
      • 开启一个事务可以包含一些SQL语句,这些SQL语句要么同时成功,要么全部失败
    • 事务的作用
      • 保证了对数据操作的安全性、一致性
      • 案例:ATM账户之间转账
    • 事务的四大特性:ACID特性
      • 原子性(atomicity):一个事务是不可分割的工作单位,事务中包括的各种操作要么都做,要么都不做
      • 一致性(consistency):事务必须是使数据库从一个一致性状态变到另一个一致性状态,一致性与原子性是密切相关的
      • 隔离性(isolation):一个事务的执行不能被其他事务干扰,就是事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰
      • 持久性(durability):持久性也称为永久性(permanence),指的是一个事务一旦提交,它对数据库的影响,改变就是永久性的,接下来的其他操作或故障不应该对其有任何影响
    • 支持回滚操作
      • 一旦数据操作的不符合预期,可以回滚到上一个状态
      • 开启事务:start transcation;
      • 回滚:rollback
      • 确认:commit
    CREATE TABLE user(
    id INT PRIMARY KEY auto_increment,
    name VARCHAR(20),
    balance INT);
    
    
    INSERT INTO user(name, balance)
    VALUES
    ('wsb',1000),
    ('egon',1000),
    ('ysb',1000);
    
    -- 修改数据之前先开启事务
    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元
    
    SELECT * FROM user;
    -- 回滚到上一个状态
    ROLLBACK;
    
    -- 开启事务之后,只要没有执行commit操作,数据其实都没有真正刷新到硬盘
    COMMIT;
    -- 开启事务检测操作是否完整,不完整主动回滚到上一个状态,如果完整就应该执行commit操作
    
    # 站在python代码的角度,应该实现的伪代码逻辑
    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;
    

    存储过程

    • 存储过程包含了一系列可执行的SQL语句,存储过程存放于MySQL中,通过调用它的名字可以执行其内部的一堆SQL

    • 关键字:procedure

    • 语法结构

      create procedure 存储过程的名字(
      	形参1,
      	形参2,
      	形参3,
      	...)
      begin
      	sql语句;
      end;
      
    • 无参

      delimiter $
      create procedure p1()
      begin
      	select * from user;
      end $
      delimiter ;
      -- MySQL中调用
      call p1();
      
    • 有参

      delimiter $
      create prodedure p1(
      	in m int,	-- 表示这个参数必须只能是传入不能被返回出去
      	in n int,
      	out res int
      ) -- out表示这个参数可以被返回出去,还有一个inout表示既可被传入也可被返回出去
      begin
      	select tname from teacher where tid > m and tid < n;
      	set res=0;	# 修改形参的值	设置
      end $
      delimiter ;
      -- 返回值	用来判断当前存储过程是否执行成功
      res = 10
      p1(1,2,res)
      print(res)
      
    • 在python中调用

      # pymysql链接mysql
      #产生的游表
      cursor.callproc('p1',(2,4,10))  # 内部原理:@_p1_0=2,@_p1_1=4,@_p1_2=10;
      cursor.excute('select @_p1_2;')
      

    函数

    注意与存储过程的区别,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');
    

    流程控制

    -- 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

    注意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字段,所以还需要利用主键才去查找

    慢查询日志

    最后说下慢查询日志是什么

    比如10s

    设定一个时间检测所有超出该时间的sql语句,然后针对性的进行优化!

  • 相关阅读:
    人生感悟:人与人之间的距离
    9月22日测试题目
    Java自学第五十二天
    Java自学第五十一天
    Java自学第五十天
    Java自学第四十九天
    Java自学第四十八天
    Java自学第四十七天
    Java自学第四十六天
    Java自学第四十五天
  • 原文地址:https://www.cnblogs.com/YGZICO/p/12097807.html
Copyright © 2011-2022 走看看