• 使用DECLARE定义条件和处理程序


    定义条件和处理程序是事先定义程序执行过程中可能遇到的问题,并且可以在处理程序中定义解决这些问题的办法,可以简单理解

    为异常处理,这种方式可以提前预测可能出现的问题,并提出解决办法,从而增强程序健壮性。避免程序异常停止,mysql

    通过declare关键字定义条件和处理程序。

    定义条件

    mysql中可以使用declare关键字来定义条件,其基本语法如下:

    -- 条件定义语法

    declare           condition_name condition for condition_value

    -- condition_value 的定义格式

    sqlstate [value] sqlstate_value | mysql_error_code

    其中,condition_name 表示条件的名称,condition_value 参数表示条件的类型;sqlstate_value 参数和mysql_error_code参数都可以

    表示 mysql的 错误,如常见的error 1146 (42s02) 中,sqlstate_value 值是42s02,mysql_error_code值是1146,

    简单案例如下:

    -- 定义主键重复错误

    -- error 1062 (23000):duplicate entry '60' for key 'primary'

     -- 方法一:使用 sqlstate_value

    declare primary_key_duplicate condition for sqlstate     '23000';

    -- 方法二: 使用mysql_error_code

    declare primary_key_duplicate condition for 1062;

    定义处理程序

    前面定义的处理条件,可以在定义处理程序中 使用,先了解一下定义语法:

    declare handler_type HANDLER FOR

    condition_value[,...] sp_statement

    handler_type 参数的取值有三种:CONTINUE | EXIT | UNDO.

    CONTINUE 表示遇到错误不进行处理,继续向下执行;

    EXIT 表示遇到错误后马上退出;

    UNDO 表示遇到错误后撤回之前的操作,但mysql中暂时还不支持这种处理方式。

    我们需要注意的是,大多数情况下,执行过程中遇到错误应该立刻停止执行下面的语句,并且撤回前面的操作。由于mysql目前

    并不支持UNDO操作。所以,遇到错误时最好执行EXIT操作。如果事先能够预测错误类型,并且进行相应的处理,那么就选择

    CONTINUE 操作。

    condition_value 参数指明错误类型,该参数有6个取值。语法如下:

    -- condition_value 的取值:

    SQLSTATE [VALUE] sqlstate_value

    mysql_error_code

    condition_name

    SQLWARNING

    SQLEXCEPTION

    sqlstate_value 参数和mysql_error_code参数都可以ysql的错误。如常见的error 1146(42s02)中,sqlstate_value值是42s02,

    mysql_error_code值是1146.与条件中参数是一样的。

    condition_name 是DECLARE定义的条件名称,就前面定义条件语句

    NOT FOUND表示所有以02开头的sqlstate_value值。

    SQLEXCEPTION表示所有没有被SQLWARNING或 NOT FOUND捕获的sqlstate_value值。

    sp_statement 参数表示要执行存储过程或函数语句。

    一下定义了如何捕获和处理异常的简单例子

    -- 捕获sqlstate_value值。如果遇到sqlstate_value值为42s02,执行CONTINUE操作,并且设置用户变量info。

    DECLARE CONTIUNE HANDLER FOR SQLSTATE '42s02' SET @info='CAN NOT FIND';

    -- 捕获mysql_error_code,如果遇到mysql_error_code值为1146,执行CONTIUNE操作,并且设置用户变量info.

    DECLARE CONTINUE  HANDLER FOR 1146 SET @INFO='CAN NOT FIND';

    -- 先定义条件,然后定义处理程序调用

    DECLARE can_not_find CONDITION FOR 1146;

    -- 定义处理程序,并使用定义的can_not_find 条件

    DECLARE CONTINUE HANDLER FOR can_not_find SET @INFO='CAN NOT FIND'

    -- SQLWARNING捕获所有以01开头的sqlstate_value值,然后执行EXIT

    DECLARE EXIT HANDLER FOR SQLWARNING SET @info='ERROR';

    -- NOT FOUND 捕获所有以02开头的sqlstate_value值,然后执行EXIT操作,并且输出"CAN NOT FIND"信息

    DECLARE EXIT HANDLER FOR FOUND SET @info='CAN NOT FIND';

    -- SQLEXCEPTION 捕获所有没有被SQLWARNING或NOT FOUND 捕获的sqlstate_value 值,然后执行EXIT操作。

    DECLARE EXIT HANDLER FOR SQLEXCEPTION SET @info='ERROR';

    为了加深理解,下面我们编写一个存储过程用于添加用户,借此来了解定义处理程序的作用,如下:

    DELIMITER //

    create_procedure sp_insert_user()

    begin

    set @n=1; -- 设置用户变量,用于标识程序运行到哪一步停止

    insert into user value(60,'小米','xiaomi',null,1,null);

    set @n=2;

    insert into user value(61,'小米2','xiaomi2',null,null);

    set @n=3;

    end

    //

    DELIMITER ;

    -- 执行存储过程

    call sp_insert_user();

    -- 报错,因为主键60的用户已存在

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

    -- 查询标识,显然在第一步时遇到错误就停止了执行

    select @n;

    上述程序在执行完 set @n=1;后就出错了,因为出现了重复的主键值,也就是直接导致后面的程序也无法执行,现在我们编写一个处理程序,使用

    存储过程中即使出现2300错误也继续执行,如下:

    create procedure insert_user_2()

    begin

    --定义条件

    DECLARE primary_key_exist CONTITION SQLSTATE '23000';

    -- 定义处理程序,出现2300错误继续执行, @m用于标识

    DECLARE CONTINUE HANDLER FOR primary_key_exist SET @m = 1000;

    set @n=1;

    insert into user value(60,'小米','小米',null,1,null);

    set @n=2;

    insert into user value(61,'小米2','xiaomi2',null,1,null);

    set @n=3;

    end

    //

    DELIMITER;

    call insert_user_2();

    -- 查询标识

    select @n;

    select @m;

    从程序可以看出即使出现主键重复错误,但由于我们进行捕获并处理使得整个存储过程的程序可以

    执行完成。

    构建复杂的存储过程(案例)

    获取一个订单的总价,并判断是否需要营业税收,案例如下:

    DELIMITER //

    create procedure sp_ordertotal(in onnumber int,in taxable boolean,out ototal decimal(8,2))

    begin

    -- 定义变量:总价

    declare total decimal(8,2);

    -- 定义默认税收率

    declare taxrate int default 6;

    -- 关联查询并计算总价

    select sum(price * items_num) from orderdetail as od

    inner join items as it on it.id=od.items_id

    where od.orders_id = onnumber

    into total; -- 赋值

    -- 判断是否需要营业税收

    if taxable then

    select total + (total/100 * taxrate) into total;

    end if;

    -- 赋值给输出参数

    select total into ototal;

    end

    //

    -- 执行存储过程

    call sp_ordertotal(3,false,@total)//

    -- 查询总价

    select @total //

    存储函数

    创建存储函数

    上一篇中,我们列举不少mysql自带的函数,但是有些时候自带函数并不能很好满足

    我们的需求,此时就需要自定义存储函数了,与存储过程有些类似,简单来说就是

    封装一段sql代码,完成一种特定的功能,并返回结果。其语法如下:

    create function 函数([参数类型 数据类型[,.....]]) RETURNS 返回类型

    begin 

    sql 语句...

    return (返回的数据)

    end

    与存储过程不通过的是,存储函数中不能指定输出参数(OUT)和输入参数(IN)

    类型。存储函数只能指定输入类型而且不能存储函数可以通过return命令将处理

    的结果返回给掉用方。注意必须在参数列表后的returns(该值的returns多个s,务必留意)命令中预先指定返回值的类型。

    如下创建一个计算斐波那契数列的函数

    -- 创建存储函数

    create function fn_factorial(num int) returns int 

    begin

    declare result int default 1;

    while num > 1 do

    set result = result * num;

    set num = num -1;

    end while;

    return result;

    end 

    //

    使用 select 执行存储函数

    select fn_factorial(5);

    这里命名存储函数时使用了【fn_】作为开头,这样可以更容易区分与【sp_】开头的存储过程,从上述语句可以看出前面

    在存储过程分析的流程语句也是可以用于存储函数的,同样的, DECLARE声明变量和set设置变量也可用于存储函数,

    当然包括定义异常处理语句也是适应的,请注意执行存储函数使用的是select关键字,可同时执行多个存储函数,恩,存储函数就这样

    定义,是不是跟存储过程很相似呢,但还是有区别的,这点留到后面分析,下面编写一个用于向user插入用户的存储函数:

    -- 创建存储函数fn_insert_user

    create function fn_insert_user(name varchar(32),sex char(1)) returns int

    begin 

    insert into user (username,pinyin,birthday,sex,address) values(name,null,null,sex,null);

    return LAST_INSERT_ID(); -- 返回最后插入的ID值

    end //

    DELIMITER ;

    -- 执行存储函数

    select fn_insert_user('xiaolong',1);

  • 相关阅读:
    C#控件刷新
    [转载] 尺度不变特征变换匹配算法
    C++ windows 多线程 互斥锁
    堆栈内存申请,以及32位程序内存上限
    dumpbin检查Dll
    CV_Assert
    Linux复习
    操作系统复习
    P/NP问题
    程序
  • 原文地址:https://www.cnblogs.com/simadongyang/p/8468728.html
Copyright © 2020-2023  润新知