暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL数据库,详解游标使用(一)

Java学习网 2021-11-22
931

需求背景

当我们需要对⼀个select的查询结果进⾏遍历处理的时候,如何实现呢?

此时我们需要使⽤游标,通过游标的⽅式来遍历select查询的结果集,然后对每⾏数据进⾏处理。

准备数据

创建库:javacode2018

创建表:test1、test2、test3

/*建库javacode2018*/

drop database if exists javacode2018;

create database javacode2018;

/*切换到javacode2018库*/use javacode2018;

DROP TABLE IF EXISTS test1;

CREATE TABLE test1(a int,b int);

INSERT INTO test1 VALUES (1,2),(3,4),(5,6);

DROP TABLE IF EXISTS test2;

CREATE TABLE test2(a int);

INSERT INTO test2 VALUES (100),(200),(300);

DROP TABLE IF EXISTS test3;

CREATE TABLE test3(b int);

INSERT INTO test3 VALUES (400),(500),(600);

游标定义

游标(Cursor)是处理数据的⼀种⽅法,为了查看或者处理结果集中的数据,游标提供了

在结果集中⼀次⼀⾏遍历数据的能⼒。

游标只能在存储过程和函数中使⽤。

游标的作⽤

如sql:

select a,b from test1;

上⾯这个查询返回了test1中的数据,如果我们想对这些数据进⾏遍历处理,此时我们就

可以使⽤游标来进⾏操作。

游标相当于⼀个指针,这个指针指向select的第⼀⾏数据,可以通过移动指针来遍历后⾯

的数据。游标的使⽤步骤

声明游标:这个过程只是创建了⼀个游标,需要指定这个游标需要遍历的select查询,声

明游标时并不会去执⾏这个sql。

打开游标:打开游标的时候,会执⾏游标对应的select语句。

遍历数据:使⽤游标循环遍历select结果中每⼀⾏数据,然后进⾏处理。

关闭游标:游标使⽤完之后⼀定要关闭。

游标语法

声明游标

DECLARE 游标名称 CURSOR FOR 查询语句;

⼀个begin end中只能声明⼀个游标。

打开游标

open 游标名称;

遍历游标

fetch 游标名称 into 变量列表;

取出当前⾏的结果,将结果放在对应的变量中,并将游标指针指向下⼀⾏的数

据。

当调⽤fetch的时候,会获取当前⾏的数据,如果当前⾏⽆数据,会引发mysql内

部的NOT FOUND错误。

关闭游标

close 游标名称;

游标使⽤完毕之后⼀定要关闭。单游标示例

写⼀个函数,计算test1表中a、b字段所有的和。

创建函数:

/*删除函数*/

DROP FUNCTION IF EXISTS fun1;

/*声明结束符为$*/

DELIMITER $

/*创建函数*/

CREATE FUNCTION fun1(v_max_a int)

 RETURNS int

 BEGIN

 /*⽤于保存结果*/

 DECLARE v_total int DEFAULT 0;

 /*创建⼀个变量,⽤来保存当前⾏中a的值*/

 DECLARE v_a int DEFAULT 0;

 /*创建⼀个变量,⽤来保存当前⾏中b的值*/

 DECLARE v_b int DEFAULT 0;

 /*创建游标结束标志变量*/

 DECLARE v_done int DEFAULT FALSE;

 /*创建游标*/

 DECLARE cur_test1 CURSOR FOR SELECT a,b from test1 where 

a<=v_max_a;

 /*设置游标结束时v_done的值为true,可以v_done来判断游标是否结束了*/

 DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done=TRUE;

 /*设置v_total初始值*/

 SET v_total = 0;

 /*打开游标*/

 OPEN cur_test1;

 /*使⽤Loop循环遍历游标*/

 a:LOOP

 /*先获取当前⾏的数据,然后将当前⾏的数据放⼊v_a,v_b中,如果当前⾏⽆数据,

v_done会被置为true*/

 FETCH cur_test1 INTO v_a, v_b;

 /*通过v_done来判断游标是否结束了,退出循环*/

 if v_done THEN LEAVE a;

 END IF;

 /*对v_total值累加处理*/

 SET v_total = v_total + v_a + v_b;

 END LOOP;

 /*关闭游标*/

 CLOSE cur_test1;

 /*返回结果*/

 RETURN v_total;

 END $

/*结束符置为;*/

DELIMITER ;

上⾯语句执⾏过程中可能有问题,解决⽅式如下。

错误信息:Mysql 创建函数出现This function has none of DETERMINISTIC, NO

SQL, or READS SQL DATA

This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its

declaration and binary

mysql的设置默认是不允许创建函数

解决办法1:

执⾏:

SET GLOBAL logbintrustfunctioncreators = 1;

不过 重启了 就失效了

注意:有主从复制的时候 从机必须要设置 不然会导致主从同步失败

解决办法2:

在my.cnf⾥⾯设置

log-bin-trust-function-creators=1

不过这个需要重启服务

见效果:

mysql> SELECT a,b FROM test1;

+------+------+

| a | b |+------+------+

| 1 | 2 |

| 3 | 4 |

| 5 | 6 |

+------+------+

3 rows in set (0.00 sec)

mysql> SELECT fun1(1);

+---------+

| fun1(1) |

+---------+

| 3 |

+---------+

1 row in set (0.00 sec)

mysql> SELECT fun1(2);

+---------+

| fun1(2) |

+---------+

| 3 |

+---------+

1 row in set (0.00 sec)

mysql> SELECT fun1(3);

+---------+

| fun1(3) |

+---------+

| 10 |

+---------+

1 row in set (0.00 sec)


文章转载自Java学习网,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论