MYSQL游标和条件处理

游标

游标的基本概念

什么是游标?

在查询表时,会获得一个查询结果集,游标就是用来遍历这个结果集中每一条记录的,把查询结果集看作是一个容器,那游标就是类似于迭代器一样的东西,游标可以返回结果集中一行或多行数据,结果集是存在数据缓冲区里的,游标可以从数据缓冲区里读取相应的数据。

游标只能用在存储过程和函数中,并且一次只能指向一条记录。
游标类似于C语言中的指针,可以指向一块数据内存,然后通过这块数据进行访问,也可以理解成c++中的容器的迭代器

游标的使用

1.声明游标(定义游标)

declare 游标名 cursor for select 查询语句;

2.打开定义的游标

open 游标名;

3.遍历游标(使用游标)

fetch 游标名 into 值列表(变量);

4.使用完释放游标(关闭游标)

close 游标名;

注意:
游标在遍历完成后会指向最后一条记录的下一条,由于下一条没有数据,就会出现 no data to fetch 的错误。
为了解决这个错误,就需要定义一个条件处理函数NOT FOUND 来捕获这一个异常。没有异常处理的话就会报错。

declare 游标 cursor for # 定义游标 
select 属性名 from 表格 where 条件;

声明错误处理函数 not found ,来捕获遍历结束的错误

 declare continue handler for not found;

示例,读取一张成绩表中的内容

delimiter $$ 
create procedure cursor_test() 
begin
    ##定义三个变量 
    declare id int; 
    declare title varchar(255); 
    declare c_date date; 
    ##统计的变量 
    declare counts int default 0; 
    ##退出的条件 
    declare cur_exit bool default false; 
    ##定义游标 
    declare cur_test cursor for select * from course_tb; 
    ## 条件处理,遇到没有找到数据的错误,就执行一段命令 
    ##当游标读到末尾的时候,就将退出的条件设置为true 
    ## 这条命令要写在定义游标之后 
    declare continue handler for not found set cur_exit=true; 
    ## 打开游标 
    open cur_test; 
    ##循环遍历 
    cur:loop 
        ## 遍历游标 
        fetch cur_test into id,title,c_date; 
        ## 如果退出的条件为true,就跳出 
        if cur_exit then leave cur; 
        ##跳出循环 
        end if;
        select id,title,c_date; 
        set counts=counts+1; 
    end loop; 
    select counts; 
    ##关闭游标 
    close cur_test; 
end$$ 
delimiter ;

条件处理

条件处理就是MySQL数据库中的异常处理(错误处理)。
MySQL通过条件处理来捕获错误和异常。
注意:条件处理只能在存储过程中使用,并且存储过程和条件处理只有 MySQL5.5 版本之后才支持,如 果用的是 MySQL5.5 之前的版本就不要用条件处理了。

定义处理函数

使用命令行中的语句获取语法格式(? declare handler)

DECLARE handler_action HANDLER ##handler_action 捕获选项 
FOR 错误值 [, condition_value] 
...statement #怎么处理

handler_action选项
捕获后怎么处理? 继续 | 退出 | 不处理(MySQL不支持)

handler_action: continue | exit | UNDO # 处理动作名

continue 继续,遇到错误继续执行代码
exit 退出,遇到错误直接结束命令

condition_value: # 错误值 
mysql_error_code | SQLSTATE [VALUE] sqlstate_value

错误码 | 状态值

| condition_name | SQLWARNING | NOT FOUND | SQLEXCEPTION

条件处理实例

无错误处理的存储过程

#无错误处理的存储过程 
create procedure p_test1() 
begin
   select * from untable; 
end; 
call p_test1();

出现错误

ERROR 1146 (42S02): Table 'tzdb5.untable' doesn't exist

调用存储过程后会报错:错误码 1146 (42S02)表不存在
所有 mysql 中所定义的错误码和状态值都可以在存储过程中用错误码进行错误处理

create procedure p_test2() 
begin
    declare continue handler for 1146 
       select '此表不存在' as 错误; 
    #使用一个不存在的表 
    select * from untable; ## 出现了错误
end; 
call p_test2();

调用存储过程后不会报错,而是按照自己所设置的进行处理
在存储过程中用状态值进行错误处理

create procedure p_test3() 
begin
    declare continue handler for sqlstate '42S02' 
       select '此表真的不存在' as 错误; 
    #使用一个不存在的表 
    select * from untable; 
end; 
call p_test3();

错误条件函数

错误条件函数的声明(? declare condition)
可以进行手动的设置错误码,和错误信息

DECLARE condition_name(错误函数名) #错误条件函数 
CONDITION FOR condition_value(状态值) #声明一个条件处理

错误条件函数相当于给错误取别名,通过别名来显示错误信息

condition_value: # 条件值 
mysql_error_code # 错误码 
| SQLSTATE [VALUE] sqlstate_value

状态类 错误类名
例如:
use 一个不存在的数据库名;

# 使用不存在的数据库 use untable;

出现下面错误

ERROR 1049 (42000): Unknown database 'untable'
1049为错误码,42000为状态类

声明错误条件不能单独使用,要配合处理函数使用
1.在存储过程中用错误码进行错误处理

create procedure test4_pro() 
begin
   declare no_table condition for 1146; 
   select * from untable; 
end$$ 
call test4_pro();

2.在存储过程中用状态值进行错误处理

create procedure p_test5() 
begin 
##声明错误函数 
declare no_have_table condition for sqlstate '42S02'; 
#通过条件处理调用错误函数 
declare continue handler for no_have_table 
   select '说了此表不存在了还查' as 错误; 
   select * from untable; 
end; 
call p_test5();

获取错误信息

通过 get diagnostics 获取错误信息。
一般格式

get diagnostics condition 错误信息位置 
    @变量名1= mysql_errno, # 获取错误码 
    @变量名2= returned_sqlstate, # 获取状态值 
    @变量名3= message_text; # 获取错误信息文本

修改错误信息日志

#如:删除一个不存在的表, 
drop table untable; 
#ERROR 1051 (42S02): Unknown table 'tzdb.untable' 
get diagnostics condition 1 
@x = mysql_errno, 
@y = returned_sqlstate, 
@z = message_text;

更改错误信息

错误信息描述
schema_name数据库名
table_name表名
message_text错误信息
mysql_errno错误码
returned_sqlstate错误状态值

通过 resignal / signal 更改错误信息。
一般格式:创建一个存储过程实现错误信息的

## 声明错误信息处理的函数 
declare no_table condition for 1146;

signal需要指定错误信息

##手动设置一个错误信息 
begin declare continue handler for sqlstate '42S02' 
begin signal sqlstate '42S02' # sqlstate '42S02' = 1051 
#这里使用resignal不用指定错误,直接写个resignal就可以了 
  set schema_name = 'newdb', #数据库名 
      table_name = 'newdb_tb', #表名 
      message_text = '没有这个表', #错误信息 
      mysql_errno = 11; #错误码 
      end; 
  drop table untable; 
end; #调用存储过程 
call test_signal(); 
#resignal默认修改上一条错误信息

RESIGNAL语句。它在功能和语法方面与SIGNAL语句相似
区别:

必须在错误或警告处理程序中使用RESIGNAL语句,可以在存储过程中的任何位置使用SIGNAL语句。
可以省略SIGNAL语句的所有属性,默认修改上一条错误信息

其他错误信息

错误信息描述
subclass_origin原始子类名
constraint_catalog约束目录
constraint_name约束名
catalog_name目录名
column_name列名
cursor_name游标
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

尘客-追梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值