视图、事务、触发器、存储过程、数据库设计三大范式

 

一、视图

      1、什么是视图

           将SQL语句的查询结果称之为一张虚拟表,我们将这张虚拟表 可以称之为 视图。视图就是虚拟表。

      2、为什么用视图

          将多张表拼接起来,做成视图,方便于后期的直接查询。节省拼接表的时间消耗。

     3、如何使用视图

          

create view teacher2course as
select * from teacher inner join course on teacher.tid = course.teacher_id;

注意: 在硬盘中,视图只有表结构文件, 没有表数据文件

            视图通常是用于查询,尽量不要修改视图中的数据。

删除视图语句:drop view teacher2course;

开发过程中会不会去使用视图?

不会!视图是mysql的功能,如果你的项目里面大量的使用到了视图,那意味着你后期想要扩张某个功能的时候这个功能恰巧又需要对视图进行修改,意味着你需要先在mysql这边将视图先修改一下,然后再去应用程序中修改对应的sql语句,这就涉及到跨部门沟通的问题,所以通常不会使用视图,而是通过重新修改sql语句来扩展功能

 

二、触发器:

       在满足对某张表数据的增删改查的情况下,达到某个条件时自动触发的功能称之为触发器。

      1. 在你对表进行增删改查的时候,支持你定义的触发器。

       2.增前、增后,改前,改后,删前,删后

       3.创建触发器完整语句:create trigger 触发器的名字 before/after insert/update/delete on 表名 for each row

                                              begin

                                                      sql语句。。。

                                              end

         4.触发器命名规律:

                                  tri_before_insert_t1    表示 插入之前触发 触发器

         5.为何要用触发器?

             触发器专门针对我们对某一张表数据增insert、删delete、改update的行为,这类行为一旦执行 ​ 就会触发触发器的执行,即自动运行另外一段sql代码

       6.案例

        

# 案例
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
);

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中 sql语句的结束符

        sql语句默认的是以 分号结束。

   delimiter $$              # 表示 将mysql默认的结束符由;换成$$
   delimiter ;               # 表示 结束之后改回来,不然后面结束符就都是$$

四、事务:

      保证数据操作的安全性,一致性,如果事务中有操作失败了,整体就算失败,要么同时成功,要么同时失败。支持回滚操作,一旦数据操作不符合预期,可以回滚到上一个状态

      开启事务:start transaction          (pycharm中开启事务操作)

      回滚:rollback

      确认:commit

        1.事务的四大特性ABCD

           原子性(atomicity):一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。

           一致性(consistency):事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。

           隔离性(isolation):一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。

           持久性(durability):持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。

       2.事务的作用:

         保证了对数据操作的数据安全性

         案例:用交行的卡操作建行ATM机给工商的账户转钱

       3.如何使用事务?

        

