mysql游标简单使用说明

本文详细介绍了MySQL中的游标概念及其使用步骤,包括如何声明、打开、读取和关闭游标。通过示例展示了使用游标进行循环处理数据的方法,包括计数器循环和越界标志控制循环,并强调了在处理游标时防止空数据的注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、游标的概念:

一条sql 取出对应n条结果资源的接口/句柄,就是游标,沿着游标可以一次取出一行。

通俗说法:

 我们写一条select查询语句,按理上会一下查询出所有的结果。但我们想对查询结果数据进行一条条获取并筛选,这时相当于对查询结果集进行筛选,这个过程就是游标

2、使用游标的步骤

declare  游标名 cursor  for  select_statement  #使用declare进行声明

open  游标名                     #打开游标

fetch  游标名 into var1,var2[,...] # fetch是获取游标当前指向的数据行,并将指针指向下一行,当游标已经指向最后一行时继续执行会造成游标溢出。

close  游标名               #关闭游标 

3、使用游标循环:

使用游标进行循环时,如果 当游标读到末尾,如果继续进行取值操作会发生报错。所以需要在游标读到末尾或末尾前,结束循环。

3.1、使用计数器来循环

drop procedure if exists test17;
delimiter $$
create procedure test17()
begin
  declare orgId varchar(20) ;
  declare orgName varchar(20);
  declare parentOrgId  varchar(20);
  declare currentRow int default 1;
  declare total int;
  declare test0107 cursor for select org_id,org_name,parent_org_id from org_info where org_id BETWEEN '100001' and '100005' ;  -- 定义游标
  select count(1) into total from org_info where org_id BETWEEN '100001' and '100005' ;
  open test0107; -- 打开游标
  while currentRow <= total do
	    fetch test0107 into orgId,orgName,parentOrgId; -- 从游标中取值
	    -- insert IGNORE into org_info_0107 values(orgId,orgName,parentOrgId);
		select orgId,orgName,parentOrgId;
			set currentRow = currentRow+1;
  end while;
  close test0107; -- 关闭游标
end$$
delimiter ;

call test17();

select * from org_info_0107;

3.2、使用越界标志来控制循环

在mysql cursor中,可以声明declare continue handler来操作1个越界标志

语法:

declare  continue/exist  handler for not found statement;

continue和exit的区别:

continue : 若没有数据返回,程序继续,并将变量is_found 设为0。

exit : 若没有数据返回,退出程序,并将变量is_found 设为0。

drop procedure if exists test17;
delimiter $$
create procedure test17()
begin
  declare orgId varchar(20) ;
  declare orgName varchar(20);
  declare parentOrgId  varchar(20);
  declare have boolean default true;  -- 声明是否有下一行,默认有
  declare test0107 cursor for select org_id,org_name,parent_org_id from org_info  where org_id BETWEEN '100001' and '100005' ;  -- 定义游标
  declare CONTINUE HANDLER for not found set  have = false;
  open test0107;  -- 打开游标
  fetch test0107 into orgId,orgName,parentOrgId; -- 从游标中取值,f防止取不到数据,直接执行CONTINUE HANDLER,设置have = false
  while have do
			select orgId,orgName,parentOrgId;
	    -- insert IGNORE into org_info_0107 values(orgId,orgName,parentOrgId);-- 将提取数据插入临时表
			fetch test0107 into orgId,orgName,parentOrgId; -- 从游标中取值
  end while; -- 没有下一行(即到游标末尾),结束循环
  close test0107; -- 关闭游标
end$$
delimiter ;

call test17();
select * from org_info_0107;
select count(1) from org_info_0107;

3.3、注意事项

在一些特殊情况下,有可能会读到空数据,或者sql语句就有错误,为了避免出现 对空数据的操作,需正确使用游标操作。如:

在打开游标后,应先手动 fetch 操作获取到一行数据,然后在通过循环,在循环里先做 处理内容,后进行 fetch操作。 这样如果在手动获取数据期间就没有获得到数据的话,就会执行 hava = false。

