mysql之视图、触发器、事务和存储过程

一、视图
1、什么是视图
视图就是通过查询得到的一张虚拟表,然后保存下来,下次直接使用即可

2、为什么要用视图
如果要频繁的使用一张虚拟表,可以不用重复查询

3、如何使用视图

create view teacher2course as 
        select * from teacher inner join course
            on teacher.tid = course.teacher_id

强调:
1、在硬盘中,视图只有表结构,没有表数据文件
2、视图通常是用于插叙,尽量不要修改视图中的数据

二、触发器
1、什么是触发器
在满足对某张表数据的增、删、改的情况下,自动触发的功能称之为触发器

2、为何要用触发器
触发器专门针对我们某一张表数据增insert、删delete、改update的行为,这类
行为一旦执行就会触发触发器的执行,即自动运行另外一段sql代码

3、创建触发器语法

#针对插入
        create trigger tri_after_insert t1 after insert on 表名 for each row
        begin
            sql代码...
        end
        
        create trigger tri_before_insert t1 before insert on 表名 for each row
        begin
            sql代码...
        end
        
        #针对删除
        create trigger tri_after_insert t1 after delete on 表名 for each row
        begin
            sql代码...
        end
        
        create trigger tri_before_insert t1 before delete on 表名 for each row
        begin
            sql代码...
        end
        
        #针对修改
        create trigger tri_after_insert t1 after delete on 表名 for each row
        begin
            sql代码...
        end
        
        create trigger tri_before_insert t1 before delete on 表名 for each row
        begin
            sql代码...
        end
        
        #针对修改
        create trigger tri_after_insert t1 after update on 表名 for each row
        begin
            sql代码...
        end
        
        create trigger tri_before_insert t1 before update on 表名 for each row
        begin
            sql代码...
        end

4、案例

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 $$
        create trigger tri_after_insert_cmd after insert on cmd for each row
        begin
            if new.success = 'no' then
                insert into errorlog(err_cmd,err_time) values (new.cmd,new.sub_time);
                end if;
            end $$
        delimiter ;

三、事务

1、什么是事务
开启一个事务可以包含一些sql语句,这些语句要么同时成功,
要么一个都别想成功,这个特性称为事务的原子性


2、事务的作用
用于设计转账接口的时候使用

3、如何使用

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);
#得到的结果如下
mysql> select * from user;
+----+------+---------+
| id | name | balance |
+----+------+---------+
|  1 | wsb  |    1000 |
|  2 | egon |    1000 |
|  3 | ysb  |    1000 |
+----+------+---------+

#原子操作
start transaction;
update user set balance=900 where name='wsb';
update user set balance=1010 where name='egon';
update user set balance=1090 where name='ysb';
commit;
#得到的结果如下:
mysql> select * from user;
+----+------+---------+
| id | name | balance |
+----+------+---------+
|  1 | wsb  |     900 |
|  2 | egon |    1010 |
|  3 | ysb  |    1090 |
+----+------+---------+


#出现异常,回滚到原始状态
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之前的结果
mysql> select * from user;
+----+------+---------+
| id | name | balance |
+----+------+---------+
|  1 | wsb  |     900 |
|  2 | egon |    1010 |
|  3 | ysb  |    1090 |
+----+------+---------+
rollback;
#rollback之后的结果
mysql> select * from user;
+----+------+---------+
| id | name | balance |
+----+------+---------+
|  1 | wsb  |    1000 |
|  2 | egon |    1000 |
|  3 | ysb  |    1000 |
+----+------+---------+
commit;


        
在pymysql中使用的伪代码
        
        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

四、存储过程

1、什么是存储过程
存储过程包含了一系列可执行的sql语句,存储过程中存放于mysql中,通过调用它的名字可以
执行器内部的一堆sql

2、三种开发模型
1、
应用程序:只需要开发应用程序的逻辑
mysql:编写好存储过程,以供应用程序使用

优点:开发效率,执行效率高
缺点:考虑到人为因素,两个部门的协同效率不会很高,跨部门沟通困难,从而导致其扩展性差


2、
应用程序:除了开发应用程序的逻辑,还需要编写原生的sql
mysql:

优点:比方式1扩展性高(非技术性)
缺点:
1、开发效率,执行效率都不如方式1
2、编写原生sql太过于复杂,而且需要考虑到sql语句的优化问题

3、
应用程序:开发应用程序的逻辑,不需要编写原生sql,基于别人编写好的框架来处理数据,即ORM
mysql:

优点:不用再编写纯生sql,这意味着开发效率比方式2高,同时兼容方式2扩展性高的好处
缺点:执行效率甚至赶不上方式2

4、创建存储过程

delimiter $$
create procedure p1(
    in m int,
    in n int,
    out res int
)
begin
select tname from teacher where tid > m and tid < n;
set res = 0;
                
end $$
delimiter ;
 
1、直接在mysql中调用
    set @res = 10
    call p1(2,4,@res);
    #查看结果
    select @res;
    
2、在python程序中调用
import pymysql

conn=pymysql.connect(
    host='127.0.0.1',
    port=3306,
    user='root',
    password='123',
    charset='utf8',
    database='db42'
)

cursor = conn.cursor(pymysql.cursors.DictCursor)

cursor.callproc('p1',(2,4,10))  #@_p1_0=2,@_p1_1=4,@_p1_2=10

print(cursor.fetchall())

cursor.excute('select @_p1_2;')
print(cursor.fetchall())

cursor.close()
conn.close()


#存储过程和事务的连用
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 ;



delimiter //
create PROCEDURE p6(
    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 user 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='123',
    charset='utf8',
    database='db42'
)

cursor = conn.cursor(pymysql.cursors.DictCursor)

cursor.callproc('p5',(100,)) @_p5_0 = 100

cursor.excute('select @_p5_0')
print(cursor.fetchall())

cursor.close()
conn.close()

猜你喜欢

转载自www.cnblogs.com/guanzhicheng/p/9037775.html