zoukankan      html  css  js  c++  java
  • MySQL进阶part4

    视图(了解)

    视图就是通过查询得到一张虚拟表,然后保存下来,下次可以直接使用其实视图也是表。

    如需频繁的操作一张虚拟表(拼表组成的),你就可以制作成视图 后续直接操作

    • 如何操作

    # 固定语法
    create view 表名 as 虚拟表的查询sql语句

    # 具体操作
    create view teacher2course as
    select * from teacher inner join course
    on teacher.tid = course.teacher_id;

    ps:

    1.创建视图再硬盘上只有表结构,没有表数据(数据来自之前的表)

    2.视图一般用来查询 里面的数据不可修改 会影响到真正的表

    3.使用频率不高(视图创多了 表不好维护)

    触发器(了解)

    使用触发器可以实现监控、日志...

    触发器再六种情况下自动触发 增前 增后 删前 删后 改前 改后

    基本语法结构
    create trigger 触发器名 before/after/ insert/updata/delete
    on 表名
    for each row
    begin
    sql语句
    end
    • 针对增

    # 增之前
    create trigger tri_before_insert_t1 before insert on t1
    for each row
    begin
    sql语句
    end

    # 增之后
    create trigger tri_before_insert_t1 after insert on t1
    for each row
    begin
    sql语句
    end
    • 针对删除

    # 删之前
    create trigger tri_before_delete_t1 before delete on t1
    for each row
    begin
    sql语句
    end

    # 删之后
    create trigger tri_after_delete_t1 after delete on t1
    for each row
    begin
    sql语句
    end
    • 针对改

    # 改之前
    create trigger tri_before_update_t1 before update on t1
    for each row
    begin
    sql语句
    end

    # 改之后
    create trigger tri_after_update_t1 after update on t1
    for each row
    begin
    sql语句
    end
    • 案例

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

    """
    当cmd表中的记录succes字段是no那么就触发触发器的执行去errlog表中插入数据
    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 ;

    VALUES
       ('jason','0755','ls -l /etc',NOW(),'yes'),
       ('jason','0755','cat /etc/passwd',NOW(),'no'),
       ('jason','0755','useradd xxx',NOW(),'no'),
       ('jason','0755','ps aux',NOW(),'yes');

    # 删除触发器
    drop trigger tri_after_insert_cmd;

    事务

    • 什么是事务

    开启一个事务可以包含多条sql语句 这些sql语句要么同时成功
    要么一个都成功不了 称之为事务的原子性
    • 事务的作用

    '''
    保证了对数据操作的安全性
    '''
    eg:还钱的例子
    A用银行卡给我的支付宝转账1000给B
    第一步 A的账号里减1000
    第二步 B的账号里加1000
    • 事务的四大特性

    '''
    ACID
    A:原子性
    	一个事务是一个不可分割的单位,事务中包含的诸多操作
    	要么同时失败 要么同时成功
    	
    C:一致性
    	事务必须是使数据库从一个一致性的状态变成另外一个一致性的状态
    	ps:一致性与原子性密切相关
    	
    I:隔离性
    	一个事务的执行不能被其他事务干扰
    	(一个事务内部的操作及使用到的数据对并发的其他事务时隔离的
    	,并发执行的事务之间也是互相不干扰的)
    
    D:持久性
    	就叫"永久性"
    	一个事务一旦提交成功执行成功 那么他对数据库的修改是永久的
    	接下来的其他操作或者故障不应该对其有任何影响
    '''
    
    • 如何使用事务

    # 事务相关的关键字
    # 1 开启事务
    start transaction;
    # 2 回滚(回到事务执行之前的状态)
    rollback;
    # 3 确认(确认之后无法回滚)
    commit;
    
    '''模拟转账功能'''
    create table user(
    	id int primary key auto_increment,
        name char(16),
        balance int
    );
    insert into user(name,balance) values
    ('jason',1000),
    ('egon',1000),
    ('tank',1000);
    
    # 1 先开启事务
    start transaction;
    # 2 多条sql语句
    update user set balance=900 where name = 'jason';
    update user set balance=1010 where name = 'egon';
    update user set balance=1090 where name = 'tank';
    
    '''
    总结:当你想让多条sql语句保持一致性 要么同时成功要么同时失败
    	——使用事务
    '''
    

    存储过程(了解)

    存储过程类似于python中的自定义函数

    他的内部包含了一系列可以执行的sql语句,存储过程存放于MySQL服务端中,你可以直接通过调用存储过程触发内部sql语句的执行

    • 使用

    create procedure 存储过程的名字(形参1 ,形参2,...)
    begin
    	sql代码
    end
    # 调用
    call 存储过程的名字();
    
    • 三种开发模型

    • 第一种

    '''
    应用程序:程序员写代码开发
    MySQL:提前编写好存储过程,供应用程序调用
    
    好处:开发效率提升 执行效率也提升了
    缺点:考虑到认为元素、跨部门沟通问题 后续的存储过程的扩展性差
    '''
    
    • 第二种

    """
    应用程序:程序员写代码开发之外 设计到数据库操作也自己动手写
    优点:扩展性很高
    缺点:
    	开发效率降低
    	编写sql语句太过繁琐 而且后续还需要考虑sql优化的问题
    """
    
    • 第三种

    """
    应用程序:只写程序代码 不写sql语句 基于别人写好的操作MySQL的python框架直接调用操作即可			ORM框架  
    优点:开发效率比上面两种情况都要高 
    缺点:语句的扩展性差 可能会出现效率低下的问题 
    """
    

    ps:第一种基本不用,一般都使用第三种,出现效率问题再手动手写sql

    • 存储过程具体演示

    delimiter $$
    create procedure p1(
    	in m int,  # 只进不出  m不能返回出去
        in n int,
        out res int  # 该形参可以返回出去
    )
    begin
    	select tname from teacher where tid>m and tid<n;
        set res=666;  # 将res变量修改 用来标识当前的存储过程代码确实执行了
    end $$
    delimiter ;
    
    # 针对形参res 不能直接传数据 应该传一个变量名
    # 定义变量
    set @ret = 10;
    # 查看变量对应的值
    select @ret;
    
    • pymysql模块中调用存储过程

    import pymysql
    
    
    conn = pymysql.connect(
        host = '127.0.0.1',
        port = 3306,
        user = 'root',
        passwd = '123456',
        db = 'day48',
        charset = 'utf8',
        autocommit = True
    )
    cursor = conn.cursor(pymysql.cursors.DictCursor)
    # 调用存储过程
    cursor.callproc('p1',(1,5,10))
    """
    @_p1_0=1
    @_p1_1=5
    @_p1_2=10
    """
    # print(cursor.fetchall())
    cursor.execute('select @_p1_2;')
    print(cursor.fetchall())
    
    函数

    跟存储过程是有区别的,存储过程是自定义函数,函数就类似于是内置函数

    ('jason','0755','ls -l /etc',NOW(),'yes')
    
    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 ;
    

    索引

    ps:数据都是存在与硬盘上的,查询数据不可避免的需要进行IO操作

    索引:就是一种数据结构,类似于书的目录。意味着以后查找数据的时候,应该先找目录再找数据,而不是一页一页的找,从而提升查询速度降低IO操作

    索引在MySQL中也叫“键”,是存储引擎用于快速查找记录的一种数据结构

    • primary key

    • unique key

    • index key

    ps:foreign key 不是用来加快查询速度的

    上面三种key,前面两种不仅可以加快查询速度,还具有约束条件

    index key没有任何约束条件,单纯的帮助你加快查询速度。

    本质

    通过不断的缩小想要的数据范围——筛选出最终结果,同时将随机事件(逐页查询)变成顺序事件(先找目录,再找数据)也就是说有了索引机制,我们可以总是用一种固定的方式

    一张表内可以存在多个索引(目录)

    索引的缺点

    • 当表中有大量数据存在的前提下 创建索引速度会比较慢

    • 在索引创建完毕后 对表的查询速度会有很大提升 但是写入的速度会降低很多——所以索引不可随意创建

    b+树

    '''
    只有叶子节点存放的是真实的数据 其他节点存放的是虚拟数据 仅仅用来指路
    树的层级越高 查询数据所需要经历的步骤就越多(树有几层查询数据就需要几步)
    
    一个磁盘块存储是有限制的
    为何建议将id字段作为索引
    	占的空间少 一个磁盘块能够存储的数据多
    	从而降低了树的高度——减少查询次数
    '''
    

    聚集索引(primary key)

    '''
    聚集索引指的就是主键
    Innodb 两个文件 主键存放在idb表中
    MyIsam 三个文件 索引单独存放在一个文件中
    '''
    

    辅助索引(nuique,index)

    查询数据的时候不可能一直使用到主键,也有可能会用到name,password等字段

    这个时候没有办法利用聚集索引,可以根据情况给其他字段设置辅助索引

    '''
    叶子节点存放的是数据对应的主键值
    	先按照辅助索引去拿到数据的主键值
    	再去主键的聚集索引里查询数据
    '''
    

    覆盖索引

    在辅助索引的叶子节点就已经拿到了所需要的数据

    # 给name设置辅助索引
    select name from user where name = 'jake';
    # 非覆盖索引
    select age from user where name = 'jake';
    

  • 相关阅读:
    Java排序算法之堆排序
    servlet学习总结(一)——HttpServletRequest(转载)
    servlet学习总结(一)——初识Servlet
    Java排序算法之快速排序
    Java排序算法之直接选择排序
    第八课、泛型编程简介
    第六课、算法效率的度量
    第四课、程序灵魂的审判
    第三课、初识程序的灵魂------------------------狄泰软件学院
    用solidity语言开发代币智能合约
  • 原文地址:https://www.cnblogs.com/bailongcaptain/p/12858867.html
Copyright © 2011-2022 走看看