1. 在PL/SQL程序中执行select、insert、update、delete语句的时候,oracle会在内存中为其分配上下文区(context area)。游标是指向该区的一个指针,或是命名一个工作区(work area),或是一种结构化数据类型。它为应用程序提供了一种对具有多行数据的查询结果集中每行进行单独处理的方法,是设计交互式程序的常用编程接口。
2. 游标分为显式游标和隐式游标。隐式游标是oracle为所有DML语句自动声明和操作的一种游标,显式游标是由用户声明和操作的一种游标。
3. 在每个会话中,可以同时打开多个游标,其数量是由数据库初始化参数文件中的open_cursors参数定义。
4. 显式游标的操作及其子过程
5. 使用显式游标必须首先声明游标,同时声明游标对应的select语句,游标可以带参数,也可以带返回值。声明游标的格式为:
声明游标之后,还可以基于游标用%rowtype定义记录变量,然后该记录变量就具有了select_statement中选择列表的列名和别名(如果有表达式列,一定要取别名)。这种方法可以简化游标的数据处理,减少出错。语法格式为:
Record_variable cursor_name%rowtype;
6. 对游标声明完成之后需要打开游标。打开游标后得到的结果集是静态的,所有对数据操作的sql语句对该结果集都没有影响,直到该游标关闭后再打开,这些影响才会在结果集中反映出来。语法格式为:
Open cursor_name[arg1 datatype,arg2 datatype,]。
7. 打开游标后,游标指向结果集的第一行。如果要提取结果集的数据,就需要提取游标。语法格式为:
Fetch cursor_name into {variable_list|record_variable}
Variable_list和record_variable分别为已经声明的变量列表和记录变量。使用variable_list时,fetch语句将一个数据行的各列值分别赋予不同的变量。使用record_variable时,fetch语句将结果集中的一个数据行的各列值赋予记录变量中的不同元素。
Fetch语句执行时,每次返回一个数据行,然后将游标指针移动到下一个数据行。当检索到最后一个数据行的时候,如果再一次是fetch语句,则操作失败,同时将游标属性%notfound的值置为true。所以每次执行完成游标fetch语句后,只要检查游标属性%notfound的属性是否是true就可以判断fetch语句是否执行成功,一遍确定是否给变量赋了值。
8. 关闭游标
当提取和处理完成游标之后,应该及时关闭游标,以便于释放它所占用的资源。语法格式为:
Close cursor_name;
游标关闭之后,可以再次打开,但是当游标关闭之后,对它执行打开以外的操作,则会产生错误invalid_cursor异常错误。
9. 举例说明游标的使用方法。
先声明4个游标:c1没有参数,c2有参数,c3有参数并且有返回值类型,c4有参数;然后打开游标;用loop循环提取游标,并处理结果集;关闭游标,并显示游标参数的传递方法和基于游标定义记录变量的方法。
测试该游标的基本表如下
Select * from dept;
对4个游标进行测试的语句为:
declare
type DeptRecord is record(
deptno dept.deptno%type,
dname dept.dname%type,
loc dept.loc%type);
v_DeptRecord DeptRecord;
v_dept_name dept.dname%type;
v_dept_loc dept.loc%type;
cursor c1 --声明游标
is
select dname,loc from dept where deptno <= 10;
cursor c2(v_dept_no number) --有参数的游标
is
select dname,loc from dept where deptno <= v_dept_no;
cursor c3(v_dept_no number) --有返回数据类型游标
return DeptRecord
is
select deptno,dname,loc from dept where deptno < v_dept_no;
cursor c4(v_dept_no number)
is
select deptno,dname,loc from dept where deptno < v_dept_no;
v_dept_rec c4%rowtype;
begin
open c1;
loop
fetch c1 into v_dept_name,v_dept_loc; --提取游标
if c1%found then
dbms_output.put_line('c1'||v_dept_name||' '||v_dept_loc);
else
dbms_output.put_line('c1'||'已经处理完结果集了!');
exit;
end if;
end loop;
open c2(20);
loop
fetch c2 into v_dept_name,v_dept_loc; --提取游标
exit when c2%notfound;
dbms_output.put_line('c2'||v_dept_name||' '||v_dept_loc);
end loop;
open c3(v_dept_no => 30);
loop
fetch c3 into v_deptrecord;
exit when c3%notfound;
dbms_output.put_line('c3'||v_deptrecord.deptno||' '||v_deptrecord.dname);
end loop;
open c4(40);
loop
fetch c4 into v_dept_rec;
exit when c4%notfound;
dbms_output.put_line('c4'||v_dept_rec.deptno||' '||v_dept_rec.dname);
end loop;
close c1;
close c2;
close c3;
close c4;
end;
游标测试的结果为:
10. 显示游标属性,包括:isopen,found,notfound,rowcount
11. 隐式游标属性,oracle为每一个不属于显示游标的DML语句都创建一个隐式游标。隐式游标的名称是SQL。不能对隐式SQL游标显式的执行open、fetch、close语句。
12. 为了简化游标操作,PL/SQL语言提供了游标for循环语句。一个游标for循环可以隐含的实现open、fetch、close游标以及循环处理结果集的功能。其步骤是:当进入循环时,自动打开一个已经声明的游标,并提取第一行游标数据。并且能够按照for循环对查询结果集按行进行处理;当处理完成所有行之后,会自动结束循环并关闭游标。当在游标for循环中调用exit语句和goto语句,或者由于发生异常错误等原因而导致程序跳出循环时,PL/SQL均能够自动关闭游标。语法格式为:
举例说明使用方法:
13. 使用显式游标更新或删除当前游标行的数据,要求游标查询语句中必须有for update选项。语法格式为:
首先使用for update选项打开游标,然后在update和delete语句中where子句更新当前结果集中的游标行对应数据库数据表行。
举例说明: