zoukankan      html  css  js  c++  java
  • mysql-视图、事物等

    一、视图

    视图是一个虚拟表(非真实存在),其本质是【根据SQL语句获取动态的数据集,并为其命名】,用户使用时只需使用【名称】即可获取结果集,可以将该结果集当做表来使用。

    使用视图我们可以把查询过程中的临时表摘出来,用视图去实现,这样以后再想操作该临时表的数据时就无需重写复杂的sql了,直接去视图中查找即可,但视图有明显地效率问题,并且视图是存放在数据库中的,如果我们程序中使用的sql过分依赖数据库中的视图,即强耦合,那就意味着扩展sql极为不便,因此并不推荐使用

    create view course2teacher as select * from course inner join teacher on course.teacher_id = teacher.tid;  # 只有表结构,没有表数据,因为它的数据是基于其他表的。不建议使用,因为以后扩展sql语句的时候,视图也需要跟着修改。
    
    # 修改视图
    alter view teacher_view as select * from course where cid>3;
    
    # 删除视图
    drop view teacher_view
    
    
    -- 2.触发器  (一般不用,这个在应用程序级别能做,在应用程序级别能干的活还是去自己干好,以后扩展方便)
    
    #准备表
    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 //  # 定义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 ;  # 把结束符号还原回来 
    
    
    #往表cmd中插入记录,触发触发器,根据IF的条件决定是否插入错误日志
    INSERT 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');
    
    
    # 删除触发器
    drop trigger tri_after_insert_cmd;
    
    
     -- 3 存储过程
     # (1) 无参存储过程
     delimiter //
     create procedure p1()
     BEGIN
      select * from db7.teacher;
     END //
     delimiter ;
     
     # MySQL中调用
     call p1();
     
     # Python中调用
     cursor.callproc('p1')
     
     # (2) 有参存储过程。不但要指定是接收还是返回,还要指定类型
     
     delimiter //
     create procedure p2(in n1 int,in n2 int,out res int)
     BEGIN
         select * from db7.teacher where tid > n1 and tid < n2;
         set res = 1;
     END //
     delimiter ;
     
     # inout 可进可出 了解就行
     
     # MySQL中调用
     set @x=0
     call p2(2,4,@x);
     select @x;  # 查看返回值结果
     
     # Python中调用 
     cursor.callproc('p2',(2,4,0))  # @_p2_0=2,@_p2_1=4,@_p2_2=0
     cursor.excute('select @_p3_2')
     cursor.fetchall()
    
    
    
    
    
    ## 应用程序和数据库结合使用
    
    ### 方式一:
    
        MySQL:  编写存储过程
    
        python:调用存储过程
    
    
    
    ### 方式二:
    
        Python:编写纯生SQL
    
        MySQL:什么都不用干
    
    ### 方式三:
    
        Python:ORM --> 纯生SQL
    
        MySQL:
    
    # 运行效率方式二高,开发效率方式三高(运行效率比方式二慢不了多少),我们主要是用方式三,偶尔用方式二,很少会去用方式一,除非一个人应用程序开发和DBA开发都很厉害。

    二、事物

    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元
    commit;
    
    #出现异常,回滚到初始状态
    start transaction;
    update user set balance=900 where name='wsb'; #买支付100元
    update user set balance=1010 where name='egon'; #中介拿走10元
    uppdate user set balance=1090 where name='ysb'; #卖家拿到90元,出现异常没有拿到
    rollback;
    commit;

    三、函数和流程控制

    #1 准备表和记录
    CREATE TABLE blog (
        id INT PRIMARY KEY auto_increment,
        NAME CHAR (32),
        sub_time datetime
    );
    
    INSERT 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');
       
    #2. 提取sub_time字段的值,按照格式后的结果即"年月"来分组
    
    select date_format(sub_time,'%Y-%m'),count(id) from blog group by date_format(sub_time,'%Y-%m');

    四、索引原理

    #1. 准备表
    create table s1(
    id int,
    name varchar(20),
    gender char(6),
    email varchar(50)
    );
    
    #2. 创建存储过程,实现批量插入记录
    delimiter $$ #
    create procedure auto_insert1()
    BEGIN
        declare i int default 1;
        while (i<3000000) do
            insert into s1 values(i,'egon','male',concat('egon',i,'@oldboy'));
            set i=i+1;
        end while;
    END$$
    delimiter ; 
    
    #3. 查看存储过程
    show create procedure auto_insert1G 
    
    #4. 调用存储过程
    call auto_insert1();
    
    #无索引:mysql根本就不知道到底是否存在id等于333333333的记录,只能把数据表从头到尾扫描一遍,此时有多少个磁盘块就需要进行多少IO操作,所以查询速度很慢
    mysql> select * from s1 where id=333333333;
    Empty set (0.33 sec)
    
    # 创立索引前
    select count(id) from s1 where id = 1000
    row in set (0.80 sec)
    
    # 创立索引
    create index idx_id on s1(id)
    Query OK, 0 rows affected (2.63 sec)
    Records: 0  Duplicates: 0  Warnings: 0
    
    # 创立索引后
    select count(id) from s1 where id = 1000;
    row in set (0.00 sec)
  • 相关阅读:
    lightoj 1094 Farthest Nodes in a Tree 【树的直径 裸题】
    nyoj 1185 最大最小值【线段树最大值最小值维护】
    nyoj 123 士兵杀敌(四) 树状数组【单点查询+区间修改】
    poj 3468 A Simple Problem with Integers【线段树区间修改】
    hdoj 1698 Just a Hook【线段树区间修改】
    hdoj 1556 Color the ball【线段树区间更新】
    hdoj 1286 找新朋友【欧拉函数】
    [LC] 303. Range Sum Query
    [LC] 79. Word Search
    [LC] 211. Add and Search Word
  • 原文地址:https://www.cnblogs.com/hexiaorui123/p/10440378.html
Copyright © 2011-2022 走看看