Oracle游标概念及使用

游标的概念:
游标位于内存中的 "临时表"。 具体如下:游标是从数据表中提取出来的数据,以 临时表 的形式存放到 内存中,在游标中有一个 数据指针, 在初始状态下指向的是首记录,利用 fetch 语句可以移动该指针,从而对游标中的数据进行各种操作,然后将操作结果写回到数据库中。游标用来查询数据库,获取记录集合(结果集)的指针,可以让开发者 一次访问一行结果集, 在每条结果集上作操作。

一、语法及属性

1.隐式游标

在 PL/SQL 中使用 DML 和 select into时,会自动创建隐式游标,隐式游标自动声明、打开和关闭(无法手动查看),其名为 SQL,通过检查隐式游标的属性可以获得 最近执行的 DML 和 select into 语句的信息

数据准备
INTO stu(s_id, s_xm) VALUES (1, '小游子')
INTO stu(s_id, s_xm) VALUES (2, '小优子') 


总共 4 个步骤,缺一不可:(参数可选)
DECLARE
   CURSOR cur_stu(参数值 参数类型) IS SELECT * FROM stu t [WHERE t.id = 参数值]; -- 步骤1: 声明游标
   v_stu  cur_stu%ROWTYPE;
BEGIN
   OPEN cur_stu(参数值); -- 步骤2: 打开游标
   
   LOOP 
     FETCH cur_stu INTO v_stu; -- 步骤3: 提取数据
     EXIT WHEN cur_stu%NOTFOUND;
       dbms_output.put_line(v_stu.s_id ||' : '||v_stu.s_xm);
   END LOOP;
   
   CLOSE cur_stu; -- 步骤4: 关闭游标
   
EXCEPTION
   WHEN OTHERS THEN
      dbms_output.put_line(SQLCODE || ' : ' || SQLERRM);
      dbms_output.put_line(dbms_utility.format_error_backtrace);
END;

2.动态游标

DECLARE
   v_sql VARCHAR(2000);
   v_b1 NUMBER(3) := 3;
   v_id system.stu.s_id%TYPE;
   v_xm system.stu.s_xm%TYPE;
   -- TYPE cur_stu_type IS REF CURSOR;
   -- cur_stu cur_stu_type;
   cur_stu SYS_REFCURSOR;
BEGIN
   v_sql := 'SELECT t.s_id, t.s_xm FROM stu t WHERE t.s_id <= :b1';

   OPEN cur_stu FOR v_sql
      USING v_b1; -- 绑定变量 : 大数据处理常用优化手段

   LOOP
      FETCH cur_stu
         INTO v_id, v_xm;
      EXIT WHEN cur_stu%NOTFOUND;
      dbms_output.put_line('序号:' || v_id || chr(10) || '姓名:' || v_xm);
   END LOOP;
   
   CLOSE cur_stu;
EXCEPTION
   WHEN OTHERS THEN
      dbms_output.put_line(SQLCODE || ' : ' || SQLERRM);
      dbms_output.put_line(dbms_utility.format_error_backtrace);
END;

3.带参数的游标

declare  
isok integer;  
v_event_id number(10);  
v_isagain number(2);  
v_rate number(2);  
  
v_sender char(11) := '13800138000';  
  
cursor cursorVar(p_sender varchar2) is select event_id, isagain, rate from call_event where sender = p_sender; -- 声明游标  
  
begin  
    open cursorVar(v_sender);    -- 打开游标,在括号里传参。  
    loop  
         fetch cursorVar into v_event_id, v_isagain, v_rate;       -- 取值  
         exit when cursorVar%notfound;                             --当没有记录时退出循环  
         dbms_output.put_line(v_event_id || ', ' || v_isagain || ', ' || v_rate);  
    end loop;  
     
    close cursorVar;   -- 关闭游标  
end;

4.属性

属性 返回值类型 说明
SQL%ISOPEN 布尔型 游标是否开启, true:开启,false:关闭
SQL%FOUND 布尔型 前一个 fetch 语句是否有值,true:有,false:没有
SQL%NOTFOUND 布尔型 与上述相反,常被用于 退出循环,true:有,false:没有, null : 空。注意哦,只有 为 true 时,才退出(当 第一次 fetch 为 null 时,不会退出!)
SQL%ROWCOUNT 整型 当前成功执行的数据行数(非总记录数
DECLARE
   CURSOR cur_stu IS SELECT * FROM stu;
   v_stu cur_stu%ROWTYPE;
BEGIN

   OPEN cur_stu;

   LOOP
      FETCH cur_stu INTO v_stu;
      EXIT WHEN cur_stu%NOTFOUND; -- sql%notfound
      
      IF cur_stu%FOUND THEN -- sql%found
         dbms_output.put_line(v_stu.s_id || ' : ' || v_stu.s_xm);
         dbms_output.put_line('当前记录条数:' || cur_stu%ROWCOUNT); -- sql%rowcount
      ELSE 
         dbms_output.put_line('无记录...');
      END IF;
   END LOOP;

   CLOSE cur_stu; 

EXCEPTION
   WHEN OTHERS THEN
      IF cur_stu%ISOPEN THEN -- sql%isopen
         CLOSE cur_stu;
      END IF;
      
      dbms_output.put_line(SQLCODE || ' : ' || SQLERRM);
      dbms_output.put_line(dbms_utility.format_error_backtrace);
END;

二、特别说明 sql%notfound

1、fetch … into 语句有数据时,会覆盖 into 变量后的值
2、fetch … into 语句无数据时,into 变量的值不改变(为最后一次有数据的值),就像 select … into 如果没有数据会报异常,但是不会把 into 后面的变量置为空一样。

posted @ 2019-01-10 20:12  reaperhero  阅读(1191)  评论(0编辑  收藏  举报