上一次,介绍了FETCH BULK COLLECCT INTO语句,可以用于显示游标的结果集所有数据一次性批量取得的处理中。
也就是说,可以一次性操作,将结果集所有数据转换成配列数组。
优点是:结果集不能随意利用某一行数据,但是配列可以自由访问任意节点的数据。
本次接着上次继续解说LIMIT语句用法。
LIMIT语句是FETCH BULK COLLECCT INTO语句的可选语句。
没有LIMIT语句的时候,结果集全部数据一次性取得并保存到数组变量中。
因此,结果集的数据非常多的时候,将大量的数据一次性放到数组里,如果内存不足,会影响性能。
使用LIMIT句的话,不需要将大量的所有数据一次性放到数组里,可以分批取的数据,可以通过LIMIT指定一次性取得的数据行数。
我们把之前的例子改成LIMIT语句的处理方式:
和上次一样,TEST01表有10行数据,数据修改如下:
SQL> SELECT * FROM TEST01 ORDER BY A;
A B
1 BB001
2 BB002
3 BB003
4 BB004
5 BB005
6 BB006
7 BB007
8 BB008
9 BB009
10 BB010
选择了10行。
把LIMIT句的值设为4:
启用画面显示
SQL> SET SERVEROUTPUT ON
执行一下语句:
SQL>DECLARE --定义部
2 --声明游标
3 CURSOR C1 IS SELECT * FROM TEST01 ORDER BY A;
4 --声明记录类型变量的数组类型
5 TYPE RECTAB_TYPE IS TABLE OF C1%ROWTYPE INDEX BY BINARY_INTEGER;
6 --声明该记录类型的配列
7 RECTAB RECTAB_TYPE;
8 --申明一个存储过程:内容是以降顺显示记录类型的数组内容
9 PROCEDURE PROC_REVERSE_DISP( PTAB IN RECTAB_TYPE)
10 IS
11 JBINARY INTEGER;–用于排列的变量
12 BEGIN
13 J := PTAB.LAST;–配列的最后一个索引值
14 LOOP
15 DBMS_OUTPUT.PUT_LINE(PTAB(J).B);–显示到画面上
16 EXIT WHEN J = PTAB.FIRST;–配列的第一个索引值结束
17 J := PTAB.PRIOR(J);–配列的前一个索引值
18 END LOOP;
19 END PROC_REVERSE_DISP;
20 BEGIN --执行部
21 OPEN C1;–打开游标(打开游标和结果集)
22 LOOP --循环处理
23 FETCH C1 BULK COLLECCT INTO RECTAB LIMIT4;-- 一次性取得4行数据
24 PROC REVERSE DISP(RECTAB); --用定义的存储过程中按降顺的方式显示到画面上
25 EXIT WHEN C1%NOTFOUND;
26 END LOOP;
27 CLOSE C1;
28 END;
29 /
BB004
BB003
BB002
BB001
BB008
BB007
BB006
BB005
BB010
BB009
PL/SQL过程成功完成。
解说如下:。
LIMIT句的值是4,批量取得处理每次取得4行数据。
因为总行数是10行,所以需要循环进行这个处理。
同理,降序显示的逻辑也要循环执行。
为了让循环构造更容易理解,第9-19行在定义部将其处理过程化了。
该存储程序接收PTAB的配列的变量(第9行参数的定义:PTAB),过程内容是将配列的B列按照降顺显示在画面上。
在执行块(从第20行开始)中,游标打开后,提取4行数据(23行)存储到配列里,以降顺显示到画面上,并循环这些处理(22行~26行)
这样的话,就重复将10行的数据每次取得4行数据进行批量绑定,最后一次只有2条数据用的批量绑定的方式。
注意,此时游标%NOTFOUND的值是TRUE。
一般情况下,如果用FETCH INTO语句一行一行地取得数据的话,在最后一次没有再取到数据的时候,游标名%NOTFOUND才会变为TRUE,
但是在有LIMIT句的FETCH BULK COLLEC INTO语句中,即使最后一次还是有数据的,但是残留的数据条数小于LIMIT语句指定的行数,
游标名%NOTFOUND也为TRUE,并不是没数据才为TRUE。这时特别要注意的。
因此,第21行的“EXIT WHEN C1%NOTFOUND;”的语句没有紧挨着第23行的FETCH文之后的。
也就是说,最后一次即使游标名为%NOTFOUND的TRUE,也是有一些残留数据可以取到了。
所以组织逻辑的时候稍微有些差异
另外,请注意显示的B列值的顺序:降序显示的数据也是以4行为一次显示结果的。
本次到此为止。期待下次。