定义

我们经常会遇到这样的一种情况,需要对我们查询的结果进行遍历操作,并对遍历到的每一条数据进行处理,这时候就会使用到游标。
所以:游标(Cursor)是处理数据的一种存储在MySQL服务器上的数据库查询方法,为了查看或者处理结果集中的数据,提供了在结果集中一次一行遍历数据的能力。
游标主要用在循环处理、存储过程、函数、触发器 中。

游标的作用

比如我们上面那个students学生,需要对每个用户进行遍历,然后根据他们的其他评价进行加分或者减分。这时候我们就需要查询到所有的学生信息(包含成绩)。
1 select studentid,studentname,score from students; 
执行之后返回了的学生数据集合,我们如果需要对学生数据逐一遍历,然后根据具体的情况进行加分,那就需要是使用游标了。
游标相当于一个指针,这个指针指向select的第一行数据,可以通过移动指针来遍历后面的数据。 

游标的使用

声明游标:创建一个游标,并指定这个游标需要遍历的select查询,声明游标时并不会去执行这个sql。
打开游标:打开游标的时候,会执行游标对应的select语句。
遍历数据:使用游标循环遍历select结果中每一行数据,然后进行处理。
业务操作:对遍历到的每行数据进行操作的过程,可以放置任何需要执行的执行的语句(增删改查):这里视具体情况而定
关闭游标:游标使用完之后一定要释放。
注:使用的临时字段需要在定义游标之前进行声明。

声明游标

1 DECLARE cursor_name CURSOR FOR select_statement; 
声明一个游标。也可以在子程序中定义多个游标,但是一个块中的每一个游标必须有唯一的名字。声明游标后也是单条操作的,但是SELECT语句不能有INTO子句。
一个begin end中只能声明一个游标。

打开游标

1 OPEN cursor_name; 
打开先前声明的游标。

遍历游标数据

1 FETCH cursor_name INTO var_list;
这个语句用指定的打开游标读取下一行(如果有下一行的话),并且前进游标指针。取出当前行的结果,将结果放在对应的变量中,并将游标指针指向下一行的数据。
当调用fetch的时候,会获取当前行的数据,如果当前行无数据,会引发mysql内部的NOT FOUND错误。

关闭游标

1 CLOSE cursor_name; 
切记游标使用完毕之后要关闭。

游标举例

写一个函数,里面包含对students 学生用户成绩的计算和附加分计算
数据基础
 1 mysql> select * from students;
2 +-----------+-------------+-------+---------+
3 | studentid | studentname | score | classid |
4 +-----------+-------------+-------+---------+
5 | 1 | brand | 97.5 | 1 |
6 | 2 | helen | 96.5 | 1 |
7 | 3 | lyn | 96 | 1 |
8 | 4 | sol | 97 | 1 |
9 | 5 | b1 | 81 | 2 |
10 | 6 | b2 | 82 | 2 |
11 | 7 | c1 | 71 | 3 |
12 | 8 | c2 | 72.5 | 3 |
13 | 9 | lala | 73 | 0 |
14 | 10 | A | 99 | 3 |
15 | 16 | test1 | 100 | 0 |
16 | 17 | trigger2 | 107 | 0 |
17 | 22 | trigger1 | 100 | 0 |
18 +-----------+-------------+-------+---------+
19 13 rows in set 
编写包含游标的函数

这边注释很清晰,关键知识点都已经标红

 1 mysql>
2 /*判断函数如果存在则删除*/
3 DROP FUNCTION IF EXISTS fun_test;
4 /*声明结束符为$*/
5 DELIMITER $
6 /*创建函数,对符合条件的每个同学的分数进行加分,加的分数不能超过给定的值max_score*/
7 CREATE FUNCTION fun_test(max_score decimal(10,2))
8 RETURNS int
9 BEGIN
10 /*定义实时StudentId的变量*/
11 DECLARE var_studentId int DEFAULT 0;
12 /*定义计算后分数的变量*/
13 DECLARE var_score decimal(10,2) DEFAULT 0;
14 /*定义游标结束标志变量*/
15 DECLARE var_done int DEFAULT FALSE;
16 /*创建游标*/
17 DECLARE cur_test CURSOR FOR SELECT studentid,score from students where classid<>0;
18 /*游标结束时会设置var_done为true,后续可以使用var_done来判断游标是否结束*/
19 DECLARE CONTINUE HANDLER FOR NOT FOUND SET var_done=TRUE;
20 /*打开游标*/
21 OPEN cur_test;
22 /*使用Loop循环遍历游标*/
23 select_loop:LOOP
24 /*先获取当前行的数据,然后将当前行的数据放入var_studentId,var_score中,如果无数据行了,var_done会被置为true*/
25 FETCH cur_test INTO var_studentId,var_score;
26 /*通过var_done来判断游标是否结束了,退出循环*/
27 IF var_done THEN
28 LEAVE select_loop;
29 END IF;
30 /*对var_score值添加随机值,不能超过给定的分数*/
31 set var_score = var_score + LEAST(ROUND(rand()*10,0),max_score);
32 update students set score = var_score where studentId= var_studentId;
33 END LOOP;
34 /*关闭游标*/
35 CLOSE cur_test;
36 /*返回结果:可以根据实际情况返回需要的内容*/
37 RETURN 1;
38 END $
39 /*结束符置为;*/
40 DELIMITER ;
41 Query OK, 0 rows affected
调用函数
1 mysql>
2 /* 参数为8,表示加分上限为8 */
3 select fun_test(8);
4 +-------------+
5 | fun_test(8) |
6 +-------------+
7 | 1 |
8 +-------------+
9 1 row in set
查看结果

