数据库—事务与存储过程

***事务管理

事务中的语句要么都执行,要么都不执行

*开启事务  start transaction

*提交事务  commit      (之前的mysql都是直接提交的,而在事务中则需要使用commit语句进行提交)

*如果不想提交事务,取消事务(回滚) rollback    (只针对未提交的事物,已提交的事务是不能进行回滚的)

事务有很严格的定义,它必须同时满足4个特性(ACID标准):原子性、一致性、隔离性、持久性

**事务的隔离级别

  数据库是多线程并发访问的,很容易出现多个线程并发使用的情况

 可能产生的情况:

  脏读:一个事务读取了另一个事务未提交的数据

  不可重复读:事务中两次查询的结果不一致,因为查询过程中其他事务做了更新的操作

  幻读,又称虚读,指一个事务内两次查询中数据条数不同,因为查询过程中其他事务做了插入操作

 

* 为事务设置隔离级别的语法:set session transaction isolation level 隔离级别

    session 表示当前会话,transaction 表示事务 ,isolation 表示隔离 , level 表示级别

 *查询当前会话的隔离级别:select @@transaction_isolation

  读未提交(read uncommitted):事务隔离中的最低级别,该级别下会出现脏读,这是相当危险的。开发过程中很少使用

  读提交(read commited):大多数数据库管理系统默认的隔离级别。该级别下只能读取其他事务已经提交的内容,可以避免脏读,但不能避免重复读和幻读

   可重复读(repeatable read):mysql默认的事务隔离级别。可以避免脏读和不可重复读。通过版本更新也可避免幻读

  可串行化(serializable):事务的*别。强制事务进行排序,以此解决脏读等问题,这个级别非常耗时,并且可能导致大量的超时现象和锁竞争,实际很少使用

 *创建存储过程:create procedure sp_name ([proc_parameter]) [characteristics···]routine_body

    (create procedure 是创建存储过程的关键字,sp_name存储过程名称,

    proc_parameter指定存储过程参数列表,该参数列表的形式:[in|out|inout])param_name type

              in 表示输入参数,out 表示输出参数,inout 表示即可输入又可输出;param_name 表示参数名称;type 表示参数类型,可以是MySQL库中的任意类型

delimiter //    将MySQL的结束符设置为//,以end // 结束存储过程;存储过程定义完毕后再使用 delimiter ; 恢复默认结束符,delimiter 也可指定其他符号作为结束符。

注:delimiter 与要设定的结束符之间一定要有一个空格,否则设定无效

**变量的使用

*定义变量: declare var_name[,varname]···data_type[default value];

    var_name 为局部变量的名称,default value 子句给变量提供一个默认值。该值除了可以被声明为一个常数外,还可以被指定为一个表达式。如果没有default子句,变量的初始值为null。

例:定义一个名称为myvariable的变量,类型为int类型,默认值为100

  declare myvariable int default 100;

*定义变量之后可以给变量赋值:set var_name = expr[,var_name=expr]···;

例:声明变量var1、var2、var3,数据类型为int:declare var1,var2,var3 int;

                      set var1=10,var2=20;

                      set var3=var2+var1;

*select ··· into 为一个或多个变量赋值:select col_name [···] into var_name[···] table_expr;

    col_name 表示字段名称;var_name 表示定义的变量名称;table_expr 表示查询条件表达式,包括表名称和where子句

 

 例:声明变量s_grade 和 s_gender :declare s_grade float;

                 declare s_gender char(2);

                 select grade,gender into s_grade,s_gender

                 from student where name = 'rose';

*定义条件,使用declare语句:declare condition_name condition for [condition_type];

              // condition_type 的两种形式;

              [condition_type] : 

              sqlstate [value] sqlstate_value|mysql_error_code

    condition_name表示所定义的条件的名称;condition_type表示条件的类型;sqlstate_value和mysql_error_code为数值类型的错误代码。如:ERROR1142(42000) ,sqlstate_value的值是42000,mysql_error_code的值是1142

*定义处理程序:declare handler_type handler for condition_value[,···] sp_statement

        handler_type:

             continue|exit|undo

         condition_value:

          |condition_name

          |sqlwarning 

          |not found

          |sqlexception

          |mysql_error_code

      注:handler_type为错误处理方式,参数取三个值:continue、exit、undo。continue 表示遇到错误不处理,继续执行;exit 表示遇到错误马上退出;undo 表示遇到错误后撤回之前的操作,MySQL暂时不支持这种操作。sp_statement参数为程序语句段,表示在遇到定义的错误时,需要执行的存储过程;condition_value 表示错误类型

*光标的使用:(在编写存储过程中,查询语句可能会返回多条记录,如果数据量非常大,则需要使用光标来逐条读取查询结果集中的记录。光标是一种用于轻松处理多行数据的机制。)

#光标的声明(光标必须声明在声明变量、条件之后,声明处理程序之前): declare cursor_name cursor for select_statement;

    cursor_name 表示光标的名称,select_statement 表示select语句的内容,返回一个用于创建光标的结果集

  例:声明一个名为 cursor_name 的光标:declare cursor_name cursor for select s_name,s_gender from student;

#打开光标:open cursor_name

