游标(Cursor)是Oracle数据库中用于处理查询结果集的重要机制,它允许开发者逐行处理SQL语句返回的数据。
目录
一、游标基本概念
1. 游标定义
2. 游标分类
二、静态游标
(一)显式游标
【一】不带参数,普通的显示游标
1. 显式游标使用步骤
2. 语法
3. 显式游标的四个属性
4. 注意事项
5. %notfound 和普通循环一起用
6. %found 和while循环一起用
7. 基本示例
【二】带参数的显示游标
1. 语法结构
2. 示例代码
3. 练习
(二)隐式游标
1.隐式游标的四个属性
2. 示例代码
二、动态游标
【动态游标注意事项】
【强类型游标和弱类型游标区别】
【动态游标类型定义】
(一)强类型游标
(二)弱类型游标(SYS_REFCURSOR)
(三)动态游标
三、游标变量与批量处理
1. 游标变量
2. 批量提取(BULK COLLECT)
3. 批量处理与FORALL
四、游标最佳实践
五、高级游标技术
1. 可更新游标
2. 游标子查询
3. 游标表达式(12c+)
一、游标基本概念
1. 游标定义
游标是一个指向上下文区域的指针,用于处理SQL语句的执行结果。它提供了以下能力:
-
逐行访问结果集
-
跟踪当前处理的行
-
对结果集进行修改或删除操作
2. 游标分类
游标类型 | 描述 | 生命周期 | 控制方式 | |
---|---|---|---|---|
静态 | 隐式游标 | Oracle自动为每条SQL语句创建 | 单条SQL执行期间 | Oracle自动管理 |
显式游标 | 开发者显式定义 | 从OPEN到CLOSE | 开发者手动控制 | |
动态 | REF游标 | 动态游标,运行时确定 | 灵活控制 | 开发者控制 |
二、静态游标
(一)显式游标
显示的游标:在declare的部分用is显示了的游标
【一】不带参数,普通的显示游标
1. 显式游标使用步骤
(1)声明游标:定义游标及其关联的SELECT语句
(2)打开游标:执行查询,填充结果集
(3)提取数据:从结果集中获取行数据
(4)关闭游标:释放资源
2. 语法
-- 1. 声明游标
CURSOR cursor_name [(parameters)][RETURN return_type]IS select_statement;-- 2. 打开游标
OPEN cursor_name [(parameters)];-- 3. 提取数据
FETCH cursor_name INTO variable_list;-- 4. 关闭游标
CLOSE cursor_name;-- 5. 举例
declare
cursor cur_name is select语句;---声明一个显示游标
begin open cur_name;--打开游标fetch cur_name into 变量;--赋值变量,提取记录dbms_output.put_line()---打印close cur_name;--关闭游标
end;
/
3. 显式游标的四个属性
属性 | 返回值 | 描述 | 说明 |
cursor_name%FOUND | 布尔值 | 如果最近一次 FETCH返回行则为TRUE | 游标的指针是否有值(有)对 (没有) 错 |
cursor_name%NOTFOUND | 布尔值 | 如果最近一次 FETCH未返回行则为TRUE | 游标的指针是否没值(有值)错, (没值)对,理论上可以返回空 在open之后fetch之前可以返回空 |
cursor_name%ROWCOUNT | 数值 | 到目前为止已提取的行数 | 游标的指针已经指了几行,返回数值, 但是要赋给变量才能显示 返回最近一次从游标读取的数据 |
cursor_name%ISOPEN | 布尔值 | 如果游标已打开则为TRUE | 判断是否打开游标(打开)对 (没有)错 |
4. 注意事项
首先声明一个游标,使用之前先打开游标,提取记录只能一行,可以多列
使用完游标要关闭游标,可以通过open打开游标继续使用
5. %notfound 和普通循环一起用
open→loop fetch→exit when %notfound→打印→end loop→close【举例1】declarecursor cur_a is select * from emp;---声明一个显示游标v_emp emp%rowtype;---声明变量v1 varchar2(20);---声明变量
beginopen cur_a;--打开游标loop/*普通循环*/ fetch cur_a into v_emp;/*赋值变量,抓取记录*/ exit when cur_a%notfound;/*和普通循环一起用*/ dbms_output.put_line(v_emp.ename); end loop;/*结束循环*/ close cur_a;/*关闭游标*/ end;
/-- LOOP循环语法
declare 部分;
beginloop 要执行的语句;exit when 退出的条件;end loop;
end;
注意事项:进入循环不需要条件
6. %found 和while循环一起用
open→fetch→while %found loop→打印→fetch→end loop→close【举例】
declarecursor cur_a is select * from emp;v_emp emp%rowtype;
beginopen cur_a;fetch cur_a into v_emp;while cur_a%found loopdbms_output.put_line(v_emp.ename);fetch cur_a into v_emp;end loop;close cur_a;
end;
7. 基本示例
DECLARE-- 1. 声明游标CURSOR emp_cursor ISSELECT employee_id, last_name, salaryFROM employeesWHERE department_id = 10;v_emp_id employees.employee_id%TYPE;v_name employees.last_name%TYPE;v_sal employees.salary%TYPE;
BEGIN-- 2. 打开游标OPEN emp_cursor;-- 3. 提取数据LOOPFETCH emp_cursor INTO v_emp_id, v_name, v_sal;EXIT WHEN emp_cursor%NOTFOUND;DBMS_OUTPUT.PUT_LINE(v_emp_id || ': ' || v_name || ', ' || v_sal);END LOOP;-- 4. 关闭游标CLOSE emp_cursor;
END;
/1、输出emp表工资前十名的员工姓名和薪资
declarecursor cur_1 isselect ename, salfrom (select ename, sal from emp order by sal desc)where rownum <= 10;v_n emp.ename%type;v_s emp.sal%type;
beginopen cur_1;loopfetch cur_1 into v_n, v_s;exit when cur_1%notfound;dbms_output.put_line('姓名:' || v_n || '薪资:' || v_s);end loop;close cur_1;
end;
/
-------------------
declarecursor cur_1 isselect ename, salfrom (select ename, sal from emp order by sal desc)where rownum <= 10;v_n emp.ename%type;v_s emp.sal%type;
beginopen cur_1;fetch cur_1 into v_n, v_s;while cur_1%found loopdbms_output.put_line('姓名:' || v_n || '薪资:' || v_s);fetch cur_1 into v_n, v_s;end loop;close cur_1;
end;
/
【二】带参数的显示游标
游标可以接受参数,使查询更加灵活:
1. 语法结构
CURSOR cursor_name (parameter1 datatype, parameter2 datatype, ...)IS select_statement;declarecursor cur_name(变量 类型) is select语句;---声明一个显示游标
begin open cur_name(变量);--打开游标fetch cur_name into 变量;