首页 > 数据库 >MySQL Cursor 的定义和使用

MySQL Cursor 的定义和使用

时间:2023-04-09 18:34:21浏览次数:48  
标签:定义 游标 Cursor MySQL 声明 DECLARE name

前言

最近项目中需要迁移数据,对旧表A 的每一行记录处理后插入 新表B。 Google一下,发现 MySQL Cursor 适合这种场景,上篇文章介绍了 handler,那么本篇就一起看下 Cursor 是什么吧!

本文基于 MySQL 8.0

定义

我们来看看 ChatGPT 是怎么理解MySQL Cursor 的吧:

  • 我:MySQL Cursor 是什么?

  • ChatGPT:MySQL 中的 Cursor 是一种用于在存储过程、函数等数据库对象中,按照一定顺序依次遍历结果集中每一条记录的机制。具体地说,使用 Cursor 可以将结果集中的记录一条一条地处理,每次处理一条记录,直到处理完所有记录。

    Cursor 的使用非常灵活,可以用于在数据库对象中对结果集进行迭代,执行某些计算、条件判断等操作,在不同记录之间进行状态转移等。可以使用 Cursor 访问结果集的每一行、每一列,并对结果集中的数据进行修改、删除、插入等操作。

    需要注意的是,使用 Cursor 需要谨慎,因为 Cursor 首先会将所有记录都读入到内存中,开销较大,而且 Cursor 可能会导致并发性和性能问题。除非必要,一般情况下不建议滥用 Cursor。

Cursor 就是游标,可以理解为 Java 集合迭代器的游标,或者数组的下标。在存储过程中对查询的数据进行处理时,由于 Select 返回的是个数据集,无法处理第一行、下一行、前十行的数据,除非每次修改 where 条件获得想要的那一条记录,而 Cursor 可以很方便的处理这种情况。

MySQL游标是只读的,不可滚动且不敏感的。

  • 只读:无法通过游标更新表中的数据。
  • 不可滚动:只能朝着一个方向挨个遍历,不能反向遍历;不能跳行或者跳转到特定行。
  • 不敏感:有两种光标:敏感型游标和不敏感游标。敏感型光标指向实际数据,而不敏感型光标使用数据的临时副本。敏感型游标比不敏感游标执行得更快,因为它不必创建临时数据副本。但是,其他连接所做的任何更改都将影响敏感光标正在使用的数据。MySQL游标是不敏感的。

Cursor 的使用

Cursor 的使用分为如下四步:

  • 声明游标
  • 打开游标
  • 获取数据
  • 关闭游标

声明游标

DECLARE cursor_name CURSOR FOR select_statement

注意:

  • 游标声明中,必须有一个 Select 语句
  • Select 语句中不能包含 into 关键字
  • 游标声明,必须在 handler 声明之前,在 变量 和 condition 声明之后
  • 在一个代码块中可以声明多个游标,但是多个游标的名字不能相同

打开游标

OPEN cursor_name

获取数据

FETCH cursor_name INTO var_name [, var_name] ...

注意:

  • fetch 中的 cursor_name 必须是开启状态
  • fetch 语句中,var_name 的数量要与声明语句中 Select 查询列的数量一致,保证每个列都有变量接收

使用 fetch 获取游标中 Select 语句的下一条记录,并将游标前进一步。如果查询到数据,就将每列对应的值赋值给相应变量;如果已经到了数据集末尾,没有数据可以获取了,会产生一个值为 '02000' 的 SQLSTATE (NOT FOUND),此时可以声明一个 handler 来处理这种情况。

如果我们在一个代码块中有多个游标,那么一个游标 fetch 时如果产生 NOT FOUND,handler 的触发可能会对另一个游标产生影响。如果想避免这种影响,可以在多个 BEGIG...END 代码块中分别声明各自的handler,然后再操作游标,保证互不影响。

关闭游标

CLOSE cursor_name
  • 如果关闭一个非开启状态的游标会报错
  • 对于声明在一个 BEGIN...END 中的游标,如果没有显示的使用 close 去关闭的话,执行到 END 会自动关闭游标

示例

如下示例中,我们声明了两个游标 cur1 和 cur2,分别查询 id、data 和 i 字段;还声明了一个 CONTINUE handler,当其中一个游标访问到数据集末尾时,设置变量 done 为 TRUE,用于控制循环退出。

其中几个注意点:

  1. 声明游标必须在 handler 声明之前,在 变量 和 condition 声明之后
  2. 多个游标名称不能重复
  3. 使用游标前需要先打开游标
  4. 游标中 select 列的数量,与 fetch into 变量数量一样
  5. 使用完关闭游标
