显式游标主要是用于对查询语句的处理,尤其是在查询结果为多条记录的情况下。
显示游标的调用格式
声明一个显式游标后,可以在同一子程序或程序包中对其进行定义,或者同时声明并定义显式游标。
仅声明游标的显式游标声明具有以下语法:
CURSOR cursor_name [ parameter_list ] RETURN return_type;
明确的游标定义语法如下:
CURSOR cursor_name [ parameter_list ] [ RETURN return_type ]
IS select_statement;
显示游标的处理步骤
显式游标处理需四个步骤:
定义游标
打开游标
提取游标数据
关闭游标
定义游标
定义游标名,以及与其相对应的 SELECT 语句。
格式如下:
CURSOR cursor_name[(parameter[, parameter]…)] IS select_statement;
游标参数只能为输入参数,其格式为:
parameter_name [IN] datatype [{:= | DEFAULT} expression]
注意
在指定数据类型时,不能使用长度约束。如 NUMBER(4)、CHAR(10) 等都是错误的。
打开游标
执行游标所对应的 SELECT 语句,将其查询结果放入工作区,并且指针指向工作区的首部,标识游标结果集合。如果游标查询语句中带有 FOR UPDATE 选项,OPEN 语句还将锁定数据库表中游标结果集合对应的数据行。
格式如下:
OPEN cursor_name[([parameter =>] value[, [parameter =>] value]…)];
在向游标传递参数时,可以使用与函数参数相同的传值方法,即位置表示法和名称表示法。PL 程序不能用 OPEN 语句重复打开一个游标。
提取游标数据
检索结果集合中的数据行,放入指定的输出变量中。
格式如下:
FETCH cursor_name INTO {variable_list | record_variable };
对该记录进行循环处理,直到处理完活动集合中的所有记录。
关闭游标
当提取和处理完游标结果集合数据后,应及时关闭游标,以释放该游标所占用的系统资源,并使该游标的工作区变成无效,这时就不能再使用 FETCH 语句取其中数据。关闭后的游标可以使用 OPEN 语句重新打开。
格式如下:
CLOSE cursor_name;
使用显示游标循环获取记录集的每行记录
下面步骤展示了如何使用显式游标循环获取记录集的每行记录。
- 首先在声明部分声明一个游标,参见以下两种方法。
CURSOR cursor_name IS query;
CURSOR cursor_name(para_namedata_type) IS query;
- 在声明部分声明一个记录保存游标返回的行记录。
record_name cursor_name%ROWTYPE;
- 在执行部分打开游标,参见以下两种方法。
OPEN cursor_name;
OPEN cursor_name(para_name);
- 在执行部分从游标记录集中获取行数据。每次一行,结合下面格式的 LOOP 语句一起使用可以获取多行数据。
LOOP
FETCHcursor_name INTO record_name;
EXIT WHENcursor_name%NOTFOUND;
statement;
[ statement; ]...
END LOOP;
- 关闭游标。
CLOSE cursor_name;
示例:使用显式游标循环获取记录集的每行记录
delimiter /
CREATE OR REPLACE PACKAGE pkg_ware_mgmt as
PROCEDURE sp_record_print(p_w_id IN ware.w_id%type);
END;
/
delimiter ;
delimiter /
CREATE OR REPLACE PACKAGE BODY pkg_ware_mgmt
AS
PROCEDURE sp_record_print_by_record(p_record IN ware%ROWTYPE)
AS
BEGIN
dbms_output.put_line('Print a record :');
dbms_output.put_line('W_ID : ' || p_record.w_id
|| ', W_YTD : ' || p_record.w_ytd
|| ', W_TAX : ' || p_record.w_tax
|| ', W_NAME : ' || p_record.w_name
|| ', W_STREET_1 : ' || p_record.w_street_1
|| ', W_STREET_2 : ' || p_record.w_street_2
|| ', W_CITY : ' || p_record.w_city
|| ', W_STATE : ' || p_record.w_state
|| ', W_ZIP : ' || p_record.w_zip )
;
dbms_output.put_line('');
END;
PROCEDURE sp_record_print(p_w_id IN ware.w_id%TYPE )
IS
CURSOR c1(cp_w_id ware.w_id%TYPE ) IS SELECT * FROM ware WHERE w_id = cp_w_id ;
r_ware ware%ROWTYPE;
BEGIN
OPEN c1(p_w_id);
dbms_output.put_line('Open a cursor with a parameter [ ' || p_w_id || ' ].');
LOOP
FETCH c1 INTO r_ware ;
dbms_output.put_line('Fetch the cursor one time.');
EXIT WHEN c1%NOTFOUND ;
sp_record_print_by_record(r_ware);
END LOOP;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('Raise an unkown exception !');
END ;
END;
/
delimiter ;
obclient> set serveroutput on;
Query OK, 0 rows affected (0.00 sec)
obclient> call pkg_ware_mgmt.sp_record_print(1);
Query OK, 0 rows affected (0.12 sec)
Open a cursor with a parameter [ 1 ].
Fetch the cursor one time.
Print a record :
W_ID : 1, W_YTD : 1200, W_TAX : .1868, W_NAME : W_NAME_1, W_STREET_1 : jTNkXKWXOdh, W_STREET_2 : lf9QXTXXGoF04IZBkCP7, W_CITY : srRq15uvxe5, W_STATE : GQ, W_ZIP : 506811111
Fetch the cursor one time.
obclient>