zoukankan      html  css  js  c++  java
  • mysql数据库—事务、存储过程

    视图

    什么是试图

    试图是由一张表或多张表的查询结果构成的一张虚拟表

    为什么使用视图

    我们在使用多表查询时 我们的sql语句可能会非常的复杂,如果每次都编写一遍sql'的话无疑是一件麻烦的事情,这时候就可以使用视图来避免多次编写sql的问题;

    简答的说可以帮我们节省sql的编写,

    视图的另一个作用是,可以不同的视图来展示开放不同数据的访问

    例如,同一张工资表,老板可以查看全部,部门主管可以查看该部门所有人,员工只能看自己的一条记录

    使用方法

    语法:
    create [or replace] view view_name as 查询语句;
    or replace 如果视图已经存在了 就替换里面的查询语句;
    
    # 修改视图
    alter view view_name  as 新的语句;
    
    # 删除视图
    drop view  view_name;
    
    # 查看
    desc view_name;
    show create view view_name;
    
    
    
    # 限制可以查看的记录 
    create table salarys(id int,name char(10),money float);
    insert into salarys values(1,"张三丰",50000),(2,"张无忌",40000);
    # 创建视图  限制只能查看张无忌的工资
    create view zwj_view as select *from salarys where name = "张无忌";
    
    # 简化sql编写
    create table student(
      s_id int(3),
      name varchar(20), 
      math float,
      chinese float 
    );
    insert into student values(1,'tom',80,70),(2,'jack',80,80),(3,'rose',60,75);
    
    create table stu_info(
      s_id int(3),
      class varchar(50),
      addr varchar(100)
    );
    insert into stu_info values(1,'二班','安徽'),(2,'二班','湖南'),(3,'三班','黑龙江');
    # 查询班级和学员的对应关系做成一个视图  方便后续的查询 
    create view class_info as select student.s_id,name,class from student join stu_info on student.s_id = stu_info.s_id;
    
    select *from class_info;
    

    注意: 修改视图 也会引起原表的变化,我们不要这么做,视图仅用于查询

    触发器

    什么是触发器

    触发器是一段与表有关的mysql程序
    当这个表在某个时间点发生了某种事件时 将会自动执行相应的触发器程序

    创建触发器

    语法:

    create trigger t_name  t_time t_event on  table_name for each row 
    begin
    #sql语句。。。。。:
    end
    

    案例:

    #准备数据
    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
    );
    
    #需求: 当插入cmd表 的时候 如果执行状态时失败的 那么将信息插入到errlog中
    
    # 将结束符设置为|
    delimiter |
    create trigger cmd_insert after insert on cmd for each row
    begin
    if new.success = "no" then
    	insert into errlog values(null,new.cmd,new.sub_time);
    end if;
    end|
    # 在还原之前的结束符 
    delimiter ;
    
    
    # 创建一个触发器 叫cmd_insert  
    # 触发器会在 插入数据到cmd表后执行 
    # 当插入的记录的success为no时 自动插入记录到errlog中 
    
    
    # 错误原因 遇到分号自动提交了  , 需要重定义  行结束符  
    delimiter |
    
    # 删除触发器
    drop trigger cmd_insert;
    
    #查看 所有触发器
    show triggers;
    
    # 查看某个触发器的语句 
    show create trigger t_name;
    

    事务

    什么是事务

    事务就是一系列sql语句的组合,是一个整体

    为什么要有事务

    很多时候一个数据操作,不是一个sql语句就完成的,可能有很多个sql语句,如果部分sql执行成功而部分sql执行失败将导致数据错乱!

    例如转账操作,

    1.从原有账户减去转账金额

    2.给目标账户加上转账金额

    若中间突然断电了或系统崩溃了,钱就不翼而飞了!

    事务的四个特性:

    原子性:

    事务是一组不可分割的单位,要么同时成功,要么同时不成功

    一致性:

    事物前后的数据完整性应该保持一致,(数据库的完整性:如果数据库在某一时间点下,所有的数据都符合所有的约束,则称数据库为完整性的状态);

    隔离性:

    事物的隔离性是指多个用户并发访问数据时,一个用户的事物不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离

    持久性:

    持久性是指一个事物一旦被提交,它对数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响

    使用事务

    start transaction: 开启事物,在这条语句之后的sql将处在同一事务,并不会立即修改数据库

    commit:提交事务,让这个事物中的sql立即执行数据的操作,

    rollback:回滚事务,取消这个事物,这个事物不会对数据库中的数据产生任何影响

    #开启事务 
    start transaction 
    #sql 语句......
    #sql 语句......
    rollback  #回滚操作   即撤销没有提交之前的所有操作 
    #sql 语句......
    commit  #提交事务 一旦提交就持久化了
    
    
    CREATE TABLE `account` (
      `name` char(10),
      `money` float  
    );
    
    start transaction;
    update account set money = money - 100 where name = "一只穿云箭";
    update account set money = money + 100 where name = "千军万马";
    commit;
    
    
    # 何时应该回滚  当一个事务执行过程中出现了异常时
    # 何时提交   当事务中所有语句都执行成功时
    
    # 保存点 可以在rollback指定回滚到某一个savepoint ,也就是回滚一部分  
    
    start transaction;
    update account set money = money - 100 where name = "一只穿云箭";
    savepoint a;
    update account set money = money - 100 where name = "一只穿云箭";
    savepoint b;
    update account set money = money - 100 where name = "一只穿云箭";
    savepoint c;
    
    select * from account;
    
    # 回滚至某个保存点a,b,c 
    rollback to 保存点名称(a,b,c)
    
    read committed
    
    

    修改隔离级别

    数据库使用者可以控制数据库工作在哪个级别下,就可与防止不同的隔离性问题

    read uncommitted --不做任何隔离,可能脏读,幻读

    read committed----可以防止脏读,不能防止不可重复读,和幻读,

    Repeatable read --可以防止脏读,不可重复读,不能防止幻读

    Serializable--数据库运行在串行化实现,所有问题都没有,就是性能低

    修改全局的  
     set global transaction isolation level read committed;
     或者:
     set @@tx_isolation = "asasasasas-read";
     修改局部
     set session transaction isolation level read committed;
    
     @@系统内置变量
     @表示用户自定义的变量
     
     # 修改后重新连接服务器生效
    

    存储过程

    什么是存储过程

    存储过程是一组任意的sql语句集合,存储在mysql中,调用存储过程时将会执行其包含的所有sql语句;与python中函数类似;

    为什么使用存储过程

    回顾触发器与视图都是为了简化应用程序中sql语句的书写,但是还是需要编写,而存储过程中可以包含任何的sql语句,包括视图,事务,流程控制等,这样一来,应用程序可以从sql语句中完全解放,mysql可以替代应用程序完成数据相关的的逻辑处理!

    那我们以后都是用存储过程不就完了?

    三种开发方式对比

    1.应用程序仅负责业务逻辑编写,所有与数据相关的逻辑都交给mysql来完成,通过存储过程(推荐使用)

    优点:

    应用程序与数据处理完解耦合,一堆复杂的sql被封装成了一个简单的存储过程,考虑到网络环境因素,效率高

    应用程序开发者不需要编写sql语句,开发效率高

    缺点:

    python语法与mysql语法区别巨大,学习成本高

    并且各种数据库的语法大不相同,所以移植性非常差

    应用程序开发者与BDA的跨部门沟通成本高,造成整体效率低

    2.应用程序不仅编写业务逻辑,还需要编写所有的sql语句

    优点:扩展性高,对于应用程序开发者而言,扩展性和维护性相较于第一种都有所提高

    缺点:sql语句过于复杂,导致开发效率低,且需要考虑sql'优化问题

    3.应用程序仅负责业务逻辑,sql语句的编写交给ORM框架,(常用解决方案)

    优点:应用程序开发者不需要编写sql语句,开发效率高

    缺点:执行效率低,由于需要将对象的操作转化为sql语句,且需要通过网络发送大量sql

    创建存储过程

    create procedure pro_name(p_Type p_name data_type)
    begin
    sql语句......流程控制
    end
    

    p_type 参数类型

    in 表示输入参数

    out 表示输出参数

    inout表示既能输入又能输出

    p_name 参数名称

    data_type 参数类型 可以是mysql支持的数据类型

    案例:使用存储过程完成对student表的查询

    delimiter //
    create procedure p1(in m int,in n int,out res int)
    begin
        select *from student where chinese > m and chinese < n;
        #select *from student where chineseXXX > m and chinese < n; 修改错误的列名以测试执行失败
        set res = m+n;
    end//
    delimiter ;
    set @res = 0;
    #调用存储过程
    call p1(70,80,@res);
    #查看执行结果
    select @res;
    

    存储过程中的事务应用

    存储过程中支持任何的sql语句包括事务!

    案例:模拟转账中发生异常,进行回滚

    delimiter //
    create PROCEDURE transfer(in aid int,in bid int,in m float,out res int)
    BEGIN 
        DECLARE exit handler for sqlexception 
        BEGIN 
            # ERROR 
            set res = 1; 
            rollback; 
        END; 
        # exit 也可以换成continue 表示发生异常时继续执行
        DECLARE exit handler for sqlwarning 
        BEGIN 
            # WARNING 
            set res = 2; 
            rollback; 
        END; 
    
        START TRANSACTION; 
        update account set money = money - 1000 where id = 1;
        update account set moneys = money - 1000 where id = 1; # moneys字段导致异常
        COMMIT; 
    
        # SUCCESS 
        set res = 0; #0代表执行成功
    END //
    delimiter ;
    
    
    #在mysql中调用存储过程
    set @res=123;
    call transfer(1,2,90,@res);
    select @res;
    
  • 相关阅读:
    C#——面向对象,常用类
    C#——基础
    C#——winform
    Oracle——PL/SQL,存储过程/函数,java连接Oracle操作存储过程/函数,触发器
    Oracle——数据处理(增删改查),创建表与管理表,视图,索引,同义词
    Oracle——集合运算
    PoisonTap
    在Ubuntu上安装LAMP(Apache、Mysql、Php)
    "Unable to locate package lrzsz"的解决办法
    OtterCTF
  • 原文地址:https://www.cnblogs.com/gaohuayan/p/11197007.html
Copyright © 2011-2022 走看看