MySQL笔记12

游标

游标的基本概念
什么是游标?
在查询表时,会获得一个查询结果集,游标就是用来遍历这个结果集中每一条记录的,把查询结果集看作是一个容器,那游标就是类似于迭代器一样的东西,
游标可以返回结果集中一行或多行数据,结果集是存在数据缓冲区里的,游标可以从数据缓冲区里读取相应的数据。
游标只能用在存储过程和函数中,并且一次只能指向一条记录。

游标的使用
①声明游标(定义游标)
declare 游标名 cursor for select查询语句;
②打开定义的游标
open 游标名;
③遍历游标(使用游标)
fetch 游标名 into 值列表(变量);
④使用完释放游标(关闭游标)
close 游标名;
# 注意:游标在遍历完成后会指向最后一条记录的下一条,由于下一条没有数据,就会出现no data to fetch的错误。
|# 为了解决这个错误,就需要定义一个条件处理函数NOT FOUND 来捕获这一个异常。没有异常处理的话就会报错。

案例:新建一个数据库和数据表,通过游标遍历表中的每一条数据。
①创建数据库和数据表,并插入数据。

create database tzdb5;
use tzdb5;
create table cursor_test
(id int primary key,name varchar(20),age int
)engine innodb default charset utf8;
insert into cursor_test values(1,”小威”,18),
(2,”夏七”,25),(3,”danny”,36),(4,”罗伯特”,40);
	select * from cursor_test;

②创建一个存储过程,使用游标遍历表cursor_test中大于30岁的记录,并统计个数。

create procedure p_cursor_test()
begin
declare count1 int default 0; # 定义统计变量
declare ids int; # 定义接收id变量
declare names varchar(20); # 定义接收name变量
declare ages int; # 定义接收age变量
declare c_exit bool default false; # 定义退出变量
declare cursor1 cursor for # 定义游标
select id,name,age from cursor_test where age > 30;
 # 声明错误处理函数not found,来捕获遍历结束的错误
declare continue handler for not found 
set c_exit = true; # 遍历结束,设置退出变量为true
open cursor1;
cur:loop # 循环遍历临时结果集
	fetch cursor1 into ids,names,ages;
	if c_exit then leave cur; end if;
	select ids,names,ages; set count1 = count1+1;
	end loop; select count1; close cursor1; end;

条件处理

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

定义处理函数(? declare handler)
DECLARE handler_action HANDLER
FOR condition_value [, condition_value] …
statement
handler_action: CONTINUE | EXIT | UNDO # 处理动作名
|# 捕获后怎么处理? 继续 | 退出 | 不处理(MySQL不支持)
condition_value: # 错误值
mysql_error_code | SQLSTATE [VALUE]sqlstate_value
# 错误码 | 状态值
| condition_name | SQLWARNING | NOT FOUND | SQLEXCEPTION
|# | |所有以01开头的|所有以02开头的|除了00、01、02开头的
①无错误处理的存储过程

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 tzdb6; # 1049为错误码,42000为状态类
ERROR 1049 (42000): Unknown database ‘tzdb6’
# 声明错误条件不能单独使用,要配合处理函数使用

在存储过程中用错误码进行错误处理

create procedure p_test4()
begin
	declare no_have_table condition for 1146;
	declare continue handler for no_have_table
		select '此表还是不存在' as 错误;
	select * from untable;
end;

call p_test4(); 

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

create procedure p_test5()
begin
declare no_have_table condition for sqlstate '42S02';
	declare continue handler for no_have_table
		select 'MDZZ说了此表不存在了还查' as 错误;
	select * from untable;
end;
call p_test5(); 
# 之前说过存储过程里不能使用select语句
	#这里可以用错误条件处理实现存储过程中使用select语句

获取诊断信息(获取错误信息)
通过get diagnostics获取错误信息。
一般格式:
get diagnostics condition 错误信息位置
@变量名1= mysql_errno, # 获取错误码
@变量名2= returned_sqlstate, # 获取状态值
@变量名3= message_text; # 获取错误信息文本
如:删除一个不存在的表,drop table untable;
ERROR 1051 (42S02): Unknown table ‘tzdb5.untable’
get diagnostics condition 1 @x = mysql_errno,
@y = returned_sqlstate,@z = message_text;

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

create procedure test_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默认修改上一条错误信息
signal需要指定错误信息
其他错误信息
#class_origin #原始类名
#subclass_origin #原始子类名
#constraint_catalog #约束目录
#constraint_name #约束名
#catalog_name #目录名
#column_name #列名
#cursor_name #游标

发布了51 篇原创文章 · 获赞 5 · 访问量 400

猜你喜欢

转载自blog.csdn.net/qq_42078231/article/details/102991809
今日推荐