一、游标使用
二、异常处理
三、例题
一、游标使用
游标:(一次遍历,多次处理)。对结果集的每一行都做处理
1.select 多行多列/单列 into 变量
2.当结果集是多行多列的时候
循环处理最好
游标使用步骤:
1、声明游标:
DECLARE a_playerno CURSOR FOR
SELECT playerno FROM PLAYERS;(游标是跟SQL语句关联到一起的-------相当于给结果集起了名字)
2、打开游标:执行SQL语句(游标跟SQL语句的结果集关联起来)
3、提取游标:使用循环获取游标,获取结果集
FETCH a_playerno INTO 变量(FETCH 等同于SELECT INTO)
当把最后一行数据fetch之后,再去fetch时,就会找不到数据,然后会报’200‘错误,
此时需要定义一个对2开头的错误捕获 DECLARE CONTINUE HANDLER FOR NOT FOUND SET FOUND=FALSE;
4、关闭游标:close a_playerno
游标使用前提条件:
grant execute ---------------对存储过程的执行权限给用户
on procedure number_penalties
to 'u1'@'%';
二、存储函数中的异常处理:
没有异常处理,只要碰到错误,就退出,所以执行过程非常难以预测执行结果
异常处理:碰到错误,怎么去处理
DECLARE EXIT/CONTINUE HANDLER FOR SQLATATE '23000'/1062
1.错误-------------出错不报错
1062 (23000)---错误编号
2.处理-------------可以进行处理
异常处理部分跟其下面一条SQL语句可以看做一个整体////////用来记录错误发生时一些信息,也可以用begin end
步骤:
1.执行存储过程,并且定义了23000的异常处理
2.首先不执行第一条SQL语句,先是去执行第二条及其后面的,如果在某一条SQL语句中报的是23000的错误,则返回异常处理部分
3.异常处理部分捕获错误,就去执行其下面的一条SQL语句
4.执行完SQL语句之后,有两个选择(1)退出存储过程--exit (2)接着执行错误SQL语句的下一条--continue
当我们不想为每个错误都定义一个处理程序时,可以使用三个处理程序------SQLWARNING---NOT FOUND---SQLEXCEPTION
1.以’01’开头的所有sqlstate码都对应SQLWARNING处理程序;
2.以’02’开头的所有sqlstate码都对应NOT FOUND 处理程序;
3.那些不以’01’或’02’开头的所有sqlstate码都对应SQLEXCEPTION处理程序
2.DECLARE EXIT/CONTINUE HANDLER FOR SQLWARNING BEGIN END--------捕获以1开头错误不处理
异常处理嵌套问题
1.我们不知道23000具体表示什么意思时,可以起一个名字,相当于注释的意思:
DECLRE non_unique CONDITION FOR SQLSTATE '23000';
DECLARE CONINUE HANDLER FOR non_unique
2.当有多层begin..end时,每层都要有完善的异常处理
自己的异常,自己这层去处理
例题:
1.查询某个专业的学生
2.如果学生的总学分小于50,就修改该学生的年级,自动降级;
DROP TABLE youbiao;
CREATE TABLE youbiao(
NAME VARCHAR(10) primary key,
major VARCHAR(10),
nianji INT,
score INT
)CHARACTER SET gbk;
INSERT INTO youbiao VALUES
('张三','计算机',1,78),
('李四','统计',2,56),
('王六','信息',2,90),
('娜娜','统计',3,34),
('乐乐','计算机',4,78);
DROP PROCEDURE IF EXISTS decrease_nianji;
DELIMITER $$
CREATE PROCEDURE decrease_nianji(IN maj VARCHAR(10))
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE s_name VARCHAR(10);
DECLARE s_score INT;
-- 声明在游标中使用的变量
DECLARE cur1 CURSOR FOR SELECT NAME,score FROM youbiao WHERE major=maj;
-- 创建游标
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
-- 游标异常处理部分
OPEN cur1;-- 打开游标
-- 对提取的数据进行遍历
chengji_loop:LOOP
FETCH cur1 INTO s_name,s_score;
IF done -- 异常处理
THEN
LEAVE chengji_loop ;
END IF ;
IF s_score<50
THEN
UPDATE youbiao SET nianji=nianji-1 WHERE NAME=s_name;
END IF ;
END LOOP ;
CLOSE cur1 ;-- 关闭游标
END $$
DELIMITER ;
CALL decrease_nianji('统计');