ITPub博客

首页 > 数据库 > Oracle > oracle 游标使用

oracle 游标使用

原创 Oracle 作者:powerinf 时间:2013-12-27 16:29:25 0 删除 编辑

游标:
     用来查询数据库,获取记录集合(结果集)的指针,我们所说的游标通常是指显式游标,因此从现在起没有特别指明的情况,我们所说的游标都是指显式游标。
     要在程序中使用游标,必须首先声明游标分类:
            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/ ,如需转载,请注明出处,否则将追究法律责任。

上一篇: 没有了~
下一篇: 没有了~
请登录后发表评论 登录
全部评论

注册时间:2013-12-27

  • 博文量
    1
  • 访问量
    5579