zoukankan      html  css  js  c++  java
  • 07--视图、触发器、存储过程、函数、流程控制

    一、视图

    视图就是通过查询一张虚拟表,然后保存下来,下次直接使用
    

    1、为什么要用视图

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

    2、如何操作

     #固定语法
     create view 表名 as 虚拟表的查询sql语法
    
    #创建视图
     create view new_emp as select name,age,post from employee where salary > 10000;
    
    # 查看视图
    show create view new_emp;
    select * from new_emp;
    
    # 修改视图
    alter view new_emp as select name,age from employee where id < 10;
    
    #删除视图
    drop view new_emp;
    

    3、注意

    1、创建视图在硬盘上只会有表结构 没有表数据(数据还是来自之前的表)
    2、视图一般只用来查询,里面的数据不要修改,否则会影响真正的表
     
    # 视图使用频率不高,因为创建了很多视图,会造成表的不好维护
    

    二、触发器

    在满足对表数据进行【增、删、改】操作时前后的行为(6种情况),自动触发的功能,注意:没有查询
    使用触发器可以帮助我们实现监控、日志
    # 删除不能使用触发器
    
    # 语法结构
    create trigger 触发器名字 /before/after insert/update/delete  on 表名 
    for each row
    begin
       sql语句
    end
    #具体使用,触发器的名字 我们要做到见名之意
    
    CREATE TRIGGER tri_after_update_tb1 AFTER UPDATE ON tb1 FOR EACH ROW
    BEGIN #增加
    drop trigger tri_after_insert_cmd; #删除
    
    #  ps:修改Mysql默认语句结束符
    delimiter $$ 将默认的结束符合改为$$
    # delimiter ; 就可以改回来的
    =======================================================
    CREATE TRIGGER trigger_name trigger_time trigger_event ON tb_name FOR EACH ROW trigger_stmt
    trigger_name:触发器的名称
    tirgger_time:触发时机,为BEFORE或者AFTER
    trigger_event:触发事件,为INSERT、DELETE或者UPDATE
    tb_name:表示建立触发器的表明,就是在哪张表上建立触发器
    trigger_stmt:触发器的程序体,可以是一条SQL语句或者是用BEGIN和END包含的多条语句
    
    #可以说MySQL创建以下六种触发器:
    1.插入前	 # before insert 
    create trigger tri_before_insert_tb1 before insert on tb1 for each row
    begin
    	...
    end
    
    1.删除前     # before delete
    create trigger tri_before_delete_tb1 before delete on tb1 for each row 
    begin
    	...
    end
    
    3.更新前      #  before uptate
    create trigger tri_before_update_tb1 before update on tb1 for each row
    begin 
    	...
    end
    
    4.插入后      #  after insert 
    create trigger tri_after_insert_tb1 after insert on tb1 for each row
    begin
    	...
    end
    
    5.删除后      # after delete 
    create trigger tri_after_deletet_tb1 after delete on tb1 for each row
    begin
    	...
    end
    
    6.更新后       # after update
    create trigger tri_after_update_tb1 after update on tb1 for each row
    begin
    	...
    end
    

    1、实例

    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 ;   #改回sql语句的结束符号为分号
    
    # 表cmd中插入记录,触发触发器,根据IF的条件决定是否插入错误日志
    INSERT INTO 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');
        
    #查询错误日志,发现有两条    
    mysql> select * from errlog;
    +----+-----------------+---------------------+
    | id | err_cmd         | err_time            |
    +----+-----------------+---------------------+
    |  1 | cat /etc/passwd | 2021-07-04 10:02:08 |
    |  2 | useradd xxx     | 2021-07-04 10:02:08 |
    +----+-----------------+---------------------+
    2 rows in set (0.00 sec)
    # 删除触发器
    drop trigger tri_after_insert_cmd;
    

    三、存储过程

    1.介绍

    存储过程包含了一系列可执行的sql语句,存储过程存放于MySQL中,通过调用它的名字可以执行其内部的一堆sql,类似与python自定义函数
    

    1)使用存储过程的优点:

    #1. 用于替代程序写的SQL语句,实现程序与sql解耦
    
    #2. 基于网络传输,传别名的数据量小,而直接传sql数据量大
    

    2)存储过程的缺点:

    #1. 程序员扩展功能不方便
    

    3)补充:程序与数据库结合使用的三种方式

    #方式一:
        MySQL:存储过程
        程序:调用存储过程
    
    #方式二:
        MySQL:
        程序:纯SQL语句
    
    #方式三:
        MySQL:
        程序:类和对象,即ORM(本质还是纯SQL语句)
    

    2.基本使用

    create procedure 存储过程的名字(形参1,形参2,形参3...)
    begin
    sql代码
    end
    # 调用
    call 存储过程的名字()
    

    开发模式介绍

    #   程序员                       数据库管理者
        应用程序                      存储过程
        应用程序+sql语句  
        应用程序+orm框架  
        
     # IO多路复用
     https://www.cnblogs.com/linhaifeng/articles/7495918.html
    

    三种开发模型

    # 第一种
    应用程序:程序员写代码开发
    mysql:提前编写好存储过程 ,供应用程序调用
    优点:开发效率提升了,执行效率上去了
    缺点:考虑到人为元素、跨不忙沟通的问题,后续存储过程的跨扩展性差
    
    # 第二种
    应用程序:程序员写代码开发之外,设计到数据库操作也自己手写
    优点:存储过程的跨扩展性很高
    缺点:编写sql语句太多频繁,后续还需要考虑sql优化的问题
    
    # 第三种
    应用程序:只写程序代码,不写sql语句,基于别人写好的mysql的python框架直接调用即可 
    #框架 半成品  ORM跨架
    优点: 开发效率比上面两种效率高
    缺点:语句扩展性差,可能出现效率低下爱的问题
    
    # 第一种基本不用,一般用第三种,出现效率问题在手动写sql
    

    3.存储过程具体演示

    对于存储过程,可以接收参数,其参数有三类:
    #in          仅用于传入参数用
    #out        仅用于返回值用
    #inout     既可以传入又可以当作返回值
    
    delimiter //
    create procedure proc_name(
    	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;
    
    #执行存储过程
    -- 无参数
    call proc_name()
    
    -- 有参数,全in
    call proc_name(1,2)
    
    -- 有参数,有in,out,inout
    set @t1=0;
    set @t2=3;
    call proc_name(1,2,@t1,@t2)
    

    4.删除存储过程

    drop procedure proc_name;
    

    四、函数

    #!!!注意!!!
    #函数中不要写sql语句(否则会报错),函数仅仅只是一个功能,是一个在sql中被应用的功能
    #函数只能在sql语句中使用,不能独立调用
    #若要想在begin...end...中写sql,请用存储过程
    
    存储过程是自定义函数,而函数是内置函数
    
    #1、 准备表和记录
    mysql> create table blog(
        -> id int primary key auto_increment,
        -> name char(30),
        -> sub_time datetime
        -> );
    
    mysql> 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');
    
    #2. 提取sub_time字段的值,按照格式后的结果即"年月"来分组 date_format函数:格式化时间
    mysql> select date_format(sub_time,"%Y-%m"),count(id) from blog group by date_format((sub_time,"%Y-%m");
    
    #结果
    +-------------------------------+-----------+
    | date_format(sub_time,"%Y-%m") | count(id) |
    +-------------------------------+-----------+
    | 2015-03                       |         2 |
    | 2016-07                       |         4 |
    | 2017-03                       |         3 |
    +-------------------------------+-----------+ 
    3 rows in set (0.00 sec
    

    1.自定义函数

    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 ;
    

    2.删除函数

    drop function func_name;
    

    3.执行函数

    # 获取返回值
    select UPPER('egon') into @res;
    SELECT @res;
    
    # 在查询中使用
    select f1(11,nid) ,name from tb2;
    

    五、流程控制

    # 条件语句 if判断
    delimiter //
    CREATE PROCEDURE proc_if ()
    BEGIN
        
        declare i int default 0;    #先声明一个变量,i为整形
        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 ;
    
    call proc_while();
    
  • 相关阅读:
    ZooKeeper系列
    CST和GMT时间的区别
    ZooKeeper系列之二:Zookeeper常用命令
    分布式服务框架 Zookeeper -- 管理分布式环境中的数据
    ZooKeeper资料
    分布式选举算法
    初识ZooKeeper与集群搭建实例
    原子广播
    Apache ZooKeeper
    工作流引擎
  • 原文地址:https://www.cnblogs.com/caodan01/p/14995553.html
Copyright © 2011-2022 走看看