zoukankan      html  css  js  c++  java
  • oracle中REF Cursor用法

    1,什么是 REF游标 ?
     动态关联结果集的临时对象。即在运行的时候动态决定执行查询。
     
    2,REF 游标 有什么作用?
     实现在程序间传递结果集的功能,利用REF CURSOR也可以实现BULK SQL,从而提高SQL性能。

    3,静态游标和REF 游标的区别是什么?
     ①静态游标是静态定义,REF 游标是动态关联;
     ②使用REF 游标需REF 游标变量。
     ③REF 游标能做为参数进行传递,而静态游标是不可能的。
     
    4,什么是REF 游标变量?
     REF游标变量是一种 引用 REF游标类型  的变量,指向动态关联的结果集。

    5,怎么使用  REF游标 ?
     ①声明REF 游标类型,确定REF 游标类型;
      ⑴强类型REF游标:指定retrun type,REF 游标变量的类型必须和return type一致。
       语法:Type   REF游标名   IS   Ref Cursor Return  结果集返回记录类型;
      ⑵弱类型REF游标:不指定return type,能和任何类型的CURSOR变量匹配,用于获取任何结果集。
       语法:Type   REF游标名   IS   Ref Cursor;

     ②声明Ref 游标类型变量;
      语法:变量名  已声明Ref 游标类型;
      
     ③打开REF游标,关联结果集 ;
      语法:Open   Ref 游标类型变量   For   查询语句返回结果集;
      
     ④获取记录,操作记录;
      语法:Fatch    REF游标名 InTo   临时记录类型变量或属性类型变量列表;
      
     ⑤关闭游标,完全释放资源;
      语法:Close   REF游标名;
     
     例子:强类型REF游标

     代码如下 复制代码
     /*conn scott/tiger*/
     Declare 
      Type MyRefCurA IS  REF CURSOR RETURN emp%RowType;
      Type MyRefCurB IS  REF CURSOR RETURN emp.ename%Type;
      vRefCurA  MyRefCurA;
      vRefCurB  MyRefCurB;
      vTempA  vRefCurA%RowType;
      vTempB  vRefCurB.ename%Type;
      
     Begin
      Open  vRefCurA  For Select  *  from   emp   Where  SAL > 2000;
      Loop
       Fatch  vRefCurA InTo  vTempA;
       Exit  When  vRefCurA%NotFound;
       DBMS_OUTPUT.PUT_LINE(vRefCurA%RowCount||'  '|| vTempA.eno||'  '||vTempA.ename ||'  '||vTempA.sal)
      End Loop;
      Close vRefCurA;
      
      DBMS_OUTPUT.PUT_LINE('-------------------------------------------------------------------------------------------------------');
      
      Open  vRefCurB  For Select  ename  from   emp   Where  SAL > 2000;
      Loop
       Fatch  vRefCurB InTo  vTempB;
       Exit  When  vRefCurB%NotFound;
       DBMS_OUTPUT.PUT_LINE(vRefCurB%RowCount||'  '||vTempB)
      End Loop;
      Close vRefCurB; 
      
      DBMS_OUTPUT.PUT_LINE('-------------------------------------------------------------------------------------------------------');   
      
      Open  vRefCurA  For Select  *  from   emp   Where  JOB = 'CLERK';
      Loop
       Fatch  vRefCurA InTo  vTempA;
       Exit  When  vRefCurA%NotFound;
       DBMS_OUTPUT.PUT_LINE(vRefCurA%RowCount||'  '|| vTempA.eno||'  '||vTempA.ename ||'  '||vTempA.sal)
      End Loop;
      Close vRefCurA;
     End;
     


     例子:弱类型REF游标
     

     代码如下 复制代码

    /*conn scott/tiger*/
     Declare
      Type MyRefCur  IS  Ref  Cursor;
      vRefCur MyRefCur;
      vtemp  vRefCur%RowType;
     Begin
      Case(&n)
       When  1 Then Open vRefCur  For Select   *   from emp;
       When  2 Then Open vRefCur  For Select   *   from dept;
       Else 
        Open vRefCur  For Select   eno,  ename  from emp Where JOB = 'CLERK';
      End Case;
      Close  vRefCur;
     End;

    6,怎样让REF游标作为参数传递?

     代码如下 复制代码

    --作为函数返回值
    create or replace function returnacursor return sys_refcursor 
    is
       v_csr sys_refcursor;
    begin
        open v_csr for select a1 from test3;
        return v_csr;
    end;
    /

    declare
    c sys_refcursor;
    a1 char(2);
    begin
      c:=returnacursor;
      loop
        fetch c into a1;
        exit when c%notfound;
        dbms_output.put_line(a1);
      end loop;
      close c;
    end;
    /

    --作为参数
    create or replace procedure proc_ref_cursor (rc in sys_refcursor) as
      v_a number;
      v_b varchar2(10);
      
    begin
      loop
        fetch rc into v_a, v_b;
        exit when rc%notfound;
        dbms_output.put_line(v_a || ' ' || v_b);
      end loop;
    end;
    /

    declare
    v_rc sys_refcursor;
    begin
      open v_rc for 
      select a1,a2 from test3;
      proc_ref_cursor(v_rc);
      close v_rc;
    end;
    /


    REF CURSOR 示例包括下列三个 Visual Basic 示例,演示如何使用 REF CURSOR。

    示例  说明  
    在 OracleDataReader 中检索 REF CURSOR 参数
     此示例执行一个 PL/SQL 存储过程,返回 REF CURSOR 参数,并将值作为 OracleDataReader 读取。
     
    使用 OracleDataReader 从多个 REF CURSOR 检索数据
     此示例执行一个 PL/SQL 存储过程,返回两个 REF CURSOR 参数,并使用 OracleDataReader 读取值。
     
    使用一个或多个 REF CURSOR 填充 DataSet
     此示例执行一个 PL/SQL 存储过程,返回两个 REF CURSOR 参数,并使用返回的行填充 DataSet。
     

    要使用这些示例,可能需要创建 Oracle 表,并且必须创建 PL/SQL 包和包正文。

    创建 Oracle 表
    这些示例使用 Oracle Scott/Tiger 架构中定义的表。大多数 Oracle 安装均包括 Oracle Scott/Tiger 架构。如果此架构不存在,可以使用 {OracleHome}rdbmsadminscott.sql 中的 SQL 命令文件创建供这些示例使用的表和索引。

    创建 Oracle 包和包正文
    这些示例要求服务器上存在以下 PL/SQL 包和包正文。在 Oracle 服务器上创建以下 Oracle 包

     代码如下 复制代码

    CREATE OR REPLACE PACKAGE BODY CURSPKG AS
        PROCEDURE OPEN_ONE_CURSOR (N_EMPNO IN NUMBER,
                                   IO_CURSOR IN OUT T_CURSOR)
        IS 
            V_CURSOR T_CURSOR; 
        BEGIN 
            IF N_EMPNO <> 0 
            THEN
                 OPEN V_CURSOR FOR 
                 SELECT EMP.EMPNO, EMP.ENAME, DEPT.DEPTNO, DEPT.DNAME 
                      FROM EMP, DEPT 
                      WHERE EMP.DEPTNO = DEPT.DEPTNO 
                      AND EMP.EMPNO = N_EMPNO;

            ELSE 
                 OPEN V_CURSOR FOR 
                 SELECT EMP.EMPNO, EMP.ENAME, DEPT.DEPTNO, DEPT.DNAME 
                      FROM EMP, DEPT 
                      WHERE EMP.DEPTNO = DEPT.DEPTNO;

            END IF;
            IO_CURSOR := V_CURSOR; 
        END OPEN_ONE_CURSOR;

        PROCEDURE OPEN_TWO_CURSORS (EMPCURSOR OUT T_CURSOR,
                                    DEPTCURSOR OUT T_CURSOR)
        IS 
            V_CURSOR1 T_CURSOR; 
            V_CURSOR2 T_CURSOR; 
        BEGIN 
            OPEN V_CURSOR1 FOR SELECT * FROM EMP;
            OPEN V_CURSOR2 FOR SELECT * FROM DEPT;
            EMPCURSOR  := V_CURSOR1; 
            DEPTCURSOR := V_CURSOR2; 
        END OPEN_TWO_CURSORS; 
    END CURSPKG;
    /


     

    Oracle提供REF CURSOR,通过该功能可以实现在程序间传递结果集的功能,利用REF CURSOR也可以实现BULK SQL,从而提高SQL性能。

    使用scott用户的emp表实现以下测试案例:

     代码如下 复制代码

    SQL> desc emp
    Name Null? Type
    ----------------------------------------- -------- ----------------------------
    EMPNO NOT NULL NUMBER(4)
    ENAME VARCHAR2(10)
    JOB VARCHAR2(9)
    MGR NUMBER(4)
    HIREDATE DATE
    SAL NUMBER(7,2)
    COMM NUMBER(7,2)
    DEPTNO NUMBER(2)

    使用ref cursor获得结果集输出:


    SQL> set serveroutput on
    SQL> DECLARE
    2 TYPE mytable IS TABLE OF emp%ROWTYPE;
    3 l_data mytable;
    4 l_refc sys_refcursor;
    5 BEGIN
    6 OPEN l_refc FOR
    7 SELECT empno, ename, job, mgr, hiredate, sal, comm, deptno FROM emp;

    9 FETCH l_refc BULK COLLECT INTO l_data;
    10 
    11 CLOSE l_refc;
    12 
    13 FOR i IN 1 .. l_data.COUNT
    14 LOOP
    15 DBMS_OUTPUT.put_line ( l_data (i).ename
    16 || ' was hired since '
    17 || l_data (i).hiredate
    18 );
    19 END LOOP;
    20 END;
    21 /
    SMITH was hired since 17-DEC-80
    ALLEN was hired since 20-FEB-81
    WARD was hired since 22-FEB-81
    JONES was hired since 02-APR-81
    MARTIN was hired since 28-SEP-81
    BLAKE was hired since 01-MAY-81
    CLARK was hired since 09-JUN-81
    SCOTT was hired since 19-APR-87
    KING was hired since 17-NOV-81
    TURNER was hired since 08-SEP-81
    ADAMS was hired since 23-MAY-87
    JAMES was hired since 03-DEC-81
    FORD was hired since 03-DEC-81
    MILLER was hired since 23-JAN-82

    PL/SQL procedure successfully completed.

  • 相关阅读:
    HDU 5585 Numbers
    HDU 3308 LCIS
    POJ 2991 Crane
    POJ 1436 Horizontally Visible Segments
    POJ 3667 Hotel
    HaiHongOJ 1003 God Wang
    【SDOI 2008】 递归数列
    5月19日省中提高组题解
    【HDU 1588】 Gauss Fibonacci
    【POJ 3233】Matrix Power Series
  • 原文地址:https://www.cnblogs.com/min-yu/p/11138320.html
Copyright © 2011-2022 走看看