游标cursor

本文深入探讨了SQL游标的使用步骤、注意事项,并详细解释了游标的属性%found和%notfound的用法。通过示例代码,展示了如何在游标中获取数据并进行输出,以及如何利用游标属性进行数据循环处理。

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

set serveroutput on;

游标使用步骤:

SQL> declare
  2      cursor      empcursor is select * from s_emp; --1.定义游标--
  3      var_emp     s_emp%rowtype;
  4  begin
  5      open        empcursor;      --2.打开游标--
  6      fetch       empcursor into var_emp;     --3.获取游标--
  7      dbms_output.put_line(var_emp.id||':'||var_emp.first_name);
  8      fetch       empcursor into var_emp;
  9      dbms_output.put_line(var_emp.id||':'||var_emp.first_name);
 10      close       empcursor;      --4.关闭游标--
 11  end;
 12  /    

执行结果:

1:Carmen
2:LaDoris

两个注意事项:1.注释要前后都有“--”


SQL> declare
  2      cursor mycursor is select first_name,salary,name 
  3          from s_emp,s_dept
  4              where dept_id=s_dept.id;
  5      var_e   mycursor%rowtype;
  6  begin
  7      open    mycursor;
  8      fetch   mycursor into var_e;
  9      dbms_output.put_line(var_e.first_name||':'||var_e.salary||':'
 10          ||var_e.name);
 11      close mycursor;
 12  end;
 13  /    
Carmen:2500:Administration


PL/SQL procedure successfully completed.

-------------------------------------------------------------------------------------------------------------

****游标的属性
    1.游标名%found  
        当提取游标数据时,如果提取到新数据,这个属性就返回TRUE;反之返回FALSE。
    游标必须处于打开状态,否则返回非法游标,游标必须fetch,否则返回NULL值。
    2.游标名%notfound
        当提取游标数据时,如果提取到新数据,这个属性就返回FALSE;反之返回TRUE。
    游标必须处于打开状态,否则返回非法游标,游标必须fetch,否则返回NULL值。       
      declare
          cursor empcursor is select
            e.id eid,first_name,name
            from s_emp e,s_dept d
            where e.dept_id=d.id and 
            e.id<11;
          var_emp  empcursor%rowtype;   
      begin
          open  empcursor;
          loop
          fetch empcursor into  var_emp;
          /* 如何结束循环? */
          exit  when  empcursor%notfound;
          dbms_output.put_line(var_emp.eid
          ||':'||var_emp.first_name||':'
          ||var_emp.name);
          end loop;
          close empcursor; 
      end;
      /   

1:Carmen:Administration
2:LaDoris:Operations
3:Midori:Sales
4:Mark:Finance
5:Audry:Administration
6:Molly:Operations
7:Roberta:Operations
8:Ben:Operations
9:Antoinette:Operations
10:Marta:Operations


PL/SQL procedure successfully completed.

-------------------------------------------------------------------------------------------------------------------