对比原来的成绩的值,发现成绩添加了随机值,但没超过给定的分数 8

 1 mysql> select * from students;
2 +-----------+-------------+-------+---------+
3 | studentid | studentname | score | classid |
4 +-----------+-------------+-------+---------+
5 | 1 | brand | 105.5 | 1 |
6 | 2 | helen | 98.5 | 1 |
7 | 3 | lyn | 97 | 1 |
8 | 4 | sol | 97 | 1 |
9 | 5 | b1 | 89 | 2 |
10 | 6 | b2 | 90 | 2 |
11 | 7 | c1 | 76 | 3 |
12 | 8 | c2 | 73.5 | 3 |
13 | 9 | lala | 73 | 0 |
14 | 10 | A | 100 | 3 |
15 | 16 | test1 | 100 | 0 |
16 | 17 | trigger2 | 107 | 0 |
17 | 22 | trigger1 | 100 | 0 |
18 +-----------+-------------+-------+---------+
19 13 rows in set
查看触发器日志

符合条件被修改分数的有9条数据,都已经被触发器记录到日志里面了

 1 mysql>
2 /*上一篇编写了触发器,当修改students表的时候触发日志记录 */
3 select * from triggerlog;
4 +----+--------------+---------------+-----------------------------------------+
5 | id | trigger_time | trigger_event | memo |
6 +----+--------------+---------------+-----------------------------------------+
7 | 1 | after | insert | new student info,id:21 |
8 | 2 | after | update | update student info,id:21 |
9 | 3 | after | update | delete student info,id:21 |
10 | 4 | after | update | from:test2,101.00 to:trigger2,106.00 |
11 | 5 | after | update | from:trigger2,106.00 to:trigger2,107.00 |
12 | 6 | after | update | delete student info,id:11 |
13 | 7 | after | update | from:brand,97.50 to:brand,105.50 |
14 | 8 | after | update | from:helen,96.50 to:helen,98.50 |
15 | 9 | after | update | from:lyn,96.00 to:lyn,97.00 |
16 | 10 | after | update | from:sol,97.00 to:sol,97.00 |
17 | 11 | after | update | from:b1,81.00 to:b1,89.00 |
18 | 12 | after | update | from:b2,82.00 to:b2,90.00 |
19 | 13 | after | update | from:c1,71.00 to:c1,76.00 |
20 | 14 | after | update | from:c2,72.50 to:c2,73.50 |
21 | 15 | after | update | from:A,99.00 to:A,100.00 |
22 +----+--------------+---------------+-----------------------------------------+
23 15 rows in set  
游标的执行过程
按照上面的例子,分析下这个游标的执行过程。
1、我们创建了一个游标,数据源取自于student学生表。
2、游标中有个指针,当打开游标的时候,会执行游标对应的select语句,这个指针会指向select结果中第一行记录。
3、当调用fetch 游标名称时,会获取当前行的数据,如果当前行无数据,会触发NOT FOUND异常。
当触发NOT FOUND异常的时候,我们可以使用一个变量来标记一下,如上面的:DECLARE CONTINUE HANDLER FOR NOT FOUND SET var_done=TRUE;
将变量var_done的值置为TURE,循环中就可以通过var_done的值控制循环的退出:LEAVE select_loop;。
如果当前行有数据,则将当前行数据存到对应的变量中,并将游标指针指向下一行数据,如下语句:FETCH cur_test INTO var_studentId,var_score;

总结

1、游标用来对查询结果进行遍历处理。
2、游标的使用过程:声明游标、打开游标、遍历游标、关闭游标。
3、游标主要用在循环处理、存储过程、函数中使用,用来查询结果集。
4、游标的缺点是只能一行一行操作,在数据量大的情况下,是不适用的,速度过慢。数据库大部分是面对集合的,业务会比较复杂,而游标使用会有死锁,影响其他的业务操作,不可取。 当数据量大时,使用游标会造成内存不足现象。

