8.2.6 显式游标的属性

利用游标属性可以得到游标执行的相关信息。显式游标有以下4个属性:

❑%ISOPEN:用于判断游标是否打开,如果已经打开则返回TRUE,如果游标未打开则返回FALSE。

❑%FOUND:此属性可用来检测行数据是否有效。如果有效该属性返回TRUE,否则返回FALSE。

❑%NOTFOUND:与%FOUND属性恰好相反,如果没有提取出数据则返回TRUE,否则返回FALSE。

❑%ROWCOUNT:累计到当前为止使用FETCH提取数据的行数。

下面利用几个示例来了解以上4个属性的具体使用方法。

1)要想获取游标的数据,首要一点就是游标是打开的,如果在游标关闭状态下操作数据则会出现错误。如果在游标未打开时使用FETCH语句会提示错误。

【示例6】%ISOPEN的使用

具体使用方法如下:


01 DECLARE

02 CURSOR pdct_isopen_cur

03 IS SELECT*FROM PRODUCTINFO;

04

05 cur_prodrcd productinfo%ROWTYPE;

06

07 BEGIN

08 IF pdct_isopen_cur%ISOPEN THEN

09 FETCH pdct_isopen_cur INTO cur_prodrcd;

10 DBMS_OUTPUT.PUT_LINE('产品ID:'||cur_prodrcd.productid

11 ||'产品名称:'||cur_prodrcd.productname

12 ||'产品价格:'||cur_prodrcd.productprice);

13

14 ELSE

15 DBMS_OUTPUT.PUT_LINE('游标pdct_isopen_cur没有打开');

16 END IF;

17 END;


【代码解析】

❑第8、14行利用游标属性%ISOPEN判断如果游标已经打开,则执行THEN后面的语句,否则执行ELSE后面的语句。

❑第16行是IF语句的结束标志。

【执行效果】

脚本执行效果如下:


游标pdct_isopen_cur没有打开


由执行效果可以看出脚本走的是ELSE这个流程,说明此属性判断游标是否打开没有问题。

2)在FETCH提取数据的时候,通常开发者都会判断行数据的有效性,这样可以避免脚本出现技术性的错误。

【示例7】%FOUND的使用

具体使用方法如下:


01 DECLARE

02 CURSOR pdct_found_cur

03 IS SELECT*FROM PRODUCTINFO;

04

05 cur_prodrcd productinfo%ROWTYPE;

06

07 BEGIN

08 OPEN pdct_found_cur;

09 LOOP

10 FETCH pdct_found_cur INTO cur_prodrcd;

11 IF pdct_found_cur%FOUND THEN

12 DBMS_OUTPUT.PUT_LINE('产品ID:'||cur_prodrcd.productid

13 ||'产品名称:'||cur_prodrcd.productname

14 ||'产品价格:'||cur_prodrcd.productprice);

15 ELSE

16 DBMS_OUTPUT.PUT_LINE('没有数据被提取');

17 EXIT;

18 END IF;

19 END LOOP;

20 CLOSE pdct_found_cur;

21 END;


【代码解析】

❑整个脚本在提取数据时做了判断,如果数据存在则输出,否则提示“没有数据被提取”然后退出。

❑第19行表示遍历结果集。

❑第11行用到%FOUND属性,表示如果该游标的指向有效则执行第12~14行输出脚本。

❑第11行的判断如果返回FALSE,则执行第15~17行。第17行的EXIT表示退出循环,否则当游标指向无效时重复执行第16行。

【执行效果】

参考以下执行效果可以更好地理解SQL脚本的含义。效果如下:


产品ID:0240010001 产品名称:天堂伞 产品价格:59

产品ID:0240040001 产品名称:夏普LCD-46G100A 产品价格:7000

产品ID:0240030001 产品名称:海尔XQB50-918A 产品价格:1100

产品ID:0240030002 产品名称:三星WF-R1065S/XSC 产品价格:3600

