zoukankan      html  css  js  c++  java
  • 视图 触发器 事务 存储过程 内置函数 流程控制 索引

    视图
        一个查询语句的结果是一张虚拟表,将这种虚拟表保存下来,它就变成了一个视图
        当频繁需要用到多张表的连表结果,你就可以事先生成好视图,之后直接调用即可,避免了反复写连表操作的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
          sqly语句
        end
        create trigger tri_brfore
    /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 ;
    delimiter $$  # 只对当前窗口有效
    create trigger tri_after_insert_user after insert on user for each row
    begin
        insert into user(name,password) values('老子翻车了','123');  # user和上面user不能相同,不能执行同一张表
    end $$
    delimiter ;
    drop trigger tri_before_insert_user;

    事务
        事务包含一大堆sql语句,这些sql要么同时成功,要么一个也别想成功
        事务四大特性:ACID
            A:原子性/ C:一致性/  I:隔离性/ D:持久性
      原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
      一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
      隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
      持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
      如何开启事务:start transaction
      事务回滚 rollback
      永久性更改 commit

    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操作"""
    
    # 站在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;

    存储过程
        就类似于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 ;
    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 ;
    set @res = 10   # 设置一个变量与值的绑定关系
    调用存储过程 将变量@res传入,之后通过select @res查看存储过程执行完成后的返回结果
    存储过程在哪个库下面定义 就只能在哪个库下面使
    delimiter //
    create PROCEDURE p5(
        OUT p_return_code tinyint
    )
    BEGIN
        DECLARE exit handler for sqlexception
        BEGIN
            -- ERROR
            set p_return_code = 1;
            rollback;
        END;
    
    
      DECLARE exit handler for sqlwarning
      BEGIN
          -- WARNING
          set p_return_code = 2;
          rollback;
      END;
    
      START TRANSACTION;
          update user set balance=900 where id =1;
          update user123 set balance=1010 where id = 2;
          update user set balance=1090 where id =3;
      COMMIT;
    
      -- SUCCESS
      set p_return_code = 0; #0代表执行成功
    
    
    END //
    delimiter ;

     pymysql 调用存储过程

    import pymysql
    conn = pymysql.connect(
        host = '127.0.0.1',
        port = 3306,
        user = 'root',
        password = '777',
        database = 'db2',
        charset = 'utf8',
        autocommit = True
    )
    cursor = conn.cursor(pymysql.cursors.DictCursor)
    # call p1()  mysql中调用
    # callproc()  pymysql中调用 cursor.callproc(
    'p1',(1,5,10)) # 内部自动用变量名存储了对应的值 print(cursor.fetchall())

    函数

    注意与存储过程的区别,mysql内置的函数只能在sql语句中使用!

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

    流程控制

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

    索引与慢查询优化

      *索引在MySQL中也叫做“键”,是存储引擎用于快速找到记录的一种数据结构。
      * primary key / unique key / index key

      上面三种key前两种除了有加速查询的效果之外还有额外的约束条件(primary key:非空且唯一,unique key:唯一),而index key没有任何约束功能只会帮你加速查询,注意foreign key不是用来加速查询用的。

      索引就是一种数据结构,类似于书的目录。意味着以后再查数据应该先找目录再找数据,而不是用翻页的方式查询数据。本质都是:通过不断地缩小想要获取数据的范围来筛选出最终想要的结果,同时把随机的事件变成顺序的事件,也就是说,有了这种索引机制,我们可以总是用同一种查找方式来锁定数据。
    **索引的影响:**
      * 在表中有大量数据的前提下,创建索引速度会很慢
      * 在索引创建完毕后,对表的查询性能会大幅度提升,但是写的性能会降低

    b+树

      只有叶子结点存放真实数据,根和树枝节点存的仅仅是虚拟数据,查询次数由树的层级决定,层级越低次数越少,一个磁盘块儿的大小是一定的,那也就意味着能存的数据量是一定的。如何保证树的层级最低呢?一个磁盘块儿存放占用空间比较小的数据项

    聚集索引(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字段,所以还需要利用主键才去查找

    dayehui
  • 相关阅读:
    JAVA课上课后问题总结(2019.09.20)
    JAVA课后问题汇总(第三次课)
    java课后作业:记录创建对象数
    《程序员修炼之道》读后感(一)【第二章与第三章】
    [java web]小学四则运算出题系统
    apache连接数
    isql导出表到文本
    iis6上的FTP有缓存
    Perl 标量的操作符
    apachetomcat
  • 原文地址:https://www.cnblogs.com/zrh-960906/p/11400589.html
Copyright © 2011-2022 走看看