MySQL全面瓦解19:游标相关的更多相关文章

  1. MySQL全面瓦解24:构建高性能索引(策略篇)

    学习如果构建高性能的索引之前,我们先来了解下之前的知识,以下两篇是基础原理,了解之后,对面后续索引构建的原则和优化方法会有更清晰的理解: MySQL全面瓦解22:索引的介绍和原理分析 MySQL全面瓦 ...

  2. MySQL全面瓦解25:构建高性能索引(案例分析篇)

    回顾一下上面几篇索引相关的文章: MySQL全面瓦解22:索引的介绍和原理分析 MySQL全面瓦解23:MySQL索引实现和使用 MySQL全面瓦解24:构建高性能索引(策略篇) 索引的十大原则 1. ...

  3. 搭建 MySQL 5.7.19 主从复制,以及复制实现细节分析

    主从复制可以使MySQL数据库主服务器的主数据库,复制到一个或多个MySQL从服务器从数据库,默认情况下,复制异步; 根据配置,可以复制数据库中的所有数据库,选定的数据库或甚至选定的表. Mysql ...

  4. MySQL全面瓦解13:系统函数相关

    概述 提到MySQL的系统函数,我们前面有使用过聚合函数,其实只是其中一小部分.MySQL提供很多功能强大.方便易用的函数,使用这些函数,可以极大地提高用户对于数据库的管理效率,并更加灵活地满足不同用 ...

  5. MySQL全面瓦解23:MySQL索引实现和使用

    MySQL索引实现 上一篇我们详细了解了B+树的实现原理(传送门).我们知道,MySQL内部索引是由不同的引擎实现的,主要包含InnoDB和MyISAM这两种,并且这两种引擎中的索引都是使用b+树的结 ...

  6. MySQL 5.7.19 简易安装、卸载教程

    前言:传统的 exe 文件安装的MySQL,安装后特别难卸载,而且一旦处理不好,就容易出错,想再安装别的版本也不容易.因为这种方式的安装,虽然是不断的下一步,但是卸载的时候需要处理很多,在本文最后,有 ...

  7. MySQL中函数、游标、事件、视图

    MySQL中函数.游标.事件.视图基本应用举例(代码) MySQL中function用户自定义函数c,fun,fun是面向过程的实现方式只能传入参数,或不传入参数,不能传出参数,必有返回值函数中是不能 ...

  8. 一起学ASP.NET Core 2.0学习笔记(二): ef core2.0 及mysql provider 、Fluent API相关配置及迁移

    不得不说微软的技术迭代还是很快的,上了微软的船就得跟着她走下去,前文一起学ASP.NET Core 2.0学习笔记(一): CentOS下 .net core2 sdk nginx.superviso ...

  9. WordPress 4.8 安装配置教程 (基于 centos 7.3, php 7.0, mysql 5.7.19, nginx 1.12.1)

    最近想要整个 blog,记录自己工作.学习中的点滴.Wordpress 自然是首选,因为内容才是关键,所以也就不怕别人说太 low.网上大部份都是讲 wordpress 配合 apache 的安装教程 ...

随机推荐

  1. SpringBoot进阶教程(六十七)RateLimiter限流

    在上一篇文章nginx限流配置中,我们介绍了如何使用nginx限流,这篇文章介绍另外一种限流方式---RateLimiter. v限流背景 在早期的计算机领域,限流技术(time limiting)被 ...

  2. JavaScript实现自定义右键菜单

    JavaScript实现自定义右键菜单,思路如下: 1. 屏蔽默认右键事件: 2. 隐藏自定义的菜单模块(如div.ul等): 3. 右键点击特定或非特定区域,显示菜单模块: 4. 再次点击,隐藏菜单 ...

  3. qt界面设计

    需求 需要不同界面同样的位置有上下的公共部分 分解 在WPF中我亦接触到需要这样做的程序.在wpf中我将上下公共部分作为界面基类,其它界面都继承这个基类.我用qt准备定义一个stackedpanel, ...

  4. flowable中传入审批人是list

    package org.springblade.flow.engine.listener; import org.flowable.engine.delegate.DelegateExecution; ...

  5. 人脸识别--SeetaFace

    检测:http://download.csdn.net/detail/qq_14845119/9639840 对齐:http://download.csdn.net/detail/qq_1484511 ...

  6. 仅4步,就可通过SQL进行分布式死锁的检测与消除

    摘要:本文主要介绍在 GaussDB(DWS) 中,如何通过 SQL 语句,对分布式死锁进行检测和恢复. 分布式数仓应用场景中,我们经常遇到数据库系统 hang 住的问题,所谓 hang 是指虽然数据 ...

  7. Linux性能优化:CPU性能分析工具--vmstat

    Blog:博客园 个人 目录 参数说明 输出信息说明 procs memory swap io system cpu 示例 vmstat是Virtual Meomory Statistics(虚拟内存 ...

  8. druid监控

    1 @ConfigurationProperties(prefix = "spring.datasource") 2 @Bean 3 public DataSource druid ...

  9. IDEA中配置Git,在Github上clone项目到IDEA

    一.安装git 1.用homebrew安装git 运行以下命令安装 brew install git 默认的安装位置是 /usr/local/Cellar目录中(后面会用到) 二.在idea中配置Gi ...

  10. tep0.6.0更新聊聊pytest变量接口用例3个级别复用

    tep是一款测试工具,在pytest测试框架基础上集成了第三方包,提供项目脚手架,帮助以写Python代码方式,快速实现自动化项目落地.fixture是pytest核心技术,本文聊聊如何使用fixtu ...