产品ID:0240030003 产品名称:三星XQB55-T86A/XSC 产品价格:2500

产品ID:0240050001 产品名称:台电C430T 产品价格:400

产品ID:0240020001 产品名称:思科RV082路由器 产品价格:2800

没有数据被提取


这里注意一下执行结果中的最后一行,如果脚本的第16行放在第17行以后,则输出结果将不包含“没有数据被提取”这句话。

属性%NOTFOUND与%FOUND的含义正好相反,它的使用方式可以参考示例3的第14行,这里不做讲解。

3)%ROWCOUNT也是比较常用的属性,利用它可以知道当前已经返回了多少行数据。

【示例8】%ROWCOUNT的使用

具体使用方法如下:


01 DECLARE

02 CURSOR pdct_rowcount_cur

03 IS SELECT*FROM PRODUCTINFO;

04

05 TYPE PDCT_TAB IS TABLE OF PRODUCTINFO%ROWTYPE;

06 pdct_count_rd PDCT_TAB;

07

08 BEGIN

09 OPEN pdct_rowcount_cur;

10 LOOP

11

12 FETCH pdct_rowcount_cur BULK COLLECT INTO pdct_count_rd LIMIT 2;

13 FOR i in pdct_count_rd.first..pdct_count_rd.last LOOP

14 DBMS_OUTPUT.PUT_LINE('产品ID:'||pdct_count_rd(i).productid||'产品名称:'||

15 pdct_count_rd(i).productname||'产品价格:'||

16 pdct_count_rd(i).productprice);

17 END LOOP;

18 IF mod(pdct_rowcount_cur%ROWCOUNT,2)=0 THEN

19 DBMS_OUTPUT.PUT_LINE('读取到了第'

20 ||pdct_rowcount_cur%ROWCOUNT

21 ||'条记录!');

22 ELSE

23 DBMS_OUTPUT.PUT_LINE('读取到单条记录为第'

24 ||pdct_rowcount_cur%ROWCOUNT

25 ||'条记录!');

26 END IF;

27 EXIT WHEN pdct_rowcount_cur%NOTFOUND;

28

29 END LOOP;

30 CLOSE pdct_rowcount_cur;

31 END;


【代码解析】

❑第1~12行可以参考示例4自行理解。

❑第13行表示对批量读取的数据从第一条到最后一条进行遍历。

❑第18行表示用条件语句进行判断,如果提取出来的数据行数能被2整除就进入THEN后面的输出脚本,如果提取的数据行数不能被2整除则进入第22行ELSE后面的输出脚本。其中,第18行的mod()是取余函数,表示pdct_rowcount_cur%ROWCOUNT对2取余。

❑第26行是IF语句的结束标志。

❑第27行利用%NOTFOUND属性判断游标是否走到尾端。此时如果没有发现可用的数据则利用EXIT退出。

【执行效果】

执行效果如下:


产品ID:0240010001 产品名称:天堂伞 产品价格:59

产品ID:0240040001 产品名称:夏普LCD-46G100A 产品价格:7000

读取到了第2条记录!

产品ID:0240030001 产品名称:海尔XQB50-918A 产品价格:1100

产品ID:0240030002 产品名称:三星WF-R1065S/XSC 产品价格:3600

读取到了第4条记录!

产品ID:0240030003 产品名称:三星XQB55-T86A/XSC 产品价格:2500

产品ID:0240050001 产品名称:台电C430T 产品价格:400

读取到了第6条记录!

产品ID:0240020001 产品名称:思科RV082路由器 产品价格:2800

读取到单条记录为第7条记录!


从执行效果中可以看出脚本每次都取出两条记录。由于该表一共7条数据,所以最后一次取出了单条记录,而脚本流程也发生了变化。

以上是对显式游标4个属性的简单介绍,通常可以利用这4个属性对脚本进行流程控制。实用性比较强,希望读者对其有更深的了解。