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个属性对脚本进行流程控制。实用性比较强,希望读者对其有更深的了解。