***事务管理
事务中的语句要么都执行,要么都不执行
*开启事务 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;