• MySQL视图、事务


    视图

    什么是视图?

      一个查询语句的结果是一张虚拟表,将这种虚拟表保存下来,它就变成了一个视图

    为什么要用视图?

    当频繁需要用到多张表的连表结果,你就可以事先生成号视图之后直接调动即可,避免了反复写连表操作的sql语句

    如何使用?

    create view teacher_course as select * from teacher INNER JOIN course
        on teacher.tid = course.teacher_id;
    1.视图只有表结构,视图中的数据还是来源于原来的表
    2.不要改动视图表中的数据
    3.一般情况下不会频繁的使用视图来写业务逻辑

    触发器

    到达某个条件时自动触发

    当你在对数据进行增、删、改的情况下会自动触发触发器的运行

    触发器分为六种情况

    固定语法结构

    create trigger 触发器的名字 after/before insert/update/delete on 表名 for each row
                begin
                    sql语句
                end
    # 详细版本
    create trigger tri_before/after_insert/update/delete_t1 after/before insert/update/delete on t1 for each row
                begin
                    sql语句
                end

    增前

      可以修改MySQL默认的结束符(;)

      delimiter $$  # 只对当前窗口有效
                create trigger tri_before_insert_user before insert on user for each row
                begin
                    select * from user
                end $$
                delimiter ;

    案例

    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 ;

    事务

    事务包含一大堆sql语句,这些语句要么同时成功,要么一个也别想成功(有一个失败,所有的都失败)

    事务四大特征:ACID

      A:原子性

      C:一致性

      I:隔离性

      D:持久性

    原子性(atomicity): 表示组成一个事务的多个数据库操作是一个不可分割的原子单元,只有所有的操作执行成功,整个事务才提交。事务中的任何一个数据库操作失败,已经执行的任何操作都必须被撤销,让数据库返回初始状态。

    一致性(consistency):事务必须始终保持系统处于一致的状态,不管在任何给定的时间并发事务有多少。也就是说:如果事务是并发多个,系统也必须如同串行事务一样操作。其主要特征是保护性和不变性(Preserving an Invariant),以转账案例为例,假设有五个账户,每个账户余额是100元,那么五个账户总额是500元,如果在这个5个账户之间同时发生多个转账,无论并发多少个,比如在A与B账户之间转账5元,在C与D账户之间转账10元,在B与E之间转账15元,五个账户总额也应该还是500元,这就是保护性和不变性。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。

    隔离性(isolation):隔离状态执行事务,使它们好像是系统在给定时间内执行的唯一操作。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据,该数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。

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

    存储过程

    就类似于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
    
    @_存储过程名_索引值
    """
    cursor.execute('select @_p1_0')
    print(cursor.fetchall())
    cursor.execute('select @_p1_1')
    print(cursor.fetchall())
    cursor.execute('select @_p1_2')
    print(cursor.fetchall())

    函数

    自定义函数

    #!!!注意!!!
    #函数中不要写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字段,所以#还需要利用主键才去查找
  • 相关阅读:
    【java并发编程】ReentrantLock 可重入读写锁
    浏览器上写代码,4核8G微软服务器免费用,Codespaces真香
    【低码】asp.net core 实体类可生产 CRUD 后台管理界面
    深度学习和图形学渲染的结合和应用 Wonder
    Sentinel Dashboard 规则 持久化到Nacos
    一条更新SQL的内部执行及日志模块
    一条Sql的执行过程
    (数据科学学习手札136)Python中基于joblib实现极简并行计算加速
    老板给我安排了个测试环境治理的活
    C# 图片沿中心点进行角度旋转
  • 原文地址:https://www.cnblogs.com/AbrahamChen/p/11400869.html
Copyright © 2020-2023  润新知