mysql游标遍历中sql语句出现异常_MySQL中的异常处理,游标
一、異常處理的理解
ERROR 1062 (23000): Duplicate entry ‘2’ for key ‘PRIMARY’
錯誤 4位error code(5位sql statis):錯誤內容
二、異常處理的重要性
沒有異常處理的存儲過程,執行過程中非常難以預測執行結果。
建議:存儲過程中加上異常處理部分。
三、異常處理的實現
異常處理的格式:
DECLARECONTINUE/EXITHANDLER FORSQLSTATE ‘23000’ (錯誤代碼)
1.錯誤是什么?
eg:1062(23000)
2.怎么處理錯誤?
先執行SQL,再執行EXIT/CONTINUE
小結:
針對什么錯誤,首先執行SQL語句,可以是一個begin..end;語句塊;
根據是continue還是exit,確定是接著執行還是退出begin..end;
接著執行的話,就是接著執行出錯的SQL的下一條語句;
如果是退出,就退出這個declare所在的begin…end。
例子1:
DELIMITER $$
CREATE PROCEDURE small_mistake1(
OUT error VARCHAR(5))
BEGIN
DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' --》這是個異常
SET error = '23000'; //用來記錄錯誤發生時的一些信息,異常捕獲、處理
select error;
SET error = '00000';
select error;
INSERT INTO TEAMS VALUES(2,27,'third');
SET error = '23001';
END$$
DELIMITER ;
執行結果:
mysql> call small_mistake1(@a); --》上來直接就是select error,因為先執行sql
+-------+
| error |
+-------+
| NULL |
+-------+
1 row in set (0.00 sec)
+-------+
| error |
+-------+
| 00000 |
+-------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
mysql> select @a; --》
+-------+
| @a |
+-------+
| 23001 |
+-------+
1 row in set (0.00 sec)
===例子2:
CREATE TABLE test.t (s1 INT, PRIMARY KEY (s1));
delimiter $$
CREATE PROCEDURE handlerdemo ()
BEGIN
DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @x2 = 1;
SET @x = 1;
INSERT INTO test.t VALUES (1); ---》能執行
SET @x = 2; --》報錯,因為@x==1
INSERT INTO test.t VALUES (1);
SET @x = 3;
END$$
delimiter ;
CALL handlerdemo()
執行結果:
mysql> select @x2; --》捕獲到異常,就令x2=1
+------+
| @x2 |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
mysql> select @x; --》set @x=3
+------+
| @x |
+------+
| 3 |
+------+
1 row in set (0.00 sec)
===例子3:
DELIMITER $$
CREATE PROCEDURE small_mistake2(
OUT error VARCHAR(5))
BEGIN
DECLARE EXIT HANDLER FOR SQLSTATE '23000' --》EXIT直接退出begin..end
SET error = '23000';
select error;
SET error = '00000';
select error;
INSERT INTO TEAMS VALUES(2,27,'third');
--》此語句出錯,捕獲到異常后,因為是exit,所以不會再執行下面的set error='23001'語句
SET error = '23001';
END$$
DELIMITER ;
mysql> call small_mistake2(@a); --》先執行sql
+-------+
| error |
+-------+
| NULL |
+-------+
1 row in set (0.00 sec) --》捕獲到異常
+-------+
| error |
+-------+
| 00000 |
+-------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
mysql> select @a; ---》證明沒有執行set error='23001'
+-------+
| @a |
+-------+
| 23000 |
+-------+
1 row in set (0.00 sec)
===例子4:一個begin后面可以接多個DECLARE
DELIMITER $$
CREATE PROCEDURE small_mistake3(
OUT error VARCHAR(5))
BEGIN
DECLARE CONTINUE HANDLER FOR SQLSTATE '23000'
SET error = '23000';
DECLARE CONTINUE HANDLER FOR SQLSTATE '21S01'
SET error = '21S01';
INSERT INTO TEAMS VALUES(2,27,'third',5);
END$$
DELIMITER ;
mysql> call small_mistake3(@error);
Query OK, 0 rows affected (0.00 sec)
mysql> select @error;
+--------+
| @error |
+--------+
| 21S01 |
+--------+
1 row in set (0.00 sec)
四、錯誤捕獲快捷方式
異常處理的好處:
①出錯不報錯
②出錯可以進行處理;記錄出錯時的一些信息
③處理所有的錯誤:
===例子1:
DELIMITER $$
CREATE PROCEDURE small_mistake5(
OUT error VARCHAR(5))
BEGIN
DECLARE CONTINUE HANDLER FOR SQLWARNING,NOT FOUND,SQLEXCEPTION
---》錯誤是1開頭的賦給SQLWARNING,2開頭的NOT FOUND,其他給SQLEXCEPTION
SET error = 'xxxxx';
INSERT INTO teams VALUES(2,27,'third');
END$$
DELIMITER ;
mysql> call small_mistake5(@a);
Query OK, 0 rows affected (0.00 sec)
mysql> select @a;
+-------+
| @a |
+-------+
| xxxxx |
+-------+
1 row in set (0.00 sec)
===忽略一個錯誤:
忽略一個條件
DECLARE CONTINUE HANDLER FOR SQLWARNING BEGIN END;
–》碰到1開頭的就過。
五、異常處理嵌套問題
例子1:增加程序的可讀性。
DELIMITER $$
CREATE PROCEDURE small_mistake6(
OUT error VARCHAR(5))
BEGIN
DECLARE non_unique CONDITION FOR SQLSTATE '23000';
DECLARE CONTINUE HANDLER FOR non_unique
begin
SET error = '23000';
select error;
end;
INSERT INTO TEAMS VALUES(2,27,'third');
END$$
DELIMITER ;
mysql> call small_mistake6(@error);
+-------+
| error |
+-------+
| 23000 |
+-------+
1 row in set (0.01 sec)
例子2:異常處理的嵌套
DELIMITER $$
CREATE PROCEDURE small_mistake7()
BEGIN
DECLARE CONTINUE HANDLER FOR SQLSTATE '23000'
SET @processed = 100;
BEGIN
DECLARE CONTINUE HANDLER FOR SQLSTATE '21000'
SET @processed = 200;
INSERT INTO TEAMS VALUES(2,27,'third');
--》出錯,假設能被內層的捕獲,就執行200;若不能被內層捕獲,內層的begin...end就廢了,就執行外層100
END;
END$$
DELIMITER ;
mysql> call small_mistake7;
Query OK, 0 rows affected (0.00 sec)
mysql> select @processed;
+------------+
| @processed |
+------------+
| 100 |
+------------+
1 row in set (0.00 sec)
====小結
當有多層begin…end的時候,最好每層都有自己完善的異常處理。自己異常,自己這層去處理。
六、游標 CURSOR
游標:處理結果集。多行多列
====例子1:
DELIMITER $$
CREATE PROCEDURE number_of_players(
OUT pnumber INTEGER
)
BEGIN
DECLARE a_playerno INTEGER; --》變量1
DECLARE FOUND BOOLEAN DEFAULT TRUE; --》變量2
DECLARE c_players CURSOR FOR --》聲明游標(將游標和sql語句關聯起來)
SELECT playerno FROM PLAYERS;
DECLARE CONTINUE HANDLER FOR NOT FOUND --》異常處理,所有的以2開頭的錯誤
SET FOUND = FALSE; --》異常處理后FOUND變為false
SET pnumber = 0;
OPEN c_players; --》打開游標(將游標和結果集聯系起來)
FETCH c_players INTO a_playerno; --》fetch...into相當于select into
WHILE FOUND DO
SET pnumber = pnumber + 1;
FETCH c_players INTO a_playerno; --》循環中的fetch...into,依次指向結果集的一個
END WHILE;
CLOSE c_players;
END$$
DELIMITER ;
mysql> call number_of_players(@pnumber);
Query OK, 0 rows affected (0.00 sec)
mysql> select @pnumber;
+----------+
| @pnumber |
+----------+
| 14 |
+----------+
1 row in set (0.00 sec)
游標處理方式小結:
定義游標:將一個游標和一個select進行關聯;
打開游標:將一個游標和一個結果集關聯,執行了select;
獲取游標(獲取結果集):需要使用循環進行游標的獲取。
{注意:當獲取到最后一個結果集時,再次執行循環的時候,會報錯,這個錯誤以2開頭,
這個時候,需要定義一個對2開頭的錯誤的捕獲:
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET FOUND = FALSE; }
關閉游標:結果集消失
資源釋放。
七、存儲過程權限問題
mysql>select ROUTINE_NAME,ROUTINE_SCHEMA,ROUTINE_TYPE from ROUTINES where ROUTINE_SCHEMA in('test','TENNIS');
GRANT EXECUTE --》授予執行權限
ON PROCEDURE number_penalties
TO 'u1'@'%';
[root@mysqlstudy ~]# mysql -uu1 -p12345678
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 7
Server version: 5.7.10 MySQL Community Server (GPL)
Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> use TENNIS;
Database changed
mysql> call number_penalties(44,@pnumber);
Query OK, 0 rows affected (0.01 sec)
mysql> select @pnumber;
+----------+
| @pnumber |
+----------+
| 3 |
+----------+
1 row in set (0.00 sec)
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的mysql游标遍历中sql语句出现异常_MySQL中的异常处理,游标的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: AI应用开发基础傻瓜书系列3-激活函数
- 下一篇: centos7mysql语句创建表格_C