目录

  1. 游标的定义
  2. 游标的分类
  3. 游标的工作原理
  4. 游标的数据缓存区(内存结构)
  5. 显式游标与隐式游标
  6. 游标使用示例
  7. 性能与优化建议

1. 游标的定义

  • 游标(Cursor) 是 Oracle 用来处理多行查询结果的机制
  • 查询语句执行后,返回的结果集被缓存在内存中,游标就像一个指针,逐行遍历该结果集
  • 游标允许开发者对查询结果进行逐行处理

2. 游标的分类

类型说明
隐式游标Oracle自动为每条SQL语句创建,开发者不直接控制
显式游标开发者声明、打开、操作和关闭的游标

3. 游标的工作原理

  1. SQL语句解析与执行:Oracle编译SQL,生成执行计划
  2. 结果集生成:执行计划访问数据块,得到符合条件的多行数据
  3. 数据缓存:结果集存入内存区,游标指向该内存区域
  4. 逐行访问:通过FETCH操作,游标逐行读取数据,处理业务逻辑
  5. 关闭游标:释放相关资源

4. 游标的数据缓存区(内存结构)

  • 游标执行查询后,Oracle会将结果集缓存到内存区域(称为数据缓存区,或称“游标缓冲区”)
  • 该缓存区存储了查询结果的行数据,供游标逐行读取
  • 数据缓存区通常位于服务器进程的 PGA(Program Global Area)内存中

细节说明

  • Oracle不会一次性把所有数据加载到缓存区,而是按需批量提取(fetch)一定行数,称为预取(prefetch)
  • 预取机制提高了性能,减少了服务器和客户端的交互次数
  • 游标缓冲区大小受参数影响,如 OPTIMIZER_INDEX_COST_ADJSESSION_CACHED_CURSORS
  • 游标关闭后,缓存区释放

5. 显式游标与隐式游标

隐式游标

  • Oracle自动维护,如执行SELECT INTO、INSERT、UPDATE、DELETE语句时产生
  • 通过SQL%FOUNDSQL%ROWCOUNT等属性监控状态

显式游标

  • 需声明:CURSOR cursor_name IS SELECT ...
  • 控制游标生命周期:OPENFETCHCLOSE
  • 能够逐行处理复杂结果集

6. 游标使用示例

DECLARE
    CURSOR emp_cur IS
        SELECT employee_id, first_name, salary FROM employees WHERE department_id = 10;
    v_emp_id employees.employee_id%TYPE;
    v_name employees.first_name%TYPE;
    v_salary employees.salary%TYPE;
BEGIN
    OPEN emp_cur;
    LOOP
        FETCH emp_cur INTO v_emp_id, v_name, v_salary;
        EXIT WHEN emp_cur%NOTFOUND;
        DBMS_OUTPUT.PUT_LINE('ID: ' || v_emp_id || ', Name: ' || v_name || ', Salary: ' || v_salary);
    END LOOP;
    CLOSE emp_cur;
END;

7. 性能与优化建议

  • 减少游标打开次数,避免频繁打开关闭
  • 使用游标变量(REF CURSOR)提高灵活性
  • 控制预取行数:客户端可设置,如 JDBC驱动默认预取行数为10
  • 使用Bulk Collect批量获取数据,减少上下文切换
  • 关闭不再使用的游标,释放资源