#光标的使用:(使用光标之前首先要打开光标): fetch cursor_name into var_name[,var_name]···

    cursor_name表示参数的名称;var_name表示将光标中的select语句查询出来的信息存入该参数中,需要注意的是,var_name 必须在声明光标之前就定义好。

  例:使用名称为cursor_student的光标,将查询出来的信息存入s_name和s_gender中: sursor_student into s_name,s_gender;

#光标的关闭:close cursor_name;      (如果没有明确的关闭光标,它会在其声明的复合语句的末尾被关闭)

**流程控制的使用

MySQL中流量控制语句包括:if语句、case语句、loop语句、while语句、leave语句、iterate语句、repeat语句和while语句。每个流程中可能包含一个单独语句,也可能使用begin···end构造的复合语句,可以嵌套

# if语句:如果满足某种条件,就根据判断的结果为true或false执行相应的语句

  if expr_condition then statement_list

    [elseif expr_condition then statement_list]

    [else statement_list]

  end if

    :expr_condition 表示判断条件,statement_list表示SQL语句列表,它可以包括一个或多个语句,如果expr_condition求值为true,相应的SQL语句就会被执行;如果没有expr_condition匹配,则else子句里的语句列表被执行

# case语句:是另一个进行条件判断的语句,该语句有两种格式,

第一种:

  case case_expr

    when when_value then statement_list

    [when when_value then statement_list] ···

    [else ststement_list]

  end case

    :case_expr 表示条件判断的表达式,决定了哪一个when子句会被执行;when_value 表示表达式可能的值,如果某个when_value表达式与case_expr表达式结果相同,则执行对应then关键字后的statement_list中的语句,statement_list 表示不同when_value值的执行语句。

第二种:

  case 

    when expr_condition then statement_list

    [when expr_condition then statement_list]

    [else statement_list]

  end case;

注:存储过程里的case语句不能有else null子句,并且用end case 替代end来终止

# loop语句:用来重复执行某些语句,与if和case语句相比,loop只是创建一个循环操作的过程,并不进行条件判断。loop内的语句一直重复执行直到跳出循环语句。

  [loop_label:] loop

    statement_list

  end loop [loop_label]

    loop_label 表示loop语句的标注名称,该参数可以省略。statement_list 表示需要循环执行的语句

例:declare id int default 0;

  add_loop:loop

  set id = id+1;

    if id>=10 then leave add_loop;

    end if;

  end loop add_loop;

# leave 语句:当不满足循环条件时,需要使用leave语句退出循环,leave语句用于退出任何被标注的流程控制构造

  leave label;

    label 表示循环的标志。通常情况下,leave语句与begin···end、循环语句一起使用

# iterate 语句:iterate的意思是再循环,iterate语句用于将执行顺序转到语句段的开头处

  iterate lable

    lable 表示循环的标志,注:iterate语句只可以出现在loop、repeat和while语句内

# repeat语句:用于创建一个带有条件判断的循环过程,每次语句执行完毕之后,会对条件表达式进行判断,如果表达式为真,则循环结束;否则重复执行循环中的语句

  [repeat_lable:] repeat

    statement_list

  until expr_condition

  end repeat [repeat_lable]

    repeat_lable为repeat语句的标注名称,该参数是可选的,repeat语句内的语句或语句群被重复,直到 expr_condition 为真

# while语句:创建一个带条件判断的循环过程,与repeat 不同的是,while在语句执行时,先对指定表达式进行判断,如果为真,则执行循环内的语句,否则退出循环

  [while_lable:] while expr_condition do 

    Statement_list

  end while [while_lable]

    while_lable 为while语句的标注名称;expr_condition 为进行判断的表达式,如果表达式结果为真,while语句内的语句或语句群被执行,直至expr_condition为假,退出循环

**存储过程的使用

# 调用存储过程(存储过程有很多调用方法。存储过程必须使用call语句调用,并且存储过程和数据库相关,如果要执行其他数据库中的存储过程,需要指定数据库名称):call sp_name([parameter[,···]])

    sp_name 为存储过程的名称,parameter 为存储过程的参数

# 查看存储过程:

1、show status 语句查看存储过程的状态:show {procedure|function} status [like'pattern']

    procedure和function分别表示查看存储过程和函数,like表示匹配的名称

2、show create 语句查看存储过程的状态:show create {procedure|function} sp_name

    类似于show create table,它返回一个可用来重新创建已命名子程序的确切字符串

3、从information_schema.Routines表中查看存储过程的信息

  select * from information_schema.Routines

  where routine_name='CountProcl' and routine_type='procedure'\G;

  注:在information_schema数据库下的Routines表中,存储所有存储过程的定义。使用select语句查询Routine 表中的存储过程的定义时,一定要使用ROUTINE_NAME字段指定存储过程的名称,否则将查询出所有存储过程的定义。

# 修改存储过程:alter {procedure|function} sp_name [characteristic···]

  sp_name 表示存储过程或函数的名称;characteristic表示要修改存储过程的哪个部分,characteristic有8部分

# 删除存储过程:drop {procedure|function}[if exists] sp_name

  sp_name 为要移除的存储过程的名称。if exists 表示如果程序不存在,它可以避免产生错误,产生一个警告。该警告可以使用show warnings 进行查询

  例:删除存储过程CountProc1:drop procedure CountProc1;

 

上一篇:COUNT(expr) 函数学习


下一篇:MySQL的SQL语句 - 数据操作语句(13)- 子查询(13)