mysql游标的用法及作用
1
当前有三张表A、B、C其中A和B是一对多关系,B和C是一对多关系,现在需要将B中A表的主键存到C中;
常规思路就是将B中查询出来然后通过一个update语句来更新C表就可以了,但是B表中有2000多条数据,
难道要执行2000多次?显然是不现实的;最终找到写一个存储过程然后通过循环来更新C表,
然而存储过程中的写法用的就是游标的形式。
【简介】
游标实际上是一种能从包括多条数据记录的结果集中每次提取一条记录的机制。
游标充当指针的作用。
尽管游标能遍历结果中的所有行,但他一次只指向一行。
游标的作用就是用于对查询数据库所返回的记录进行遍历,以便进行相应的操作。
【用法】
一、声明一个游标: declare 游标名称 CURSOR for table;(这里的table可以是你查询出来的任意集合)
二、打开定义的游标:open 游标名称;
三、获得下一行数据:FETCH 游标名称 into testrangeid,versionid;
四、需要执行的语句(增删改查):这里视具体情况而定
五、释放游标:CLOSE 游标名称;
注:mysql存储过程每一句后面必须用;结尾,使用的临时字段需要在定义游标之前进行声明。
【实例】
-
BEGIN
--定义变量
declare testrangeid BIGINT;
declare versionid BIGINT;
declare done int;
--创建游标,并存储数据
declare cur_test CURSOR for
select id as testrangeid,version_id as versionid from tp_testrange;
--游标中的内容执行完后将done设置为1
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
--打开游标
open cur_test;
--执行循环
posLoop:LOOP
--判断是否结束循环
IF done=1 THEN
LEAVE posLoop;
END IF;
--取游标中的值
FETCH cur_test into testrangeid,versionid;
--执行更新操作
update tp_data_execute set version_id=versionid where testrange_id = testrangeid;
END LOOP posLoop;
--释放游标
CLOSE cur_test;
END -
例子2:
我们现在要用存储过程做一个功能,统计iphone的总库存是多少,并把总数输出到控制台。
--在windows系统中写存储过程时,如果需要使用declare声明变量,需要添加这个关键字,否则会报错。
delimiter //
drop procedure if exists StatisticStore;
CREATE PROCEDURE StatisticStore()
BEGIN
--创建接收游标数据的变量
declare c int;
declare n varchar(20);
--创建总数变量
declare total int default 0;
--创建结束标志变量
declare done int default false;
--创建游标
declare cur cursor for select name,count from store where name = 'iphone';
--指定游标循环结束时的返回值
declare continue HANDLER for not found set done = true;
--设置初始值
set total = 0;
--打开游标
open cur;
--开始循环游标里的数据
read_loop:loop
--根据游标当前指向的一条数据
fetch cur into n,c;
--判断游标的循环是否结束
if done then
leave read_loop; --跳出游标循环
end if;
--获取一条数据时,将count值进行累加操作,这里可以做任意你想做的操作,
set total = total + c;
--结束游标循环
end loop;
--关闭游标
close cur;
--输出结果
select total;
END;
--调用存储过程
call StatisticStore();
fetch是获取游标当前指向的数据行,并将指针指向下一行,当游标已经指向最后一行时继续执行会造成游标溢出。
使用loop循环游标时,他本身是不会监控是否到最后一条数据了,像下面代码这种写法,就会造成死循环;
read_loop:loop
fetch cur into n,c;
set total = total+c;
end loop;
在MySql中,造成游标溢出时会引发mysql预定义的NOT FOUND错误,所以在上面使用下面的代码指定了当引发not found错误时定义一个continue 的事件,指定这个事件发生时修改done变量的值。
declare continue HANDLER for not found set done = true;
1
所以在循环时加上了下面这句代码:
--判断游标的循环是否结束
if done then
leave read_loop; --跳出游标循环
end if;
如果done的值是true,就结束循环。继续执行下面的代码
使用方式
游标有三种使用方式:
第一种就是上面的实现,使用loop循环;
第二种方式如下,使用while循环:
drop procedure if exists StatisticStore1;
CREATE PROCEDURE StatisticStore1()
BEGIN
declare c int;
declare n varchar(20);
declare total int default 0;
declare done int default false;
declare cur cursor for select name,count from store where name = 'iphone';
declare continue HANDLER for not found set done = true;
set total = 0;
open cur;
fetch cur into n,c;
while(not done) do
set total = total + c;
fetch cur into n,c;
end while;
close cur;
select total;
END;
call StatisticStore1();
第三种方式是使用repeat执行:
drop procedure if exists StatisticStore2;
CREATE PROCEDURE StatisticStore2()
BEGIN
declare c int;
declare n varchar(20);
declare total int default 0;
declare done int default false;
declare cur cursor for select name,count from store where name = 'iphone';
declare continue HANDLER for not found set done = true;
set total = 0;
open cur;
repeat
fetch cur into n,c;
if not done then
set total = total + c;
end if;
until done end repeat;
close cur;
select total;
END;
call StatisticStore2();
游标嵌套
在mysql中,每个begin end 块都是一个独立的scope区域,由于MySql中同一个error的事件只能定义一次,如果多定义的话在编译时会提示Duplicate handler declared in the same block。
drop procedure if exists StatisticStore3;
CREATE PROCEDURE StatisticStore3()
BEGIN
declare _n varchar(20);
declare done int default false;
declare cur cursor for select name from store group by name;
declare continue HANDLER for not found set done = true;
open cur;
read_loop:loop
fetch cur into _n;
if done then
leave read_loop;
end if;
begin
declare c int;
declare n varchar(20);
declare total int default 0;
declare done int default false;
declare cur cursor for select name,count from store where name = 'iphone';
declare continue HANDLER for not found set done = true;
set total = 0;
open cur;
iphone_loop:loop
fetch cur into n,c;
if done then
leave iphone_loop;
end if;
set total = total + c;
end loop;
close cur;
select _n,n,total;
end;
begin
declare c int;
declare n varchar(20);
declare total int default 0;
declare done int default false;
declare cur cursor for select name,count from store where name = 'android';
declare continue HANDLER for not found set done = true;
set total = 0;
open cur;
android_loop:loop
fetch cur into n,c;
if done then
leave android_loop;
end if;
set total = total + c;
end loop;
close cur;
select _n,n,total;
end;
begin
end;
end loop;
close cur;
END;
call StatisticStore3();
上面就是实现一个嵌套循环,当然这个例子比较牵强。凑合看看就行。
动态SQL
Mysql 支持动态SQL的功能,
set @sqlStr='select * from table where condition1 = ?';
prepare s1 for @sqlStr;
--如果有多个参数用逗号分隔
execute s1 using @condition1;
--手工释放,或者是 connection 关闭时, server 自动回收
deallocate prepare s1;
mysql游标的用法及作用的更多相关文章
- mysql关于视图的用法以及作用
关于视图的用法以及作用. 作用一: 提高了重用性,就像一个函数.如果要频繁获取user的name和goods的name.就应该使用以下sql语言.示例: select a.name as userna ...
- MySQL数据库中delimiter的作用概述
以下的文章主要是向大家描述的是MySQL数据库中delimiter的作用是什么?我们一般都认为这个命令和存储过程关系不大,到底是不是这样的呢?以下的文章将会给你相关的知识,望你会有所收获. 其实就是告 ...
- mysql group by 用法解析(详细)
在使用mysql时,有时需要查询出某个字段不重复的记录,虽然mysql提供 有distinct这个关键字来过滤掉多余的重复记录只保留一条,但往往只用它来返回不重复记录的条数,而不是用它来返回不重记录的 ...
- (转载)mysql group by 用法解析(详细)
(转载)http://blog.tianya.cn/blogger/post_read.asp?BlogID=4221189&PostID=47881614 mysql distinct 去重 ...
- MySQL游标的简单实践
Q:为什么要使用游标? A: 在存储过程(或函数)中,如果某条select语句返回的结果集中只有1行,可以使用select into语句(上几篇博客有介绍到用法)来得到该行进行处理:如果结果集中有多行 ...
- mysql进阶(二十八)MySQL GRANT REVOKE用法
mysql进阶(二十八)MySQL GRANT REVOKE用法 MySQL的权限系统围绕着两个概念: 认证->确定用户是否允许连接数据库服务器: 授权->确定用户是否拥有足够的权限执 ...
- mysql的if用法解决同一张数据表里面两个字段是否相等统计数据量。
MySQL的使用用法如下所示:格式:if(Condition,A,B)意义:当Condition为true时,返回A:当Condition为false时,返回B.作用:作为条件语句使用.mysql的i ...
- oracle中游标详细用法
转自:http://blog.csdn.net/liyong199012/article/details/8948952 游标的概念: 游标是SQL的一个内存工作区,由系统或用户以变量的形式定 ...
- Mysql 游标初识
MySql 游标初识 认识 游标(cursor), 按字面意思可理解为, 游动的标识, 或者叫做"光标", 这样更容易理解. 就好比现有一张表存储了n行记录, 然后我想每次取出一行 ...
随机推荐
- [CH3803] 扑克牌 (期望DP+记忆化搜索)
[题目链接] [CH3803] 扑克牌 [题面描述] \(54\)张牌,每次随机摸一张,求得到 A张黑桃 B张红桃 C张梅花 D张方块 的期望步数.特别地,大王和小王可以当做任意一种花色,当然,会选择 ...
- 【算法笔记】B1034 有理数四则运算
1034 有理数四则运算 (20 分) 本题要求编写程序,计算 2 个有理数的和.差.积.商. 输入格式: 输入在一行中按照 a1/b1 a2/b2 的格式给出两个分数形式的有理数,其中分子和分母 ...
- 迁移-Mongodb时间类数据比较的坑
背景: 拦截件监控时,对于签收的数据需要比较签收时间和实际同步数据的时间来判断 同步时间是在签收前还是签收后.在比较时,用到同步时间syncTime和signTime, signTime从Q9查单获 ...
- 原子操作类AtomicInteger详解
为什么需要AtomicInteger原子操作类?对于Java中的运算操作,例如自增或自减,若没有进行额外的同步操作,在多线程环境下就是线程不安全的.num++解析为num=num+1,明显,这个操作不 ...
- C++中函数调用时的三种参数传递方式
在C++中,参数传递的方式是“实虚结合”. 按值传递(pass by value) 地址传递(pass by pointer) 引用传递(pass by reference) 按值传递的过程为:首先计 ...
- 浏览器获取WEB服务器时间
/* * 获取XMLHttpRequest对象 */ function CreateXMLHttpRequest() { var xmlreq = false; if (window.ActiveXO ...
- selenium自动化测试用例需要关注的几点(二)
注:原文地址 UI映射 一个UI映射是一种机制,它存储所有的定位器的测试套件在一个地方,方便修改UI元素的路径标识符或改变在AUT.测试脚本,然后使用UI地图定位以被测试的元件.基本上,UI地图是一个 ...
- 局域网电脑之间ping不通解决办法
局域网电脑之间ping不通一般都是防火墙的原因.解决办法有以下两种方法 1 第一种方法 1 找到Windows防火墙 2点击更改通知设置 3 关闭专用网络防火墙 现在就可以ping通这台机器了. 2 ...
- python输出不换行
python输出不换行 Python2的写法是: print 'hello', Python3的写法是: print('hello', end='') 对于python2和python3都兼容的写法是 ...
- JavaScript中的异步 macrotask 和 microtask
看过很多setTimeout.Promise执行顺序的面试题,一直不明白为啥都是异步操作,Promise就牛×些呢?直到了解了macrotask和micromask才恍然大悟... 先来一道面试题助助 ...