20. Mysql 游标的定义和使用

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 20. Mysql 游标的定义和使用

概念

游标(Cursor)是一种数据库对象,可以指向存储在数据库表中的数据行指针。用于在 sql 语句的执行过程中,通过对查询结果集进行逐行的操作和访问。它提供了一种逐行遍历结果集的方式,可以在查询结果集上进行灵活的操作和处理。

使用场景:

  • 需要逐行处理查询结果集,进行一些特定的操作或计算。
  • 需要在一个事务中多次访问相同的查询结果集。
  • 需要在一个过程中对查询结果集进行多次迭代。
  • 需要对查询结果集进行一些复杂的业务逻辑处理。

使用限制:

  • 只能在存储过程、函数和触发器中使用游标。
  • 游标只能存放 select 语句查询的结果集合,不能存放 show 语句查询的结果。

游标的基本语法

声明游标

使用 declare 语句来声明一个游标,并指定查询语句作为游标的结果集。

示例代码:

declare cursor_name cursor for select_statement;

打开游标

使用 open 语句来打开一个游标,打开游标即将查询结果集加载到游标中,为后面游标的逐条读取结果集中的记录做准备。

示例代码:

open cursor_name;

使用游标

使用 fetch 语句,可以从游标中获取一行数据,并将数据赋值给变量。

示例代码:

fetch cursor_name into variable1, variable2[, variable3, ...];


variable1 必须在声明游标之前就定义好。游标的查询结果集中的列数,必须跟 into 后面的变量数一致,否则,在存储过程执行的时候,会提示错误。

关闭游标

使用 close 语句来关闭一个游标,因为游标会占用系统资源 ,如果不及时关闭,游标会一直保持到存储过程结束,影响系统运行的效率。

示例代码:

close cursor_name;

精选示例

需求:统计数据库中每个表的实际数量。

方法一:创建存储过程,并且使用游标。

drop procedure if exists get_table_info;
create procedure get_table_info()
begin
    -- 定义变量
    declare finished bool default 0;
    declare db_tb_name varchar(255) default '';
    declare for_cnt int default 0;

    -- 声明游标
    declare cur cursor for
        select concat('`', table_schema, '`.`', table_name, '`') as db_tb_name
        from information_schema.tables
        group by table_schema, table_name;-- 将所有表查询出来

    declare continue handler for not found set finished = 1;-- 无数据更新finished变量

    -- 打开游标
    open cur;
    truncate table sql_test1.table_info;-- 清空表数据
    l1:
    loop
        fetch cur into db_tb_name;-- 使用游标
        if finished = 1 then
            leave l1;
        end if;
        set @sql = '';
        set @sql = concat('insert into sql_test1.table_info(db_tb_name,fact_cnt) \n\tselect \'', db_tb_name,'\',count(*) \n\tfrom ', db_tb_name);
        prepare stmt from @sql;-- 预编译准备好的拼接sql
        execute stmt;-- 执行
        deallocate prepare stmt;-- 释放
    end loop;
    -- 关闭游标
    close cur;
    select '录入完成。' as info;
end;

call get_table_info();-- 调用
select * from sql_test1.table_info;-- 查询结果

其中,当游标无数据触发 not found 异常的时候,将变量更新为 finished = 1 ,这样就可以控制循环的退出了。

方法二:创建存储过程,不使用游标。

drop procedure if exists get_table_info1;
create procedure get_table_info1()
begin
    declare i int default 1;
    -- 计算出需要遍历查询的表总数
    set @max_db_tb_cnt = (select count(distinct table_schema, table_name) as db_tb_cnt
                          from information_schema.tables);

    truncate table sql_test1.table_info;-- 清空表数据
    -- 根据表的总数量遍历
    while i <= @max_db_tb_cnt
        do
            set @db_tb_name = '';
            set @sql = '';
            select db_tb_name
            into @db_tb_name
            from (select db_tb_name
                       , row_number() over (order by db_tb_name) as row_number1
                  from (select concat(table_schema, '.', table_name) as db_tb_name
                        from information_schema.tables) as t1) as t2
            where row_number1 = i;-- 根据遍历的i变量,查询出对应的表名,并且更新@db_tb_name变量
            set @sql = concat('insert into sql_test1.table_info(db_tb_name,fact_cnt) \n\tselect \'', @db_tb_name,
                              '\',count(*) \n\tfrom ', @db_tb_name);
            prepare stmt from @sql;
            execute stmt;
            deallocate prepare stmt;
            set i = i + 1;-- 更新
        end while;
    select '录入完成。' as info;
end;

call get_table_info1();
select * from sql_test1.table_info;

不使用游标,该方法利用 row_number 开窗函数给每个结果集编号,再利用循环即可实现最终结果。

总结

通过游标的知识和示例,可以发现游标其实并不复杂,非常好理解,就是依次遍历结果集,如果结果集中有特殊的序号,也是可以实现一样的效果,方法不嫌多,多去实践用起来。

参考资料

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
4月前
|
存储 关系型数据库 MySQL
轻松入门MySQL:揭秘MySQL游标,数据处理的神秘利器(16)
轻松入门MySQL:揭秘MySQL游标,数据处理的神秘利器(16)
|
1天前
|
SQL 存储 关系型数据库
mysql-视图的定义和简单使用
这篇文章介绍了MySQL中视图的定义和简单使用方法,包括视图的创建规则和使用限制。通过一个实际的例子,展示了如何创建视图以及如何使用视图来简化复杂的SQL查询操作。
mysql-视图的定义和简单使用
|
2月前
|
SQL 存储 索引
MySQL设计规约问题之为什么应该把字段定义为NOT NULL并且提供默认值
MySQL设计规约问题之为什么应该把字段定义为NOT NULL并且提供默认值
|
3月前
|
存储 SQL 关系型数据库
MySQL存储过程_触发器_游标——Baidu Comate
MySQL存储过程_触发器_游标——Baidu Comate
31 0
|
3月前
|
存储 SQL 关系型数据库
MySQL游标的创建与使用——Baidu Comate全文SQL-AI生成
MySQL游标的创建与使用——Baidu Comate全文SQL-AI生成
42 0
|
3月前
|
存储 关系型数据库 MySQL
【MySQL技术内幕】3.3-套接字文件、pid文件和表结构定义文件
【MySQL技术内幕】3.3-套接字文件、pid文件和表结构定义文件
30 0
|
3月前
|
存储 关系型数据库 MySQL
MySQL数据库——存储过程-游标(介绍-声明游标、打开游标、获取游标记录、关闭游标,案例)
MySQL数据库——存储过程-游标(介绍-声明游标、打开游标、获取游标记录、关闭游标,案例)
79 0
|
3月前
|
存储 SQL 关系型数据库
MySQL数据库——存储过程-变量(系统变量、用户定义变量、局部变量)
MySQL数据库——存储过程-变量(系统变量、用户定义变量、局部变量)
112 0
|
3月前
|
存储 关系型数据库 MySQL
mysql 存储过程游标 循环输出select 查询结果
mysql 存储过程游标 循环输出select 查询结果
47 0
|
4月前
|
关系型数据库 MySQL Java
使用shardingjdbc执行MySQL游标操作时报错
使用shardingjdbc执行MySQL游标操作时报错
100 3

热门文章

最新文章