首页 > 数据库 > Oracle > oracle 游标使用
游标:
用来查询数据库,获取记录集合(结果集)的指针,我们所说的游标通常是指显式游标,因此从现在起没有特别指明的情况,我们所说的游标都是指显式游标。
要在程序中使用游标,必须首先声明游标分类:
1、静态游标:显式游标和隐式游标。
2、REF游标:是一种引用类型,类似于指针。
其中,ref游标和普通游标(自定义游标)最大的区别是游标的结果集在什么地获取,普通游标在声明的时候,获得结果集,例子 cursor v_cur is select * from t_test;而ref游标在打开的时候,获得结果集
一、隐式游标:
1.定义
隐式游标则由则由系统自动定义,非显示定义游标的DML语句即被赋予隐式游标属性。其过程由oracle控制,完全自动化。隐式游标
的名称是SQL,不能对SQL游标显式地执行OPEN,FETCH,CLOSE语句。
2.属性
类似于显示游标,隐式游标同样具有四种属性,只不过隐式游标以SQL%开头,而显示游标以Cursor_name%开头
通过SQL%总是只能访问前一个DML操作或单行SELECT操作的游标属性,用于判断DML执行的状态和结果,进而控制程序的流程
SQL%ISOPEN
游标是否打开。当执行select into ,insert update,delete时,Oracle会隐含地打开游标,且在该语句执行完毕或隐含地关闭
游标,因为是隐式游标,故SQL%ISOPEN总是false
SQL%FOUND
判断SQL语句是否成功执行。当有作用行时则成功执行为true,否则为false。
SQL%NOTFOUND
判断SQL语句是否成功执行。当有作用行时否其值为false,否则其值为true。
SQL%ROWCOUNT
在执行任何DML语句之前,SQL%ROWCOUNT的值都是NULL,对于SELECT INTO语句,如果执行成功,SQL%ROWCOUNT的值为,如果没有
成功,SQL%ROWCOUNT的值为,同时产生一个异常NO_DATA_FOUND。
列如:
for v_aa in aaa_cursor loop
end loop;
这样就完成了一次隐式游标的调用,可以看到此种方式类似于高级语言的for循环。
二、显示游标
用户自定义游标,专门用于处理select语句返回的多行数据
-- 声明游标;CURSOR cursor_name IS select_statement
-- 语法:
CURSOR cursor_name [ ( [parameter [,parameter...] ) ] [RETURN return_specification]
IS
SELECT_statement
显示游标的过程描述:
1.声明游标
CURSOR cursor_name IS select_statement
如:CURSOR emp_cur IS SELECT empno,ename,job,sal FROM scott.emp;
2.打开游标
OPEN cursor_name --打开游标则执行对应的select语句,将对应的结果集存放到游标当中
如:OPEN emp_cur
3.读取数据
FETCH cursor_name INTO var_name1,...var_name2 ; --提取单行数据,需要配合循环语句来使用
FETCH cursor_name BULK COLLECT INTO collect1,collect2,...[LIMIT rows]; --提取多行数据,collect为集合变量
4.关闭游标
CLOSE cursor_name
5.显示游标的个属性
cursor_name%ISOPEN 游标是否打开
cursor_name%FOUND 最近的FETCH是否提取到数据
cursor_name%NOTFOUND 最近的FETCH是否没有提取到数据
cursor_name%ROWCOUNT 返回到目前为止,已经从游标缓冲区中提取到数据的行数
然而在某些情况下显式游标使用起来会更加灵活。在隐式游标的for语句调用中,类似for语句,在取不到下条记录的情况下,不会进入循环体而会直接退出。这在某些情况下会造成一些不便,比如在无更多数据时应对最后一组数据进行处理再退出。此时显式游标以aaa_cursor%notfound条件判定再退出的形式就会有用的多,可以在循环体内根据aaa_curso r%notfound的条件手动控制退出的时机,进行最后一次处理。
案例
显示游标案例
1、For 循环游标
(1)定义游标
(2)定义游标变量
(3)使用for循环来使用这个游标
declare
--类型定义
cursor c_test
is
select user_code,user_name,user_password
from sm_user
where user_code='qinhao';
--定义一个游标变量c_test_row c_test%ROWTYPE ,该类型为游标c_test中的一行数据类型
c_test_row c_test%rowtype;
begin
for c_test_row in c_test loop
dbms_output.put_line(c_test_row.user_code||'-'||c_test_row.user_name||'-'||c_test_row.user_password);
end loop;
end;
--运行结果
SQL> declare
2 --类型定义
3 cursor c_test
4 is
5 select user_code,user_name,user_password
6 from sm_user
7 where user_code='qinhao';
8 --定义一个游标变量c_test_row c_test%ROWTYPE ,该类型为游标c_test中的一行数据类型
9 c_test_row c_test%rowtype;
10 begin
11 for c_test_row in c_test loop
12 dbms_output.put_line(c_test_row.user_code||'-'||c_test_row.user_name||'-'||c_test_row.user_password);
13 end loop;
14 end;
15 /
qinhao-秦豪-hnmflgjihljmobge
PL/SQL procedure successfully completed
--Fetch游标
--使用的时候必须要明确的打开和关闭
declare
--类型定义
cursor c_test
is
select user_code,user_name,user_password
from sm_user
where user_code='limin';
--定义一个游标变量c_test_row c_test%ROWTYPE ,该类型为游标c_test中的一行数据类型
c_test_row c_test%rowtype;
begin
open c_test;
loop
--提取一行数据到c_test_row
fetch c_test into c_test_row;
--判读是否提取到值,没取到值就退出
--取到值c_test%notfound 是false
--取不到值c_test%notfound 是true
exit when c_test%notfound;
dbms_output.put_line(c_test_row.user_code||'-'||c_test_row.user_name||'-'||c_test_row.user_password);
end loop;
--关闭游标
close c_test;
end;
--运行结果
SQL> declare
2 --类型定义
3 cursor c_test
4 is
5 select user_code,user_name,user_password
6 from sm_user
7 where user_code='limin';
8 --定义一个游标变量c_test_row c_test%ROWTYPE ,该类型为游标c_test中的一行数据类型
9 c_test_row c_test%rowtype;
10 begin
11 open c_test;
12 loop
13 --提取一行数据到c_test_row
14 fetch c_test into c_test_row;
15 --判读是否提取到值,没取到值就退出
16 --取到值c_test%notfound 是false
17 --取不到值c_test%notfound 是true
18 exit when c_test%notfound;
19 dbms_output.put_line(c_test_row.user_code||'-'||c_test_row.user_name||'-'||c_test_row.user_password);
20 end loop;
21 --关闭游标
22 close c_test;
23 end;
24 /
limin-李敏-lodepcfhagbgaemb
PL/SQL procedure successfully completed
隐式游标案例
任意执行一个update操作,用隐式游标sql的属性%found,%notfound,%rowcount,%isopen观察update语句的执行情况。
begin
update zjl set USER_NAME='ALEARK' WHERE USER_CODE='qinhao';
if sql%isopen then
dbms_output.put_line('Openging');
else
dbms_output.put_line('closing');
end if;
if sql%found then
dbms_output.put_line('游标指向了有效行');--判断游标是否指向有效行
else
dbms_output.put_line('Sorry');
end if;
if sql%notfound then
dbms_output.put_line('Also Sorry');
else
dbms_output.put_line('Haha');
end if;
dbms_output.put_line(sql%rowcount);
exception
when no_data_found then
dbms_output.put_line('Sorry No data');
when too_many_rows then
dbms_output.put_line('Too Many rows');
end;
(整理自网络,并亲自实验记录)
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/28918446/viewspace-1065047/ ,如需转载,请注明出处,否则将追究法律责任。