CREATE PROCEDURE curdemo()
BEGIN
  DECLARE done INT DEFAULT FALSE;
  DECLARE a CHAR(16);
  DECLARE b, c INT;
  DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1;
  DECLARE cur2 CURSOR FOR SELECT i FROM test.t2;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

  OPEN cur1;
  OPEN cur2;

  read_loop: LOOP
    FETCH cur1 INTO a, b;
    FETCH cur2 INTO c;
    IF done THEN
      LEAVE read_loop;
    END IF;
    IF b < c THEN
      INSERT INTO test.t3 VALUES (a,b);
    ELSE
      INSERT INTO test.t3 VALUES (a,c);
    END IF;
  END LOOP;

  CLOSE cur1;
  CLOSE cur2;
END;

总结

本篇文章介绍了 MySQL Cursor 的使用方式,主要分为四步:声明、开启、获取、关闭,比较适合在刷数据或迁移数据时使用。

更多

微信公众号:CodePlayer 个人博客:  https://lifelmy.cn/

标签:定义,游标,Cursor,MySQL,声明,DECLARE,name
From: https://blog.51cto.com/u_12260130/6178914

相关文章

  • 爬虫最后一天,爬取到的数据存到mysql中,爬虫和下载中间件、加代理、cookie、header、se
    爬到的数据存到mysql中classFirstscrapyMySqlPipeline:defopen_spider(self,spider):print('我开了')self.conn=pymysql.connect(user='root',password="",host='127.0.0.1......
  • (5)使用函数验证哥德巴赫猜想:任何一个不小于6的偶数均可表示为两个奇和。输入两个正整数
    #include<stdio.h>#include<math.h>intprime(intm){  inti;  if(m<2)    return0;  for(i=2;i<=sqrt(m);i++){    if(!(m%i))      return0;  }  return1;}intmain(){  intm,n,flag;  printf("Enterm,......
  • 多表查询和python操作mysql
    目录多表查询的两种方法方法1:连表操作方法2:子查询小知识点补充说明可视化软件NaviCat多表查询练习题1、查询所有的课程的名称以及对应的任课老师姓名2.查询平均成绩大于八十分的同学的姓名和平均成绩3.查询没有报李平老师课的学生姓名4.查询没有同时选修物理课程和体育课程的学生......
  • (已解决)安装PyMySQL出现问题--'pip' 不是内部或外部命令,也不是可运行的程序 或批处理文
    问题描述:输入cmd,进入命令窗口,输入pipinstallpymysql时候出现下面的问题: 然后进入python环境中去输入还是报错:问题原因:环境变量配置出错,cmd下无法调用pip程序。解决办法:①首先退出python环境,输入命令:exit() ②然后去电脑里面找到python的安装位置,如图类似这样的文件......
  • Navicat软件、python操作MySQL
    目录Navicat软件1.软件简介2.navicat基本操作python操作MySQL1.链接、执行sql、关闭(游标)2.查询结果3.增删改查4.使用pymysql写一个注册和登录的案例Navicat软件1.软件简介第三方开发的用来充当数据库客户端的简单快捷的操作界面 无论第三方软件有多么的花里胡哨,底层的本质还......
  • 3.自定义注解实现系统日志记载
    前言今天来分享一下我昨天的成果,昨天计划复现若依系统的系统日志记载功能,若依的系统日志记载的主要实现使用过自定义注解配合切面类来实现的,这里会把标注@Log的方法在用户调用完后,将方法的一部分信息记录在数据库的指定数据表中。因此我们需要java的spring开发四层结构:domain......
  • 讲解MySQL8.0备份与还原工具(mysqlbackup)
    一、安装mysqlbackup下载登录oracleedelivery,进入下载连接选择适合你系统的版本下载,在这里我使用的是银河麒麟KylinOSServerV10SP2,因此我选择一个通用的预编译二进制的tar包,如下图:没有Oracleedelivery账号的朋友可以到私信我索取软件安装包。安装[root@light]tarx......
  • GitHub Actions:从使用action操作到自定义action操作
    (目录)1、使用action操作文档https://docs.github.com/zh/actions/quickstart.github/workflows/github-actions-demo.ymlname:GitHubActionsDemorun-name:${{github.actor}}istestingoutGitHubActions......
  • mysql 查询练习题
    1.查出至少有一个员工的部门。显示部门编号、部门名称、部门位置、部门人数。selectd.deptno,d.dname,d.loc,r.countfromdeptd,(selectdeptno,count(*)countfromempgroupbydeptno)rwhered.deptno=r.deptno;2.列出薪金比smith高的所有员工。select*fro......
  • ant-design-vue日历面板 a-calendar 属性自定义设置
    通过自定义属性设置,实现一个周末与工作日的不同颜色设置效果图: 使用的属性:自定义头部设置headerRender自定义日期显示dateFullCellRender代码:<template><divclass="box"><h3>1.自定义头部;2.自定义日期显示,工作日显示,周末显示</h3><a-c......