一、视图

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

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


1、创建视图

语法:CREATE VIEW 视图名称 AS  SQL语句

    create view teacher_view as select tid from teacher where tname='李平老师';

!!!注意注意注意:

1)使用视图以后就无需每次都重写子查询的sql,但是这么效率并不高,还不如我们写子查询的效率高

2)而且有一个致命的问题:视图是存放到数据库里的,如果我们程序中的sql过分依赖于数据库中存放的视图,那么意味着,一旦sql需要修改且涉及到视图的部分,则必须去数据库中进行修改,而通常在公司中数据库有专门的DBA负责,你要想完成修改,必须付出大量的沟通成本DBA可能才会帮你完成修改,极其地不方便。

2、使用视图

修改视图,原始表也跟着改

    create view course_view as select * from course; #创建表course的视图

    select * from course_view;

    update course_view set cname='xxx'; #更新视图中的数据

    insert into course_view values(5,'yyy',2); #往视图中插入数据

    select * from course; #发现原始表的记录也跟着修改了

注:一般情况下不应该修改视图中的记录,而且在涉及多个表的情况下是根本无法修改视图中的记录

3、修改视图

语法:ALTER VIEW 视图名称 AS SQL语句 (alter 变更)

     alter view teacher_view as select * from course where cid>3;

4、删除视图

语法:DROP VIEW 视图名称

     DROP VIEW teacher_view


二、触发器

使用触发器可以定制用户对表进行【增、删、改】操作时前后的行为。注意:没有查询!!!

1、创建触发器

    插入前

        CREATE TRIGGER tri_before_insert_tb1 BEFORE INSERT ON tb1 FOR EACH ROW

        BEGIN

            ...

        END

    插入后

        CREATE TRIGGER tri_after_insert_tb1 AFTER INSERT ON tb1 FOR EACH ROW

        BEGIN

            ...

        END

    删除前

        CREATE TRIGGER tri_before_delete_tb1 BEFORE DELETE ON tb1 FOR EACH ROW

        BEGIN

            ...

        END

    删除后

        CREATE TRIGGER tri_after_delete_tb1 AFTER DELETE ON tb1 FOR EACH ROW

        BEGIN

            ...

        END

    更新前

        CREATE TRIGGER tri_before_update_tb1 BEFORE UPDATE ON tb1 FOR EACH ROW

        BEGIN

            ...

        END

    更新后

        CREATE TRIGGER tri_after_update_tb1 AFTER UPDATE ON tb1 FOR EACH ROW

        BEGIN

            ...

        END

举个栗子:

    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

特别的:NEW表示即将插入的数据行,OLD表示即将删除的数据行。

2、使用触发器

    触发器无法由用户直接调用,而知由于对表的【增/删/改】操作被动引发的。

3、删除触发器

    drop trigger tri_after_insert_cmd;


三、事务

事务用于将某些操作的多个SQL作为原子性操作,一旦有某一个出现错误,即可回滚到原来的状态,从而保证数据库数据完整性。

    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;

    mysql> select * from user;

    +----+------+---------+

    | id | name | balance |

    +----+------+---------+

    |  1 | wsb  |    1000 |

    |  2 | egon |    1000 |

    |  3 | ysb  |    1000 |

    +----+------+---------+


四、存储过程

1、介绍

存储过程包含了一系列可执行的sql语句,存储过程存放于MySQL中,通过调用它的名字可以执行其内部的一堆sql

使用存储过程的优点:

    1)用于替代程序写的SQL语句,实现程序与sql解耦

    2)基于网络传输,传别名的数据量小,而直接传sql数据量大

使用存储过程的缺点:

    1)程序员扩展功能不方便

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

方式一:

    MySQL:存储过程

    程序:调用存储过程

方式二:

    MySQL:

    程序:纯SQL语句

方式三:

    MySQL:

    程序:类和对象,即ORM(本质还是纯SQL语句)

2、创建简单存储过程(无参)

    delimiter //

    create procedure p1()

    BEGIN

        select * from blog;

        INSERT into blog(name,sub_time) values("xxx",now());

    END //

    delimiter ;

在mysql中调用:   call p1() 

在python中基于pymysql调用

    cursor.callproc('p1') 

    print(cursor.fetchall())


3、创建存储过程(有参)

对于存储过程,可以接收参数,其参数有三类:

    in          仅用于传入参数用

    out        仅用于返回值用

    inout     既可以传入又可以当作返回值


4、执行存储过程

    -- 无参数: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)

5、删除存储过程

    drop procedure proc_name;


五 函数

MySQL中提供了许多内置函数

1、自定义函数

注意:函数中不要写sql语句(否则会报错),函数仅仅只是一个功能,是一个在sql中被应用的功能

     若要想在begin...end...中写sql,请用存储过程

2、删除函数


3、执行函数


六、流程控制

1、条件语句

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 ;

2、循环语句

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 ;

repeat循环

    delimiter //

    CREATE PROCEDURE proc_repeat ()

    BEGIN


        DECLARE i INT ;

        SET i = 0 ;

        repeat

            select i;

            set i = i + 1;

            until i >= 5

        end repeat;

    END //

    delimiter ;

loop

    BEGIN   

        declare i int default 0;

        loop_label: loop

            

            set i=i+1;

            if i<8 then

                iterate loop_label;

            end if;

            if i>=10 then

                leave loop_label;

            end if;

            select i;

        end loop loop_label;

    END