<think>好的,用户之前询问了存储过程的算法语句知识点,现在他们想详细了解游标Cursor)的使用。我需要先回顾之前的回答,确保内容连贯,并补充更详细的游标信息。 首先,在之前的回答里,我简要提到了游标用于逐行处理结果集,但用户现在需要更深入的内容。我应该详细解释游标的概念、使用场景、基本步骤,以及不同数据库的语法差异,同时给出示例和注意事项。 用户可能的实际需求是在处理需要逐行操作的数据,比如数据迁移、逐行验证或复杂计算。他们可能在使用存储过程时遇到了性能问题,或者在处理大量数据时遇到困难,所以需要了解如何正确使用游标,同时避免常见陷阱。 需要确保回答结构清晰,分步骤说明游标的使用,包括声明、打开、获取、关闭和释放。同时,对比不同数据库(如MySQL、SQL Server、Oracle)的语法差异,这对用户来说很重要,因为他们可能在不同环境中工作。 另外,用户可能对游标的优缺点不太清楚,需要强调游标的性能问题,并提供优化建议,比如尽量使用集合操作替代游标。给出实际示例,如数据迁移或逐行处理日志,帮助用户理解应用场景。 还要注意错误处理和资源释放,避免游标未关闭导致的内存泄漏。最后,通过总结强调游标的适用场景和注意事项,确保用户能合理使用游标,避免滥用。</think>### 游标Cursor)的详细使用指南 --- #### **1. 游标是什么?** 游标Cursor)是数据库中用于 **逐行处理查询结果集** 的机制,类似于编程中的迭代器。它允许在存储过程或脚本中逐条访问记录,并对每条记录执行特定操作。 - **核心作用**:处理需要逐行操作的复杂业务逻辑(如数据校验、逐行计算、级联更新)。 - **适用场景**:无法通过单条 SQL 语句完成的集合操作,必须逐行处理时使用。 --- #### **2. 游标的使用步骤** 游标的典型生命周期分为 **5 个阶段**: | 步骤 | 描述 | |--------------|----------------------------------------------------------------------| | **声明游标** | 定义游标名称及其关联的查询语句(SELECT)。 | | **打开游标** | 执行查询,将结果集加载到内存中。 | | **逐行获取数据** | 通过 `FETCH` 逐行读取数据,并将值赋给变量。 | | **关闭游标** | 释放游标占用的内存资源。 | | **释放游标** | (部分数据库如 SQL Server 需要显式释放) | --- #### **3. 不同数据库的游标语法** --- ##### **3.1 MySQL 中的游标** ```sql -- 声明游标 DECLARE cursor_name CURSOR FOR SELECT column1, column2 FROM table WHERE condition; -- 声明处理程序(用于循环结束时的退出条件) DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; -- 打开游标 OPEN cursor_name; -- 循环读取数据 read_loop: LOOP FETCH cursor_name INTO var1, var2; IF done = 1 THEN LEAVE read_loop; END IF; -- 在此处处理数据(如插入、更新等) END LOOP; -- 关闭游标 CLOSE cursor_name; ``` --- ##### **3.2 SQL Server 中的游标** ```sql -- 声明游标 DECLARE cursor_name CURSOR FOR SELECT column1, column2 FROM table WHERE condition; -- 打开游标 OPEN cursor_name; -- 获取第一行数据 FETCH NEXT FROM cursor_name INTO @var1, @var2; -- 循环读取数据 WHILE @@FETCH_STATUS = 0 BEGIN -- 处理数据 PRINT 'Column1: ' + CAST(@var1 AS VARCHAR) + ', Column2: ' + CAST(@var2 AS VARCHAR); -- 获取下一行 FETCH NEXT FROM cursor_name INTO @var1, @var2; END; -- 关闭并释放游标 CLOSE cursor_name; DEALLOCATE cursor_name; ``` --- ##### **3.3 Oracle 中的游标** ```sql -- 显式游标声明 DECLARE CURSOR cursor_name IS SELECT column1, column2 FROM table WHERE condition; v_column1 table.column1%TYPE; v_column2 table.column2%TYPE; BEGIN OPEN cursor_name; LOOP FETCH cursor_name INTO v_column1, v_column2; EXIT WHEN cursor_name%NOTFOUND; -- 退出条件 -- 处理数据(如DBMS_OUTPUT.PUT_LINE输出) END LOOP; CLOSE cursor_name; END; ``` --- #### **4. 游标的类型** - **静态游标(Static Cursor)** 结果集在打开时固定,不反映其他事务的更改(SQL Server 中 `STATIC` 关键字)。 - **动态游标(Dynamic Cursor)** 结果集实时反映其他事务的更改(SQL Server 中 `DYNAMIC` 关键字)。 - **仅向前游标(Forward-Only)** 只能单向逐行读取,不可回滚(MySQL 默认类型)。 --- #### **5. 游标的实际应用示例** ##### **场景:将订单表数据迁移到历史表(MySQL)** ```sql DELIMITER $$ CREATE PROCEDURE migrate_orders() BEGIN DECLARE done INT DEFAULT 0; DECLARE order_id INT; DECLARE order_date DATE; DECLARE cur CURSOR FOR SELECT id, order_date FROM orders WHERE status = 'completed'; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; OPEN cur; read_loop: LOOP FETCH cur INTO order_id, order_date; IF done = 1 THEN LEAVE read_loop; END IF; -- 插入历史表 INSERT INTO orders_history (id, order_date) VALUES (order_id, order_date); END LOOP; CLOSE cur; END $$ DELIMITER ; ``` --- #### **6. 游标的优缺点** | **优点** | **缺点** | |------------------------------|---------------------------------------| | 支持逐行复杂逻辑处理 | 性能低(频繁的上下文切换和 I/O 操作) | | 可访问结果集中的任意行 | 占用内存和锁资源 | | 灵活性高(如动态 SQL 处理) | 代码复杂度高,易出错 | --- #### **7. 注意事项** 1. **尽量少用游标** - 优先使用 `JOIN`、`UPDATE`、`CASE` 等集合操作替代。 - 游标适合处理无法用单条 SQL 实现的场景。 2. **性能优化** - 使用 `FAST_FORWARD`(SQL Server)或 `FOR READ ONLY`(Oracle)等高效游标类型。 - 减少循环内的 SQL 操作次数。 3. **资源释放** - 必须显式关闭游标,避免内存泄漏。 4. **错误处理** - 捕获游标操作中的异常(如 `NO_DATA_FOUND`)。 --- #### **8. 替代方案** - **临时表**:将结果集存入临时表,再用集合操作处理。 - **批量操作**:使用 `BULK COLLECT`(Oracle)或 `LIMIT ... OFFSET`(MySQL)分批次处理。 --- #### **9. 总结** - **游标是处理逐行逻辑的最后手段**,需谨慎使用。 - **核心步骤**:声明 → 打开 → 获取 → 关闭 → 释放。 - **性能关键**:减少循环内的 SQL 操作,优先选择集合操作。 合理使用游标可以解决特定复杂问题,但滥用会导致严重的性能瓶颈。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值