3.8.3 带参数的游标

在前面介绍游标的例子中,SELECT语句都没有WHERE子句,或者用WHERE子句指定了一个固定的条件,这样每次都查询同样的数据。在更多的情况下,可能要根据实际情况查询不同的数据。为了通过游标对数据进行更加灵活的处理,可以为游标定义参数,这些参数可以用在WHERE子句中。在打开游标时,指定实际的参数值,这样游标在每次打开时,可以根据不同的实际参数值,返回所需的不同数据。

定义带参数的游标的语法格式为:


DECLARE

CURSOR 游标名(参数1,参数2,……)

IS

SELECT语句;


其中参数的定义方法与子程序中的参数定义完全相同,可以指定默认值,指定参数传递模式。默认的参数传递模式为IN,如果要使用OUT或者“IN OUT”模式,就需要明确指定。由于游标一般不需要通过参数向调用者传递数据,所以OUT模式在游标中没有什么实际用处。

在用OPEN命令打开游标时,要向游标提供实际参数,游标根据提供的参数值,查询符合条件的数据。打开游标的语法格式为:


OPEN游标名(实际参数1,实际参数2……);


例如,考虑在下面定义的游标。


DECLARE

CURSOR cur_6(d_no IN emp.deptno%type, min_sal IN emp.sal%type:=1000)

IS

SELECT ename, sal, hiredate FROM emp

WHERE deptno=d_no and sal>=min_sal;

e cur_6%rowtype;

BEGIN

if not cur_6%ISOPEN then—如果游标没有打开,则打开它

open cur_6(20,2000);

END if;

fetch cur_6 INTO e;—取出第一行数据

while cur_6%found loop

dbms_output.put_line('姓名:'||e.ename||'工资:'||e.sal||'工作时间:'||e.hiredate);

fetch cur_6 INTO e;

END loop;

dbms_output.put_line('员工总数:'||cur_6%rowcount);—获取的总行数

close cur_6;—关闭游标

END;


这个块的执行结果为:


姓名:JONES 工资:2975 工作时间:02-4月-81

姓名:SCOTT 工资:3000 工作时间:19-4月-87

姓名:FORD 工资:3000 工作时间:03-12月-81

员工总数:3


在这个例子中,用传统的循环方法处理游标。首先定义了一个带参数的游标,参数d_no表示部门编号,min_sal表示最低工资,两个参数的传递模式都是IN。游标的功能是查询属于指定部门并且工资不低于指定值的所有员工。

在打开游标时,指定了两个实际参数20和2000,这样,检索出来的数据就是属于部门20,并且工资不低于2000的所有员工。如果再次以“open cur_6(10,3000)”的形式打开游标,那么检索到的数据就是属于部门10,并且工资不低于3000的员工。由此可见,带参数的游标在查询数据时更加灵活。

如果要用FOR循环处理游标中的数据,可以按照同样的方法定义游标。由于没有使用OPEN命令打开游标,所以实际参数在FOR语句中指定。这时FOR语句的格式为:


FOR 变量 IN 游标(实际参数1,实际参数2……)LOOP

……

END LOOP;


这样,在循环开始执行时,游标自动打开,并根据指定的实际参数查询数据。例如,用FOR循环处理带参数的游标,对上面的PL/SQL块进行修改,代码如下:


DECLARE

CURSOR cur_7(d_no emp.deptno%type, min_sal emp.sal%type)

IS

SELECT ename, sal, hiredate FROM emp

WHERE deptno=d_no and sal>=min_sal;

e_count integer:=0;

BEGIN

FOR e IN cur_7(10,3000)LOOP

dbms_output.put_line('姓名:'||e.ename||'工资:'||e.sal||'工作时间:'||e.hiredate);

e_count:=e_count+1;

END LOOP;

dbms_output.put_line('员工总数:'||e_count);

END;


这个块的执行结果为:


姓名:KING 工资:5000 工作时间:17-11月-81

员工总数:1