每个游标都有%ISOPEN、%FOUND、%NOTFOUND 和 %ROWCOUNT四个属性,用于测试游标的状态。本文为您介绍这些属性及示例。

%ISOPEN

%ISOPEN属性用于测试游标是否已打开。

cursor_name%ISOPEN

cursor_name是游标的名称,如果游标打开,将返回BOOLEAN数据类型TRUE,否则将返回FALSE

下面是使用%ISOPEN的示例。

CREATE OR REPLACE PROCEDURE cursor_example
IS
        ...
    CURSOR emp_cur_1 IS SELECT * FROM emp;
        ...
BEGIN
        ...
    IF emp_cur_1%ISOPEN THEN
        NULL;
    ELSE
        OPEN emp_cur_1;
    END IF;
    FETCH emp_cur_1 INTO ...
        ...
END;

%FOUND

%FOUND属性用于测试在对游标执行FETCH操作之后是否从指定游标的结果集中检索到行。

cursor_name%FOUND

cursor_name是游标的名称,如果在FETCH之后从游标的结果集中检索到行,则将返回BOOLEAN数据类型TRUE

在结果集的最后一行被FETCH之后,下一个FETCH将导致%FOUND返回 FALSE。如果结果集中没有行,则第一个FETCH之后也会返回FALSE

在游标打开之前或关闭游标之后对游标引用%FOUND会导致引发INVALID_CURSOR异常。

如果游标已打开,但在第一个FETCH之前引用%FOUND,它将返回null。

以下示例使用%FOUND

CREATE OR REPLACE PROCEDURE cursor_example
IS
    v_emp_rec       emp%ROWTYPE;
    CURSOR emp_cur_1 IS SELECT * FROM emp;
BEGIN
    OPEN emp_cur_1;
    DBMS_OUTPUT.PUT_LINE('EMPNO    ENAME');
    DBMS_OUTPUT.PUT_LINE('-----    -------');
    FETCH emp_cur_1 INTO v_emp_rec;
    WHILE emp_cur_1%FOUND LOOP
        DBMS_OUTPUT.PUT_LINE(v_emp_rec.empno || '     ' || v_emp_rec.ename);
        FETCH emp_cur_1 INTO v_emp_rec;
    END LOOP;
    CLOSE emp_cur_1;
END;

调用前面的存储过程时,输出显示如下:

EXEC cursor_example;

EMPNO    ENAME
-----    ------
7369     SMITH
7499     ALLEN
7521     WARD
7566     JONES
7654     MARTIN
7698     BLAKE
7782     CLARK
7788     SCOTT
7839     KING
7844     TURNER
7876     ADAMS
7900     JAMES
7902     FORD
7934     MILLER

%NOTFOUND

%NOTFOUND属性是%FOUND的逻辑对立面。

cursor_name%NOTFOUND

cursor_name是游标的名称,如果在FETCH之后从游标的结果集中检索到行,则将返回BOOLEAN 数据类型FALSE

在结果集的最后一行被FETCH之后,下一个FETCH将导致%NOTFOUND返回TRUE。如果结果集中没有行,则第一个FETCH之后也会返回TRUE

在游标打开之前或关闭游标之后对游标引用%NOTFOUND会导致引发INVALID_CURSOR异常。

如果游标已打开,但在第一个FETCH之前引用%NOTFOUND,它将返回null。

以下示例使用%NOTFOUND

CREATE OR REPLACE PROCEDURE cursor_example
IS
    v_emp_rec       emp%ROWTYPE;
    CURSOR emp_cur_1 IS SELECT * FROM emp;
BEGIN
    OPEN emp_cur_1;
    DBMS_OUTPUT.PUT_LINE('EMPNO    ENAME');
    DBMS_OUTPUT.PUT_LINE('-----    -------');
    LOOP
        FETCH emp_cur_1 INTO v_emp_rec;
        EXIT WHEN emp_cur_1%NOTFOUND;
        DBMS_OUTPUT.PUT_LINE(v_emp_rec.empno || '     ' || v_emp_rec.ename);
    END LOOP;
    CLOSE emp_cur_1;
END;

与前面的示例类似,此存储过程在调用时会生成相同的输出。

EXEC cursor_example;

EMPNO    ENAME
-----    ------
7369     SMITH
7499     ALLEN
7521     WARD
7566     JONES
7654     MARTIN
7698     BLAKE
7782     CLARK
7788     SCOTT
7839     KING
7844     TURNER
7876     ADAMS
7900     JAMES
7902     FORD
7934     MILLER

%ROWCOUNT

%ROWCOUNT属性返回一个整数,显示到目前为止通过FETCH从指定游标获取的行数。

cursor_name%ROWCOUNT

cursor_name是游标的名称,%ROWCOUNT对其返回到目前为止检索的行数。在检索到最后一行之后,%ROWCOUNT仍然设置为在游标关闭之前返回的总行数,此时如果引用%ROWCOUNT,它将引发 INVALID_CURSOR 异常。

在游标打开之前或关闭游标之后对游标引用%ROWCOUNT会导致引发INVALID_CURSOR异常。

如果游标已打开,但在第一个FETCH之前引用%ROWCOUNT,它将返回0。如果结果集中没有行,%ROWCOUNT也会在第一个FETCH后返回0。

以下示例使用%ROWCOUNT

CREATE OR REPLACE PROCEDURE cursor_example
IS
    v_emp_rec       emp%ROWTYPE;
    CURSOR emp_cur_1 IS SELECT * FROM emp;
BEGIN
    OPEN emp_cur_1;
    DBMS_OUTPUT.PUT_LINE('EMPNO    ENAME');
    DBMS_OUTPUT.PUT_LINE('-----    -------');
    LOOP
        FETCH emp_cur_1 INTO v_emp_rec;
        EXIT WHEN emp_cur_1%NOTFOUND;
        DBMS_OUTPUT.PUT_LINE(v_emp_rec.empno || '     ' || v_emp_rec.ename);
    END LOOP;
    DBMS_OUTPUT.PUT_LINE('**********************');
    DBMS_OUTPUT.PUT_LINE(emp_cur_1%ROWCOUNT || ' rows were retrieved');
    CLOSE emp_cur_1;
END;

此存储过程输出在员工列表末尾检索的总行数,如下所示:

EXEC cursor_example;

EMPNO    ENAME
-----    -------
7369     SMITH
7499     ALLEN
7521     WARD
7566     JONES
7654     MARTIN
7698     BLAKE
7782     CLARK
7788     SCOTT
7839     KING
7844     TURNER
7876     ADAMS
7900     JAMES
7902     FORD
7934     MILLER
**********************
14 rows were retrieved

游标状态和属性摘要

下表总结了可能的游标状态和游标属性返回的值。

游标状态 %ISOPEN %FOUND %NOTFOUND %ROWCOUNT
在OPEN之前 False INVALID_CURSOR异常 INVALID_CURSOR异常 INVALID_CURSOR异常
在OPEN之后,第一个FETCH之前 True Null Null 0
第一个成功的FETCH之后 True True False 1
第n个成功的FETCH之后(最后一行) True True False n
第n+1个FETCH之后(最后一行之后) True False True n
在CLOSE之后 False INVALID_CURSOR异常 INVALID_CURSOR异常 INVALID_CURSOR异常