[转]mysql 存储过程中使用多游标

摘要:
CREATETABLE`netingcn_proc_test`(`id`整数(11)NOTNULLATO_INCREMENT,PRIMARYKEY(`id'))ENGINE=InnoDB;滴管程序IFEXISTStest_ proc;delimiter//createprocedureest_Proc()begin--声明一个已完成的标志。

From : http://www.netingcn.com/mysql-procedure-muti-cursor.html

mysql的存储过程可以很方便使用游标来实现一些功能,存储过程的写法大致如下:

先创建一张表,插入一些测试数据:

DROP TABLE IF EXISTS netingcn_proc_test;

CREATE TABLE `netingcn_proc_test` (
  `id` INTEGER(11) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(20),
  `password` VARCHAR(20),
  PRIMARY KEY (`id`)
)ENGINE=InnoDB;

insert into netingcn_proc_test(name, password) values
('procedure1', 'pass1'),
('procedure2', 'pass2'),
('procedure3', 'pass3'),
('procedure4', 'pass4');

下面就是一个简单存储过程的例子:

drop procedure IF EXISTS test_proc;
delimiter //
create procedure test_proc()
begin
	-- 声明一个标志done, 用来判断游标是否遍历完成
	DECLARE done INT DEFAULT 0;

	-- 声明一个变量,用来存放从游标中提取的数据
	-- 特别注意这里的名字不能与由游标中使用的列明相同,否则得到的数据都是NULL
	DECLARE tname varchar(50) DEFAULT NULL;
	DECLARE tpass varchar(50) DEFAULT NULL;

	-- 声明游标对应的 SQL 语句
	DECLARE cur CURSOR FOR
		select name, password from netingcn_proc_test;

	-- 在游标循环到最后会将 done 设置为 1
	DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

	-- 执行查询
	open cur;
	-- 遍历游标每一行
	REPEAT
		-- 把一行的信息存放在对应的变量中
		FETCH cur INTO tname, tpass;
		if not done then
			-- 这里就可以使用 tname, tpass 对应的信息了
			select tname, tpass;
		end if;
 	UNTIL done END REPEAT;
	CLOSE cur;
end
//
delimiter ;

-- 执行存储过程
call test_proc();

需要注意的是变量的声明、游标的声明和HANDLER声明的顺序不能搞错,必须是先声明变量,再申明游标,最后声明HANDLER。上述存储过程的例子中只使用了一个游标,那么如果要使用两个或者更多游标怎么办,其实很简单,可以这么说,一个怎么用两个就是怎么用的。例子如下:

drop procedure IF EXISTS test_proc_1;
delimiter //
create procedure test_proc_1()
begin
	DECLARE done INT DEFAULT 0;
	DECLARE tid int(11) DEFAULT 0;
	DECLARE tname varchar(50) DEFAULT NULL;
	DECLARE tpass varchar(50) DEFAULT NULL;

	DECLARE cur_1 CURSOR FOR
		select name, password from netingcn_proc_test;

	DECLARE cur_2 CURSOR FOR
		select id, name from netingcn_proc_test;

	DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

	open cur_1;
	REPEAT
		FETCH cur_1 INTO tname, tpass;
		if not done then
			select tname, tpass;
		end if;
 	UNTIL done END REPEAT;
	CLOSE cur_1;

	-- 注意这里,一定要重置done的值为 0
	set done = 0;

	open cur_2;
	REPEAT
		FETCH cur_2 INTO tid, tname;
		if not done then
			select tid, tname;
		end if;
 	UNTIL done END REPEAT;
	CLOSE cur_2;
end
//
delimiter ;

call test_proc_1();

上述代码和第一个例子中基本一样,就是多了一个游标声明和遍历游标。这里需要注意的是,在遍历第二个游标前使用了set done = 0,因为当第一个游标遍历玩后其值被handler设置为1了,如果不用set把它设置为 0 ,那么第二个游标就不会遍历了。当然好习惯是在每个打开游标的操作前都用该语句,确保游标能真正遍历。当然还可以使用begin语句块嵌套的方式来处理多个游标,例如:

drop procedure IF EXISTS test_proc_2;
delimiter //
create procedure test_proc_2()
begin
	DECLARE done INT DEFAULT 0;
	DECLARE tname varchar(50) DEFAULT NULL;
	DECLARE tpass varchar(50) DEFAULT NULL;

	DECLARE cur_1 CURSOR FOR
		select name, password from netingcn_proc_test;

	DECLARE cur_2 CURSOR FOR
		select id, name from netingcn_proc_test;

	DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

	open cur_1;
	REPEAT
		FETCH cur_1 INTO tname, tpass;
		if not done then
			select tname, tpass;
		end if;
 	UNTIL done END REPEAT;
	CLOSE cur_1;

	begin
		DECLARE done INT DEFAULT 0;
		DECLARE tid int(11) DEFAULT 0;
		DECLARE tname varchar(50) DEFAULT NULL;

		DECLARE cur_2 CURSOR FOR
			select id, name from netingcn_proc_test;

		DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

		open cur_2;
		REPEAT
			FETCH cur_2 INTO tid, tname;
			if not done then
				select tid, tname;
			end if;
	 	UNTIL done END REPEAT;
		CLOSE cur_2;
	end;
end
//
delimiter ;

call test_proc_2();
欢迎转载,转载请注明文章出处,谢谢!

免责声明:文章转载自《[转]mysql 存储过程中使用多游标》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇金丝雀发布、滚动发布、蓝绿发布到底有什么差别?关键点是什么?偏度与峰度的正态性分布判断下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

部署 Graylog 日志系统

Graylog 是与 ELK 可以相提并论的一款集中式日志管理方案,支持数据收集、检索、可视化 Dashboard。本节将实践用 Graylog 来管理 Docker 日志。 Graylog 架构 Graylog 架构如下图所示: Graylog 负责接收来自各种设备和应用的日志,并为用户提供 Web 访问接口。 Elasticsearch 用于索引和保...

NLP(二十六):如何微调 GPT-2 以生成文本

近年来,自然语言生成 (NLG) 取得了令人难以置信的进步。 2019 年初,OpenAI 发布了 GPT-2,这是一个巨大的预训练模型(1.5B 参数),能够生成类似人类质量的文本。Generative Pretrained Transformer 2 (GPT-2) 顾名思义,基于 Transformer。 因此,它使用注意力机制,这意味着它会学习关...

jenkins结合ansible用shell实现自动化部署和回滚

最近用jenkins+gitlab+ansible做持续化集成,自动化部署和版本回滚。然而deploy plugin没能做到增量升级和回滚操作,折腾了很久决定自己写个脚本来简单实现。 环境: centos 7.064位 gitlab:v2.9.0 git:2.9 jenkins 1.651.3、git plugin、GitLab Plugin、Dynam...

AS400一些有用的命令

1. '1' -> *ON      '0' -> *OFF 2. Indicator position    CHAIN : HI    LOOKUP : EQ    READ : EQ 3.DSPFD显示PF的member个数,Format Identifier,trigger等等,DSPFFD显示PF的列名之类 DSPFD FILE(T...

webpack4.x最详细入门讲解

前言 本文主要从webpack4.x入手,会对平时常用的Webpack配置一一讲解,各个功能点都有对应的详细例子,所以本文也比较长,但如果你能动手跟着本文中的例子完整写一次,相信你会觉得Webpack也不过如此。 一、什么是webpack,为什么使用它? 1.1 什么是webpack? 简单来说,它其实就是一个模块打包器。 1.2 为什么使用它? 如果像...

【自然语言处理】利用朴素贝叶斯进行新闻分类(自己处理数据)

读完这篇博文,你能够收获什么? 从数据处理到利用朴素贝叶斯进行分类的整个过程 本文更关注于数据处理阶段,朴素贝叶斯模型直接使用sklearn库中自带的 先给出整个算法的流程:  采用的是sogou语料库的部分数据,每个C开头的文件各代表一类,里面包含着若干篇txt类型的文章,具体类别如下: 1.数据审视阶段(查看是否有不符合规范或异常的数据),由于...