加入收藏 | 设为首页 | 会员中心 | 我要投稿 银川站长网 (https://www.0951zz.com/)- 云通信、基础存储、云上网络、机器学习、视觉智能!
当前位置: 首页 > 站长学院 > MySql教程 > 正文

探讨 MySQL 中存储过程的条件处理与例外情况处置实例

发布时间:2023-10-21 14:09:17 所属栏目:MySql教程 来源:
导读:小编给大家分享一下MySQL中存储过程定义条件和异常处理的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!查看调用存储过程时的报错代码mysql> select * from test;+------+--------+| id

小编给大家分享一下MySQL中存储过程定义条件和异常处理的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!

查看调用存储过程时的报错代码

mysql> select * from test;

+------+--------+

| id  | name  |

+------+--------+

|  10 | neo   |

|  10 | neo   |

|  20 | John  |

|  30 | Lucy  |

|  40 | Larry |

|  50 | Lilly |

|  60 | Carlos |

|  70 | Jason |

+------+--------+

8 rows in set (0.00 sec)

mysql> show create procedure p_test\G

*************************** 1. row ***************************

          Procedure: p_test

           sql_mode: NO_ENGINE_SUBSTITUTION

   Create Procedure: CREATE DEFINER=`root`@`localhost` PROCEDURE `p_test`(in v_id int)

begin

set @c='insert into test values(?,?)';

select id into @a from test where id=v_id;

select @a;

end

character_set_client: utf8

collation_connection: utf8_general_ci

 Database Collation: latin1_swedish_ci

1 row in set (0.00 sec)

mysql> call p_test(10);

ERROR 1172 (42000): Result consisted of more than one row

去官网查看对应的存储过程异常代码

Error: 1172 SQLSTATE: 42000 (ER_TOO_MANY_ROWS)

Message: Result consisted of more than one row

在存储过程里面定义异常

mysql> delimiter $$

mysql> create procedure p_test(in v_id int)

   -> begin

   -> /* Declare Conditions */

   -> DECLARE too_many_rows CONDITION FOR 1172;

   -> /* Declare Exception Handlers, usually with set actions */

   -> /* usually with set actions, the following handler has two forms,

  /*> one with begin .. end statements, and the other without */

   -> DECLARE EXIT HANDLER FOR too_many_rows

   -> BEGIN

   -> select 'too many rows';

   -> END;

   -> set @c='insert into test values(?,?)';

   -> select id into @a from test where id=v_id;

   -> select @a;

   -> end$$

Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;

mysql> call p_test(10);

+---------------+

| too many rows |

+---------------+

| too many rows |

+---------------+

1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

DECLARE ... HANDLER 语句指定处理一个或多个条件的句柄。如果这些条件之中有一个条件触发了,则指定的语句会执行,执行的语句可以是一个简单的语句如SET var_name = value,也可以是使用BEGIN ... END格式的复杂语句。

句柄声明必须出现在变量或条件声明之后。

句柄动作的值指明了句柄执行的动作:

CONTINUE: 继续执行现有的程序

EXIT: 终止执行句柄声明的BEGIN ... END语句,即使条件发生在内部的块中

UNDO: 目前尚不支持

DECLARE ... HANDLER条件的值标明了激活句柄的特定条件或类别。有如下形式:

mysql错误码(mysql_error_code): 一种MySQL内部的标明MySQL错误代码的数字码,例如 1051 标明“unknown table”:

DECLARE CONTINUE HANDLER FOR 1051

 BEGIN

  -- body of handler

 END;

不要使用MySQL错误代码 0 ,因为它代表了成功而不是错误条件。

SQLSTATE [VALUE] sqlstate_value: 一种长度为5的字符串,标示了SQLSTATE的值,例如 '42S01' 标明 “unknown table”:

DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02'

 BEGIN

  -- body of handler

 END;

不要使用以'00'开头的SQLSTATE的值,因为这些值代表了成功而不是错误条件。

在DECLARE ... CONDITION中声明的条件名称,条件名称可以关联MySQL错误代码或SQLSTATE的值。

/* 声明条件 */

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;

复制代码

SQLWARNING: 以'01'开头的SQLSTATE的值的简写

DECLARE CONTINUE HANDLER FOR SQLWARNING

 BEGIN

  -- body of handler

 END;

NOT FOUND: 以'02'开头的SQLSTATE的值的简写,这和游标的上下文有关,用来控制当游标达到数据集的末尾时的数据库动作。如果没有任何行是可用的状态,No Data条件会伴随'02000'的SQLSTATE发生。想要检测到这个条件,需要设定一个针对NOT FOUND条件的句柄

DECLARE CONTINUE HANDLER FOR NOT FOUND

 BEGIN

  -- body of handler

 END;

SQLEXCEPTION: 不以'00', '01', or '02'开头的SQLSTATE的值的简写

DECLARE CONTINUE HANDLER FOR SQLEXCEPTION

 BEGIN

  -- body of handler

 END;

创建测试表

MariaDB [test]> create table actor(actor_id int,first_name varchar(25),last_name varchar(25));

Query OK, 0 rows affected (0.14 sec)

MariaDB [test]> alter table actor add primary key(actor_id);

Query OK, 0 rows affected (0.19 sec)        

Records: 0 Duplicates: 0 Warnings: 0

MariaDB [test]> desc actor;

+------------+-------------+------+-----+---------+-------+

| Field   | Type    | Null | Key | Default | Extra |

+------------+-------------+------+-----+---------+-------+

| actor_id | int(11)  | NO | PRI | NULL  |   |

| first_name | varchar(25) | YES |  | NULL  |   |

| last_name | varchar(25) | YES |  | NULL  |   |

+------------+-------------+------+-----+---------+-------+

3 rows in set (0.00 sec)

MariaDB [test]> insert into actor(actor_id,first_name,last_name) values(100,'James','Kevin');

Query OK, 1 row affected (0.06 sec)

创建存储过程

MariaDB [test]> delimiter //

MariaDB [test]> create procedure actor_insert()

  -> begin

  -> set @x = 1;

  -> insert into actor(actor_id,first_name,last_name) values(100,'James','Kevin');

  -> set @x = 2;

  -> insert into actor(actor_id,first_name,last_name) values(200,'John','Terry');

  -> set @x = 3;

  -> end//

Query OK, 0 rows affected (0.01 sec)

MariaDB [test]> delimiter ;

调用存储过程报错

MariaDB [test]> call actor_insert();

ERROR 1062 (23000): Duplicate entry '100' for key 'PRIMARY'

MariaDB [test]> select @x;

+------+

| @x |

+------+

|  1 |

+------+

1 row in set (0.00 sec)

改写存储过程,增加异常处理

MariaDB [test]> delimiter //

MariaDB [test]> drop procedure actor_insert;

  -> //

Query OK, 0 rows affected (0.17 sec)

MariaDB [test]> create procedure actor_insert()

  -> begin

  -> declare continue handler for sqlstate '23000' set @x2=1;

  -> set @x = 1;

  -> insert into actor(actor_id,first_name,last_name) values(100,'James','Kevin');

  -> set @x = 2;

  -> insert into actor(actor_id,first_name,last_name) values(200,'John','Terry');

  -> set @x = 3;

  -> end//

Query OK, 0 rows affected (0.02 sec)

在这个例子中,声明SQLSTATE 23000,代表跳过表中重复的值,下面是文档中错误的描述

 Error: 1022 SQLSTATE: 23000 (ER_DUP_KEY)

Message: Can't write; duplicate key in table '%s'

MariaDB [test]> delimiter ;

MariaDB [test]> select * from actor;

+----------+------------+-----------+

| actor_id | first_name | last_name |

+----------+------------+-----------+

|   100 | James   | Kevin  |

+----------+------------+-----------+

1 row in set (0.00 sec)

MariaDB [test]> select @x;

+------+

| @x |

+------+

|  1 |

+------+

1 row in set (0.00 sec)

再次调用存储过程,跳过重复主键的行

MariaDB [test]> call actor_insert();

Query OK, 0 rows affected (0.07 sec)

MariaDB [test]> select @x2;

+------+

| @x2 |

+------+

|  1 |

+------+

1 row in set (0.00 sec)

MariaDB [test]> select @x;

+------+

| @x |

+------+

|  3 |

+------+

1 row in set (0.00 sec)

MariaDB [test]> select * from actor;

+----------+------------+-----------+

| actor_id | first_name | last_name |

+----------+------------+-----------+

|   100 | James   | Kevin  |

|   200 | John   | Terry  |

+----------+------------+-----------+

2 rows in set (0.00 sec)

定义一个HANDLER来进行事务的自动回滚操作,如在一个存储过程中发生了错误会自动对其进行回滚操作

create procedure sp_auto_rollback_demo()

begin

declare exit handler for SQLEXCEPTION ROLLBACK;

start transaction;

insert into b select 1;

insert into b select 2;

insert into b select 1;

insert into b select 3;

commit;

end;

增加测试报错代码

delimiter //

create procedure sp_auto_rollback_demo()

begin

declare exit handler for SQLEXCEPTION BEGIN ROLLBACK; SELECT -1; END;

start transaction;

insert into b select 1;

insert into b select 2;

insert into b select 1;

insert into b select 3;

commit;

select 1;

end//

delimiter ;

看完了这篇文章,相信你对“MySQL中存储过程定义条件和异常处理的示例分析”有了一定的了解,如果想了解更多相关知识,感谢各位的阅读!

(编辑:银川站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章