声明一个显式游标后,可以在同一子程序或程序包中对其进行定义,或者同时声明并定义显式游标。

仅声明游标的显式游标声明具有以下语法:

明确的游标定义语法如下:

  1. IS select_statement;

显式游标处理需四个步骤:

  1. 定义游标

  2. 打开游标

  3. 提取游标数据

定义游标

定义游标名,以及与其相对应的 SELECT 语句。

格式如下:

  1. CURSOR cursor_name[(parameter[, parameter]…)] IS select_statement;

游标参数只能为输入参数,其格式为:

  1. parameter_name [IN] datatype [{:= | DEFAULT} expression]

注意

在指定数据类型时,不能使用长度约束。如 NUMBER(4)、CHAR(10) 等都是错误的。

打开游标

执行游标所对应的 SELECT 语句,将其查询结果放入工作区,并且指针指向工作区的首部,标识游标结果集合。如果游标查询语句中带有 FOR UPDATE 选项,OPEN 语句还将锁定数据库表中游标结果集合对应的数据行。

  1. OPEN cursor_name[([parameter =>] value[, [parameter =>] value]…)];

在向游标传递参数时,可以使用与函数参数相同的传值方法,即位置表示法和名称表示法。PL 程序不能用 OPEN 语句重复打开一个游标。

提取游标数据

检索结果集合中的数据行,放入指定的输出变量中。

格式如下:

对该记录进行循环处理,直到处理完活动集合中的所有记录。

关闭游标

当提取和处理完游标结果集合数据后,应及时关闭游标,以释放该游标所占用的系统资源,并使该游标的工作区变成无效,这时就不能再使用 FETCH 语句取其中数据。关闭后的游标可以使用 OPEN 语句重新打开。

格式如下:

  1. CLOSE cursor_name;

下面步骤展示了如何使用显式游标循环获取记录集的每行记录。

  1. 首先在声明部分声明一个游标,参见以下两种方法。
  1. CURSOR cursor_name IS query;
  1. CURSOR cursor_name(para_namedata_type) IS query;
  1. 在声明部分声明一个记录保存游标返回的行记录。
  1. record_name cursor_name%ROWTYPE;
  1. 在执行部分打开游标,参见以下两种方法。
  1. OPEN cursor_name(para_name);
  1. 在执行部分从游标记录集中获取行数据。每次一行,结合下面格式的 LOOP 语句一起使用可以获取多行数据。
  1. LOOP
  2. FETCHcursor_name INTO record_name;
  3. EXIT WHENcursor_name%NOTFOUND;
  4. statement;
  5. [ statement; ]...
  6. END LOOP;
  1. 关闭游标。
  1. CLOSE cursor_name;
  1. delimiter /
  2. PROCEDURE sp_record_print(p_w_id IN ware.w_id%type);
  3. END;
  4. /
  5. delimiter ;
  6. delimiter /
  7. CREATE OR REPLACE PACKAGE BODY pkg_ware_mgmt
  8. AS
  9. AS
  10. BEGIN
  11. dbms_output.put_line('Print a record :');
  12. dbms_output.put_line('W_ID : ' || p_record.w_id
  13. || ', W_YTD : ' || p_record.w_ytd
  14. || ', W_TAX : ' || p_record.w_tax
  15. || ', W_NAME : ' || p_record.w_name
  16. || ', W_STREET_1 : ' || p_record.w_street_1
  17. || ', W_STREET_2 : ' || p_record.w_street_2
  18. || ', W_CITY : ' || p_record.w_city
  19. || ', W_STATE : ' || p_record.w_state
  20. || ', W_ZIP : ' || p_record.w_zip )
  21. ;
  22. dbms_output.put_line('');
  23. END;
  24. PROCEDURE sp_record_print(p_w_id IN ware.w_id%TYPE )
  25. IS
  26. CURSOR c1(cp_w_id ware.w_id%TYPE ) IS SELECT * FROM ware WHERE w_id = cp_w_id ;
  27. r_ware ware%ROWTYPE;
  28. BEGIN
  29. dbms_output.put_line('Open a cursor with a parameter [ ' || p_w_id || ' ].');
  30. LOOP
  31. FETCH c1 INTO r_ware ;
  32. EXIT WHEN c1%NOTFOUND ;
  33. sp_record_print_by_record(r_ware);
  34. END LOOP;
  35. EXCEPTION
  36. WHEN OTHERS THEN
  37. dbms_output.put_line('Raise an unkown exception !');
  38. END ;
  39. END;
  40. /
  41. delimiter ;
  42. obclient> set serveroutput on;
  43. Query OK, 0 rows affected (0.00 sec)
  44. obclient> call pkg_ware_mgmt.sp_record_print(1);
  45. Query OK, 0 rows affected (0.12 sec)
  46. Open a cursor with a parameter [ 1 ].
  47. Fetch the cursor one time.
  48. Print a record :
  49. 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
  50. Fetch the cursor one time.