oracle游标的使用,oracle游标详解。在Oracle数据库开发中,有时需要对不同的数据行做不同的处理,游标提供了一种从表中检索数据并进行操作的灵活手段,游标主要用在服务器上,处理由客户端发送给服务器端的SQL语句,或是批处理、存储过程、触发器中的数据处理请求。游标的作用相当于指针,通过游标PL/SQL程序可以一次处理查询结果集中的一行,并可以对该行数据执行特定操作,从而为用户在处理数据的过程中提供了很大方便。
在Oracle中,通过游标操作数据主要使用显式游标和隐式游标,另外,还有具有引用类型的ref游标,下面将分别介绍。
1 显式游标
1.1 显式游标介绍
显式游标由用户自己定义和操作游标,通常所说的游标都是指显式游标。
游标的使用分成以下4个步骤:
1.1.1 声明游标
在DECLARE部分按以下格式声明游标:
CURSOR 游标名[(参数1 数据类型[,参数2 数据类型...])]
IS SELECT 语句;
参数是可选部分,所定义的参数可以出现在SELECT语句的WHERE子句中。如果定义了参数,则必须在打开游标时传递相应的实际参数。
1.1.2 打开游标
在可执行部分,按以下格式打开游标:
OPEN 游标名[(实际参数1[,实际参数2])];
打开游标时,SELECT语句的查询结果就被传送到了游标工作区。
1.1.3 提取数据
在可执行部分,按以下格式将游标工作区中的数据提取到变量中。提取操作必须在打开游标之后进行。
FETCH 游标名 INTO 变量名1[,变量名2...];
或
FETCH 游标名 INTO 记录变量;
游标打开后有一个指针指向数据区,FETCH语句一次返回指针所指的一样数据,要返回多行需重复执行,可以使用循环语句来实现。控制循环可以通过判断游标的属性来进行。
对以上两种格式进行说明:
第一种格式中的变量是用来从游标中接收数据的变量,需要事先定义。变量的个数与类型应与SELECT语句中的字段变量的个数与类型一致。
第二种格式一次将一行数据取到记录变量中,需使用%ROWTYPE事先定义记录变量,这种形式使用起来比较方便,不必分别定义和使用多个变量。(定义记录变量方法:变量名 表名|游标名%ROWTYPE)
1.1.4 关闭游标
CLOSE 游标名;
显示游标打开后,必须显示地关闭。游标一旦关闭,游标占用的资源就被释放,游标变成无效,必须重新打开才能使用。
1.2 显式游标属性
通过游标的属性可以获取SQL的执行结果以及游标的状态信息:
%found:布尔型,最近的FETCH语句返回一行数据则为真,否则为假;
%notfound:布尔型,与%found属性相反;
%rowcount:整数,获得FETCH语句返回的行数;
%isopen:布尔型,游标已经打开时值为真,否则为假;
1.3 显式游标举例
1)通过变量存储游标结果,将变量写在条件中,也可以参数的形式放在游标名称后面,即cursor cur_emp(pi_deptno in number)
declare v_deptno emp.deptno%type := 30; cursor cur_emp is select empno, ename, sal from emp where deptno = v_deptno; v_empno emp.empno%type; v_ename emp.ename%type; v_sal emp.sal%type;begin -- 为便于查看游标属性,将其打印出来,实际实用中不必打印 if cur_emp%isopen then dbms_output.put_line('游标已打开.....'); else dbms_output.put_line('游标未打开.....'); end if; open cur_emp; fetch cur_emp --游标一次取一行数据,若返回多行,需循环处理 into v_empno, v_ename, v_sal; dbms_output.put_line('工号:' || v_empno || ' 姓名:' || v_ename || ' 工资:' || v_sal); if cur_emp%found then dbms_output.put_line('还有数据行待处理....'); end if; close cur_emp;end;
2)通过record类型存储游标结果
declare v_deptno emp.deptno%type := 30; cursor cur_emp is select empno, ename, sal from emp where deptno = v_deptno; type typ_emp is record( empno emp.empno%type, ename emp.ename%type, sal emp.sal%type); v_emp typ_emp;begin if cur_emp%isopen then dbms_output.put_line('游标已打开.....'); else dbms_output.put_line('游标未打开.....'); end if; open cur_emp; fetch cur_emp --游标一次取一行数据,若返回多行,需循环处理 into v_emp; dbms_output.put_line('工号:' || v_emp.empno || ' 姓名:' || v_emp.ename || ' 工资:' || v_emp.sal); if cur_emp%found then dbms_output.put_line('还有数据行待处理....'); end if; close cur_emp;end;
3)通过%rowtype类型存储游标结果
declare v_deptno emp.deptno%type := 30; cursor cur_emp is select empno, ename, sal from emp where deptno = v_deptno; v_emp cur_emp%rowtype;begin if cur_emp%isopen then dbms_output.put_line('游标已打开.....'); else dbms_output.put_line('游标未打开.....'); end if; open cur_emp; fetch cur_emp --游标一次取一行数据,若返回多行,需循环处理 into v_emp; dbms_output.put_line('工号:' || v_emp.empno || ' 姓名:' || v_emp.ename || ' 工资:' || v_emp.sal); if cur_emp%found then dbms_output.put_line('还有数据行待处理....'); end if; close cur_emp;end;
4)由于逐行处理游标的获取的数据行,如果结果集比较大,由于语句的执行在SQL引擎和PL/SQL引擎上下文切换比较频繁,性能会很差,这时可考虑使用bulk collect批量处理结果集
declare cursor cur_emp is select empno, ename, sal from emp; type typ_emp is table of cur_emp%rowtype; v_emp typ_emp; begin open cur_emp; fetch cur_emp bulk collect into v_emp; dbms_output.put_line('获取的数据行数:' || v_emp.count); for r in v_emp.first .. v_emp.last loop dbms_output.put_line('工号:' || v_emp(r).empno || ' 姓名:' || v_emp(r).ename || ' 工资:' || v_emp(r).sal); end loop; close cur_emp; end;
5)当数据量很大的时候,将整个结果集作为一批进行处理,仍然会很耗时,这时就需要对结果集进行分段处理,比如每次处理50000条,可使用limit限制一次获取的数据行数
declare cursor cur_emp is select empno, ename, sal from emp; type typ_emp is table of cur_emp%rowtype; v_emp typ_emp;begin open cur_emp; loop fetch cur_emp bulk collect into v_emp limit 4; exit when v_emp.count = 0; dbms_output.put_line('获取的数据行数:' || v_emp.count); for r in v_emp.first .. v_emp.last loop dbms_output.put_line('工号:' || v_emp(r).empno || ' 姓名:' || v_emp(r) .ename || ' 工资:' || v_emp(r).sal); end loop; end loop; close cur_emp;end;
2 隐式游标
2.1 隐式游标介绍
在执行一个SQL语句时,Oracle会自动创建一个隐式游标,这个游标是内存中处理该语句的工作区域,隐式游标主要是DML语句的执行结果。
2.2 隐式游标属性
隐式游标和显示游标属性相似,只不过在其前面加上SQL:
sql%found:布尔型,值为TRUE代表插入、删除、更新或单行查询操作成功;
sql%notfound:布尔型,与sql%found属性相反;
sql%rowcount:整数,代表DML语句成功执行的行数;
sql%isopen:布尔型,DML执行过程中为真,结束后为假;
2.3 隐式游标举例
1)DML语句默认即隐式游标
declare v_deptno emp.deptno%type := 90; v_cnt number;begin update emp set sal = sal*1.2 where deptno = v_deptno; v_cnt := sql%rowcount; if v_cnt > 0 then dbms_output.put_line('更新成功....更新的记录数为:'||v_cnt); commit; else rollback; dbms_output.put_line('更新不成功....更新的记录数为:'||v_cnt); end if;end;
2)FOR ... LOOP循环语句也可是隐式游标
begin for rec in (select * from emp) loop dbms_output.put_line('工号:' || rec.empno || ' 姓名:' || rec.ename || ' 工资:' || rec.sal); end loop;end;
3 动态游标
3.1 动态游标介绍
定义游标类型语句:
TYPE 游标类型名 REF CURSOR;
声明游标变量语句:
游标变量名游标类型名;
在可执行部分可以如下形式打开一个动态游标:
OPEN 游标变量名 FOR 查询语句字符串;
3.2 示例
declare type cur is ref cursor; v_cur cur; type typ_emp is record( empno emp.empno%type, ename emp.ename%type, sal emp.sal%type); v_emp typ_emp; --v_sql varchar2(200) := 'select empno,ename,sal from emp';begin --open v_cur for v_sql; open v_cur for select empno, ename, sal from emp; loop fetch v_cur into v_emp; exit when v_cur%notfound; dbms_output.put_line('工号:' || v_emp.empno || ' 姓名:' || v_emp.ename || ' 工资:' || v_emp.sal); end loop; close v_cur;end;
以上,就是关于游标的简单介绍,希望可以帮到大家,谢谢。
本文地址:百科问答频道 https://www.neebe.cn/wenda/886373.html,易企推百科一个免费的知识分享平台,本站部分文章来网络分享,本着互联网分享的精神,如有涉及到您的权益,请联系我们删除,谢谢!