第十章 使用游标

例一:

DECLARE

         emprow  emp%ROWTYPE;

         CURSOR  emp_cur

IS

       SELECT *

           FROM  emp

        WHERE  deptno IS NOT NULL;

BEGIN

       OPEN  emp_cur;

       LOOP

             FETCH  emp_cur

                 INTO  emprow;

        DBMS_OUTPUT.put_line(

           

          )

        EXIT  WHEN  emp_cur%NOTFOUND;

END LOOP;

CLOSE  emp_cur;

END;


在oracle中,INSERT ,UPDATE , DELETE 和 SELECT INTO 语句在被执行时,都会隐含地创建游标,通过范围游标的四大属性%FOUND,%ISOPEN,%NOTFOUND和%ROWCOUNT来访问游标的相关属性。

DECLARE

     v_deptno   NUMBER;

     CURSOR  emp_cursor

IS

    SELECT *

       FROM  emp

  WHERE  deptno = v_deptno;

BEGIN

     v_deptno := 20;

OPEN  emp_cursor;

IF  emp_cursor %ISOPEN  THEN

        DBMS_OUTPUT.PUT_LINE('游标已经被打开');

END IF;

END ;

定义游标时,为游标指定参数,可以使用RETURN子句定义游标返回值的类型,返回值的类型一定要和返回结果集的数据类型一致,因此返回值一般为记录类型或%ROWTYPE指定的表中的类型。

DECLARE

         ----声明游标并指定游标返回值类型

    CURSOR  emp_cursor ( p_deptno IN NUMBER)  RETURN   emp%ROWTYPE

    IS

      SELECT *

          FROM emp

     WHERE  deptno = p_deptno;

BEGIN

        OPEN  emp_cursor(20);

END;

10.1.5使用游标属性

DECLARE

      CURSOR  emp_cursor(p_deptno  IN NUMBER)

      IS

          SELECT  *

              FROM  emp

         WHERE  deptno = p_deptno;

BEGIN

      IF NOT  emp_cursor%ISOPEN THEN

             OPEN emp_cursor(20);

      END IF;

     IF emp_cursor%ISOPEN  THEN

           DBMS_OUTPUT.PUT_LINE('游标已经打开');

     ELSE

           DBMS_OUTPUT.PUT_LINE('游标还没有被打开');

     END IF;

     CLOSE   emp_cursor;

END;

2.%FOUND属性

当游标被打开后,在调用FETCH语句获取数据之前,%FOUND会产生NULL值,而此后每取得一行数据,其值会为TRUE,如果最后一次取得数据失败,其值会变为False.因此%FOUND的作用是检查是否从结果集中提取到了数据。

DECLARE
    emp_row   emp%ROWTYPE;--定义游标值存储变量
    CURSOR  emp_cursor(p_deptno IN NUMBER)--定义游标并制定游标参数
    IS
        SELECT *
          FROM emp
         WHERE deptno = p_deptno
BEGIN
    IF NOT emp_cursor%ISOPEN
    THEN
        OPEN emp_cursor(20);
    END IF;
    IF emp_cursor%FOUND IS NULL
    THEN
        DBMS_OUTPUT.put_line('%FOUND属性为NULL');
    END IF;
    LOOP                                            --循环提取游标数据
        FETCH emp_cursor
         INTO emp_row;
         EXIT WHEN NOT emp_cursor%FOUND;
    END LOOP;
    CLOSE emp_cursor;
END;

4.%ROWCOUNT属性

当游标被打开时,%ROWCOUNT值为0,每取得一条数据,%ROWCOUNT的值就加1.

10.1.6提取游标数据

FETCH语句,可以一次一行地提取游标数据,也可以使用BULK  COLLECT子句一次性接受所有的游标数据到一个数组或者一个PL/SQL表中。

FECTH  cursor_name INTO  variable_name(s) | PL/SQL_record;

DECLARE
    deptno dept.deptno%TYPE;
    dname  dept.dname%TYPE;
    loc       dept.dname%TYPE;
    dept_row dept%ROWTYPE;
    CURSOR dept_cur IS SELECT * FROM dept;
BEGIN
    OPEN dept_cur;
    LOOP
      IF dept_cur%ROWCOUNT <= 4 THEN
          FETCH    dept_cur  INTO dept_row;
          IF dept_cur%FOUND THEN
              DBMS_OUTPUT.PUT_LINE(dept_row.deptno||' '||dept_now.dname||''||dept_row.loc);
          END IF;    
      ELSE
        FETCH dept_cur INTO deptno,dname,loc;
        IF dept_cur%FOUND THEN
            DBMS_OUTPUT.PUT_LINE(deptno||''||dname||' '||loc);
        END IF;
     END IF;
     EXIT WHEN dept_cur%NOTFOUND;
END LOOP;
CLOSE dept_cur;
END;

10.1.7批量提取游标数据

由于FETCH语句一次只从结果集中提取一行,并且提取只能是向前的,因此如果要重新提取已经提取过的数据,只有重新打开游标。

使用BULK COLLECT 批处理子句可以一次性将游标中的结果集保存到集合中,这样就可以在集合中进行前进和后退处理。下面的示例演示了如何使用BULK COLLECT语句一次性获取游标数据。

DECLARE

     TYPE  depttab_type IS TABLE OF dept%ROWTYPE;
     depttab depttab_type;
     CURSOR deptcur IS SELECT * FROM dept;
BEGIN
    OPEN deptcur;
    FETCH deptcur BULK COLLECT INTO depttab;
    ---使用BULK COLLECT INTO子句批次插入
    CLOSE deptcur;--关闭游标
    FOR i IN 1 .. depttab.count
    LOOP
    DBMS_OUTPUT.PUT_LINE( depttab(i).deptno
                          || ‘ ’
                          ||  depttab(i).dname
                          || ''
                          || depttab(i).loc
    )
    END LOOP
    CLOSE deptcur;

END;

BULK COLLECT INTO 语句会一次性将所有的数据都提取到集合中,如果数据量特别大,并且在使用VARRAY这样的具有固定元素个数的集合时,可能需要限制每次提取的行数,可以使用FETCH COLLECT INTO LIMIT语句提取部分数据:

DECLARE
    TYPE dept_type IS VARRAY(4) OF dept%ROWTYPE;
    depttab dept_type
    CURSOR dept_cursor
    IS
        SELECT *
          FROM dept;
    v_rows   INT := 4;
    v_count  INT := 0;
BEGIN
    OPEN dept_cursor;
    LOOP
        --每次提取4行数据到变长数组中
        FETCH  dept_cursor BULK COLLECT INTO depttab LIMIT v_rows;
        EXIT WHEN dept_cursor%NOTFOUND;
        DBMS_OUTPUT.put('部门名称');
        --循环提取变长数组数据,因为变长数组只能存放4个元素,因此不能越界读取
        FOR i IN 1 .. (dept_cursor%ROWCOUNT - v_count)
        LOOP
            DBMS_OUTPUT.PUT(deptabl(i).dname||'');
        END LOOP;
        DBMS_OUTPUT.NEW_LINE;    --输出新行
        v_count := dept_cursor%ROWCOUNT;--为v_count赋新的值
    END LOOP
    CLOSE dept_cursor;
END;

在代码中,通过使用BULK COLLECT INTO depttab LIMIT v_rows 一次性提取游标中的4挑记录到变长数组中,然后开始循环变长数组。由于变长数组的元素个数相对固定,因此使用v_count来减少游标个数进行提取。在代码中使用DBMS_PUT和DBMS_NEW_LINE进行断行处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值