create table user(
id int primary key auto_increment,
name char(32),
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元
rollback;                                                 # 回滚到上一个状态

commit;                                                   
# 开启事务之后,只要没有执行commit操作,数据其实都没有真正刷新到硬盘
# 开启事务检测操作是否完整,不完整主动回滚到上一个状态,如果完整就应该执行commit操作

 

五、存储过程

              是指自定义函数:内部封装了一系列的sql语句,让不会mysql操作的人也能够通过调用该存储过程来操作数据库

               1、创建存储过程的语法结构:

                      delimiter $$

                      create procedure 存储过程的名字(

                            形参1,

                            形参2,

                            形参3

                          )

                       begin

                              sql语句;

                       end$$

                       delimiter ;

          

创建存储过程

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 ;
\G表示优化表的格式。\C表示 删除sql语句
select * from mysql.user\G; # 小知识点补充,当一张表的字段特别多记录也很多的情况下,终端下显示出来会出现显示错乱的问题

 

               2、如何使用存储过程

                    大前提:存储过程在哪个库 下面创建的,只能在对应的库 下面才能使用

                    01、使用方法一、直接在MySQL中调用          # 1

set @res=10       # res的值是用来判断存储过程是否被执行成功的依据,所以需要先定义一个变量@res存储10
call p1(2,4,10);  # 报错
call p1(2,4,@res);  
select @res;      # 查看结果,执行成功,因为 @res变量值发生了变化。由10 变成了 0

                     02、使用方法二、在python程序中调用

 

import pymysql
conn = pymysql.connect(
            user = 'root',
            password = '123456',
            host = '127.0.0.1',
            port = 3306,
            db = 'day36_1',
            charset = 'utf8',
            autocommit = True
        )
cursor_obj = conn.cursor(pymysql.cursors.DictCursor)
res = cursor_obj.callproc('p1',(1,6,10))             # callproc() 表示调用 存储过程
print(cursor.fetchall())
cursor.execute('select @_p1_2')
print(cursor.fetchall())
"""
内部自动用变量存储
@_p1_0=1
@_p1_1=6
@_p1_2=10;
规律:@_存储过程的名字_索引 = 值
"""         

 

六、函数

      指的是:mysql的内置函数,只能在sql语句中使用

     例子:

     

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');

七、流程控制

             1、if 条件语句

                  01、 if....then...

                  02、elseif

                 03、else

                 04、end if

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

      2、while 循环

                      while...end while

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

 

八、索引与慢查询优化

       primary key : 约束条件:非空且唯一

       unique key: 约束条件:唯一

       index key: 没有约束条件:只会帮你加速查询

      1.什么是索引?

       索引:类似于书的目录,在MYSQL中也叫做 键,是存储引擎用于快速找到记录的一种数据结构。

      2.为什么有索引?

      一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新 操作很少出现性能问题。我们遇到最多,最容易出现问题的还是一些复杂的查询操作。为了加快数据的查询。

   3.索引的优点缺点

     索引虽然能够加速数据的查询,但不是建的索引越多越好。

     因为在插入或者修改数据的时候,索引反而会降低速度(索引的反复销毁与)

    进程池,比如开了20个进程,当一个进程服务客户端到死,才会返回到进程池。开完20个进程后,可以一直使用,不用反复开。

    要想永久保存数据,就要把数据读到硬盘上。内存是临时存储,关机后,数据就消失了。

4.索引的数据结构

  01、树

   树状图是一种数据结构。

02、B+树

  是通过二叉查找树,再由平衡二叉树,B树演化而来。

  索引的字段尽可能的小。因为IO次数取决于B+树的高度H (这是主键是ID的原因)

  索引的最左匹配特性。谁在最左边,先搜索谁。但是若缺失一个,则会降低搜索效率。

 

 

 5.索引的种类

 注意 myisam在建表的时候对应到硬盘有几个文件(三个)

         innodb在建表的时候对应到硬盘有几个文件(两个) frm文件只存放表结构,不可能放索引,也就意味着innodb的索引跟数据都放在idb表数据文件中

        聚集索引:就是主键(primary key)

        辅助索引(unique,index):给主键意以为的字段建立的索引,就是辅助索引

        覆盖索引:只在辅助索引的叶子节点中就已经找到了所有我们想要的数据

                       select name from userinfo where name='jason'

       非覆盖索引:虽然查询的时候命中了索引字段name,但是要查的是age字段,所以还需要利用主键才去查找          

                      select age from user where name='jason';

    

九、慢查询优化的基本步骤

 

十、数据库设计的三种范式

 第一范式(1NF)

数据表中的每一个字段都必须是不可拆分的最小单元,确保每一个字段的原子性。

不符合第一范式:因为地址字段 可以再分

 

 

第二范式(2NF)

首先必须满足1NF,然后表中的所有字段,都必须完全依赖于主键,而不能有任何一列与主键没有关系,确保一张表只描述一件事情。

不符合第二范式:因为客户编号和客户名称并不依赖于工号这个主键。要拆

 

 

第三范式(3NF)

在满足2NF的基础上,表中的每一个字段只与主键直接相关而不是间接相关,即表中的每一个字段只能直接依赖于主键。

不符合第三范式:因为 “部门电话” 依赖于 “所在部门”, 而 “所在部门” 依赖于 “工号” 这种传递依赖关系, “部门电话” 字段并不直接依赖于工号这个主键。要拆

 

 

 

总结:

第一范式:表中的每一个字段能不能再细分。(字段原子性)

第二范式:表能不能拆分成互相独立的多个表。(每个表至描述一种东西)

第三范式:已经分成的多个表如果有关联,那么在一张表中只能存在另外一张关联表的主键。(通过外键来查询信息)

posted @ 2019-12-17 12:22  薛定谔的猫66  阅读(328)  评论(0)    收藏  举报