• 如果关闭一个未打开的游标,则MySQL会报错
• 如果在存储过程和函数中未使用此语句关闭已经打开的游标,则游标会在声明的begin…end语句块执行完之后自动关闭 cursor游标declare语句 • Cursor declare语句用来声明一个游标和指定游标对应的数据集合,通常数据集合是一个select语句• Select_statement代表一个select语句
cursor游标fetch语句 • Cursor fetch语句用来获取游标指定数据集的下一行数据并将各个字段值赋予后面的变量• 数据集中的字段需要和INTO语句中定义的变量一一对应
• 数据集中的数据都fetch完之后,则返回NOT FOUND cursor游标open语句 • Open cursor语句用来打开一个之前已经声明好的游标
Declare condition语句
• Declare condition语句命名特定的错误条件,而该特定错误可以在declare…handler中指定处理方法• Condition_value指定特定的错误条件,可以有以下两种形式
• Mysql_err_code表示MySQL error code的整数 • SQLSTATE sqlstate_value表示MySQL中用5位字符串表达的语句状态 • 比如在MySQL中1051error code表示的是unknown table的错误,如果要对这个错误做特殊处理,可以用三种种方法: • DECLARE CONTINUE HANDLER FOR 1051 • BEGIN • -- body of handler • END; • DECLARE no_such_table CONDITION FOR 1051; • DECLARE CONTINUE HANDLER FOR no_such_table • BEGIN • -- body of handler • END; • DECLARE no_such_table CONDITION FOR SQLSTATE '42S02'; • DECLARE CONTINUE HANDLER FOR no_such_table • BEGIN • -- body of handler • END;Declare handler语句
• Declare handler语句用来声明一个handler来处理一个或多个特殊条件,当其中的某个条件满足时则触发其中的statement语句执行 • Statement可以是一个简单SQL语句,也可以是begin…end组成的多个语句DROP PROCEDURE IF EXISTS teacher_select; delimiter // CREATE PROCEDURE teacher_select () BEGIN DECLARE done INT DEFAULT FALSE ; DECLARE v_tno VARCHAR (15) ; DECLARE v_tname VARCHAR (20) ; DECLARE cur1 CURSOR FOR SELECT tno, tname FROM teacher ; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE ; #当fetch不到数据时,会执行这个,这是一个错误判断,当达到某个条件的时候,就会执行 OPEN cur1 ; FETCH cur1 INTO v_tno, v_tname ; WHILE ! done DO -----#程序逻辑 FETCH cur1 INTO v_tno, v_tname ; END WHILE ;
close cur1; END// delimiter ;
比如:
mysql> select tno,tname from teacher; +------+-----------+ | tno | tname | +------+-----------+ | t001 | 刘阳 | | t002 | 谌燕 | | t003 | 胡明星 | +------+-----------+ 3 rows in set (0.00 sec)
DROP PROCEDURE IF EXISTS teacher_select; delimiter // CREATE PROCEDURE teacher_select () BEGIN DECLARE done INT DEFAULT FALSE ; DECLARE v_tno VARCHAR (15) ; DECLARE v_tname VARCHAR (20) ; DECLARE cur1 CURSOR FOR SELECT tno, tname FROM teacher ; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE ; # OPEN cur1 ; FETCH cur1 INTO v_tno, v_tname ; WHILE ! done DO SELECT v_tno, v_tname ; FETCH cur1 INTO v_tno, v_tname ; END WHILE ; CLOSE cur1 ; END// delimiter ;
mysql> CALL teacher_select (); +-------+---------+ | v_tno | v_tname | +-------+---------+ | t001 | 刘阳 | +-------+---------+ 1 row in set (0.00 sec) +-------+---------+ | v_tno | v_tname | +-------+---------+ | t002 | 谌燕 | +-------+---------+ 1 row in set (0.00 sec) +-------+-----------+ | v_tno | v_tname | +-------+-----------+ | t003 | 胡明星 | +-------+-----------+ 1 row in set (0.00 sec) Query OK, 0 rows affected (0.00 sec) mysql>
• Handler_action子句声明当执行完statement语句之后应该怎么办 • Continue代表继续执行该存储过程或函数 • Exit代表退出声明此handler的begin…end语句块 • Undo参数已经不支持 • Condition_value的值有以下几种: • Mysql_err_code表示MySQL error code的整数 • SQLSTATE sqlstate_value表示MySQL中用5位字符串表达的语句状态 • Condition_name表示之前在declare…condition语句中声明的名字 • SQLWARNING表示所有的警告信息,即SQLSTATE中01打头的所有错误 • NOT FOUND表示查完或者查不到数据,即SQLSTATE中02打头的所有错误 • SQLEXCEPTION表示所有的错误信息 • DECLARE CONTINUE HANDLER FOR 1051 • BEGIN • -- body of handler • END; • • DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02' • BEGIN • -- body of handler • END; • • DECLARE CONTINUE HANDLER FOR SQLWARNING • BEGIN • -- body of handler • END; • • DECLARE CONTINUE HANDLER FOR SQLEXCEPTION • BEGIN • -- body of handler • END; • 当condition发生但没有声明handler时,则存储过程和函数依照如 下规则处理 • 发生SQLEXCEPTION错误,则执行exit退出 • 发生SQLWARNING警告,则执行contine继续执行 • 发生NOT FOUND情况,则执行continue继续执行
DROP PROCEDURE IF EXISTS teacher_insert; delimiter // CREATE PROCEDURE teacher_insert () BEGIN INSERT INTO teacher (tno, tname) ; VALUES ('t004', '胡桃里1') ; INSERT INTO teacher (tno, tname) VALUES ('t001', '胡桃里2') ; INSERT INTO teacher (tno, tname) VALUES ('t005', '胡桃里3') ; END// delimiter ;
执行结果:
符合当condition发生但没有声明handler时,发生SQLEXCEPTION错误,则执行exit退出
mysql> SELECT * FROM teacher ; +------+-----------+ | tno | tname | +------+-----------+ | t001 | 刘阳 | | t002 | 谌燕 | | t003 | 胡明星 | +------+-----------+ 3 rows in set (0.01 sec) mysql> CALL teacher_insert (); ERROR 1062 (23000): Duplicate entry 't001' for key 'PRIMARY' mysql> SELECT * FROM teacher ; +------+------------+ | tno | tname | +------+------------+ | t001 | 刘阳 | | t002 | 谌燕 | | t003 | 胡明星 | | t004 | 胡桃里1 | +------+------------+ 4 rows in set (0.00 sec) mysql>
声明handler,让遇到SQLEXCEPTION 错误23000时,继续执行往下执行
DROP PROCEDURE IF EXISTS teacher_insert2; delimiter // CREATE PROCEDURE teacher_insert2 () BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @done = TRUE ; INSERT INTO teacher (tno, tname) VALUES ('t004', '胡桃里1') ; INSERT INTO teacher (tno, tname) VALUES ('t001', '胡桃里2') ; INSERT INTO teacher (tno, tname) VALUES ('t005', '胡桃里3') ; END// delimiter ;
执行结果:
mysql> SELECT * FROM teacher ; +------+-----------+ | tno | tname | +------+-----------+ | t001 | 刘阳 | | t002 | 谌燕 | | t003 | 胡明星 | +------+-----------+ 3 rows in set (0.00 sec) mysql> CALL teacher_insert2 (); Query OK, 1 row affected (0.08 sec) mysql> SELECT * FROM teacher ; +------+------------+ | tno | tname | +------+------------+ | t001 | 刘阳 | | t002 | 谌燕 | | t003 | 胡明星 | | t004 | 胡桃里1 | | t005 | 胡桃里3 | +------+------------+ 5 rows in set (0.01 sec) mysql>