03-14
### 游标在数据库中的使用方法及示例 #### 定义 游标是一种临时的数据结构,用于存储由SQL查询返回的结果集。它可以逐行访问这些结果,并允许开发者对每一行数据进行操作。游标的典型应用场景包括需要逐条处理大量记录的情况。 --- #### 基本使用方法 创建和使用游标的流程通常分为以下几个部分: 1. **声明游标** 在使用游标之前,必须先对其进行声明。此步骤定义了游标所关联的SELECT语句及其结果集。 2. **打开游标** 打开游标后,可以开始遍历其内部的数据集合。 3. **提取数据 (FETCH)** 使用`FETCH`命令从游标中读取单行或多行数据到变量或其他目标位置。 4. **关闭游标** 当完成对游标的操作时,应将其关闭以释放资源。 5. **删除游标** *(可选)* 如果不再需要该游标,则可以选择显式销毁它。 上述基本概念适用于大多数关系型数据库管理系统(RDBMS),如Oracle, MySQL, PostgreSQL 和 Microsoft SQL Server等[^1]。 --- #### 示例代码展示 以下是几种常见RDBMS环境下关于如何利用游标的实例说明: ##### Java通过JDBC调用SQL Server游标 下面是一个简单的Java程序片段,展示了怎样借助JDBC驱动器连接至SQL Server数据库并运用ResultSet对象模拟游标的特性来进行分页检索工作: ```java // 加载驱动类 Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); String connectionUrl = "jdbc:sqlserver://localhost;databaseName=AdventureWorks"; try (Connection conn = DriverManager.getConnection(connectionUrl, "username", "password")) { String sql = "{CALL sp_cursoropen(?, 'SELECT * FROM Employees')}"; try (CallableStatement cstmt = conn.prepareCall(sql)) { int cursorId; // 创建游标 cstmt.registerOutParameter(1, Types.INTEGER); cstmt.execute(); cursorId = cstmt.getInt(1); // 获取指定数量的行数 String fetchSql = "{CALL sp_cursorexecute(?, ?)}"; try (PreparedStatement pstmt = conn.prepareStatement(fetchSql)) { pstmt.setInt(1, cursorId); ResultSet rs = null; do { pstmt.setInt(2, 10); // 每次获取10行 rs = pstmt.executeQuery(); while(rs.next()) { System.out.println("Employee ID:" + rs.getString("ID")); } }while(!rs.isLast()); } // 关闭游标 String closeCursorSql = "{CALL sp_cursorclose(?)}"; try (PreparedStatement psClose = conn.prepareStatement(closeCursorSql)){ psClose.setInt(1,cursorId ); psClose.executeUpdate(); } } } ``` 注意这里假设存在名为Employees表以及预置好的存储过程sp_cursoropen/sp_cursorscroll/sp_cursorfetch/sp_cursorclose来支持游标的相关功能[^2]. --- ##### 动态游标MySQL内的实践案例 对于某些高级需求而言,可能需要用到能够适应变化环境下的解决方案——即所谓的动态游标。以下是从官方文档摘录的一个例子,其中涉及到了构建自定义逻辑去操控不同类型的输入参数从而达到灵活调整的目的[^3]: ```sql DELIMITER $$ CREATE PROCEDURE dynamic_cursor_example(IN tableName VARCHAR(64), IN columnName VARCHAR(64)) BEGIN DECLARE done INT DEFAULT FALSE; DECLARE current_value DECIMAL(10 , 2 ); -- Define a handler to set the flag when no more rows are found. DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; PREPARE stmt FROM CONCAT('SELECT ',columnName,' INTO @current_val FROM ',tableName,' WHERE id=?'); OPEN cur_dynamic USING 1 ; read_loop: LOOP FETCH cur_dynamic INTO current_value ; IF done THEN LEAVE read_loop ; END IF ; /* Process each row */ SELECT CURRENT_VALUE AS processed_row ; END LOOP ; CLOSE cur_dynamic ; DEALLOCATE PREPARE stmt ; END$$ DELIMITER ; ``` 在此处我们看到的是一个通用化的模板形式,可以根据实际业务情况替换具体的字段名与表格名称即可满足多样性的请求模式。 --- ##### 达梦数据库中的隐式游标 除了显示定义外,在DM系列的产品线里还提供了另一种更为简便的方式叫做“隐式游标”。当执行诸如INSERT/UPDATE/DELETE这样的DML指令或者是单一值选取(`SELECT ... INTO`)的时候会自动触发此类机制的存在。用户仅需关注几个固定的属性便可轻松取得反馈信息比如受影响行的数量等等[^4]. 例如: ```plsql DECLARE v_count NUMBER := 0; BEGIN UPDATE employees SET salary=salary*1.1 WHERE department_id=90; IF SQL%ROWCOUNT>0 THEN DBMS_OUTPUT.PUT_LINE('Updated Rows:'||TO_CHAR(SQL%ROWCOUNT)); ELSE RAISE_APPLICATION_ERROR(-20001,'No records updated.'); END IF; EXCEPTION WHEN OTHERS THEN NULL; END; / ``` 在这里可以看到即使没有任何额外的动作发生,系统依旧能准确报告出刚刚动作影响了多少笔资料。 --- ### 总结 综上所述,无论是在传统的静态环境中还是更加复杂的动态条件下,亦或是高度集成化平台之上都有各自特色的实现手段可供选择。理解它们之间的差异有助于我们在面对具体问题时候做出最优决策。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值