日期:2014-05-16  浏览次数:20415 次

快速掌握Oracle数据库游标的使用方法
 显式游标

  当查询返回结果超过一行时,就需要一个显式游标,此时用户不能使用select into语句。PL/SQL管理隐式游标,当查询开始时隐式游标打开,查询结束时隐式游标自动关闭。显式游标在PL/SQL块的声明部分声明,在执行部分或异常处理部分打开,取出数据,关闭。

  使用游标

  这里要做一个声明,我们所说的游标通常是指显式游标,因此从现在起没有特别指明的情况,我们所说的游标都是指显式游标。要在程序中使用游标,必须首先声明游标。

  声明游标

  语法:

  CURSOR cursor_name IS select_statement;


  在PL/SQL中游标名是一个未声明变量,不能给游标名赋值或用于表达式中。

  例:
  DELCARE

  CURSOR C_EMP IS SELECT empno,ename,salary

  FROM emp

  WHERE salary>2000

  ORDER BY ename;

  ........

  BEGIN
  
在游标定义中SELECT语句中不一定非要表可以是视图,也可以从多个表或视图中选择的列,甚至可以使用*来选择所有的列 。

  打开游标

  使用游标中的值之前应该首先打开游标,打开游标初始化查询处理。打开游标的语法是:

  
OPEN cursor_name。


  cursor_name是在声明部分定义的游标名

  例:

  OPEN C_EMP; 关闭游标。

  语法:

  
CLOSE cursor_name


  例:

  CLOSE C_EMP; 从游标提取数据。从游标得到一行数据使用FETCH命令。每一次提取数据后,游标都指向结果集的下一行。语法如下:

  
FETCH cursor_name INTO variable[,variable,...]


  对于SELECT定义的游标的每一列,FETCH变量列表都应该有一个变量与之相对应,变量的类型也要相同。

  例:
  SET SERVERIUTPUT ON

  DECLARE

  v_ename EMP.ENAME%TYPE;

  v_salary EMP.SALARY%TYPE;

  CURSOR c_emp IS SELECT ename,salary FROM emp;

  BEGIN

  OPEN c_emp;

  FETCH c_emp INTO v_ename,v_salary;

  DBMS_OUTPUT.PUT_LINE('Salary of Employee'|| v_ename ||'is'|| v_salary);

  FETCH c_emp INTO v_ename,v_salary;

  DBMS_OUTPUT.PUT_LINE('Salary of Employee'|| v_ename ||'is'|| v_salary);

  FETCH c_emp INTO v_ename,v_salary;

  DBMS_OUTPUT.PUT_LINE('Salary of Employee'|| v_ename ||'is'|| v_salary);

  CLOSE c_emp;

  END
 
 这段代码无疑是非常麻烦的,如果有多行返回结果,可以使用循环并用游标属性为结束循环的条件,以这种方式提取数据,程序的可读性和简洁性都大为提高,下面我们使用循环重新写上面的程序:
  SET SERVERIUTPUT ON

  DECLARE

  v_ename EMP.ENAME%TYPE;

  v_salary EMP.SALARY%TYPE;

  CURSOR c_emp IS SELECT ename,salary FROM emp;

  BEGIN

  OPEN c_emp;

  LOOP

  FETCH c_emp INTO v_ename,v_salary;

  EXIT WHEN c_emp%NOTFOUND;

  DBMS_OUTPUT.PUT_LINE('Salary of Employee'|| v_ename ||'is'|| v_salary);

  END
  
记录变量

  定义一个记录变量使用TYPE命令和%ROWTYPE,关于%ROWsTYPE的更多信息请参阅相关资料。

  记录变量用于从游标中提取数据行,当游标选择很多列的时候,那么使用记录比为每列声明一个变量要方便得多。

  当在表上使用%ROWTYPE并将从游标中取出的值放入记录中时,如果要选择表中所有列,那么在SELECT子句中使用*比将所有列名列出来要得多。

  例:
  SET SERVERIUTPUT ON

  DECLARE

  R_emp EMP%ROWTYPE;

  CURSOR c_emp IS SELECT * FROM emp;

  BEGIN

  OPEN c_emp;

  LOOP

  FETCH c_emp INTO r_emp;

  EXIT WHEN c_emp%NOTFOUND;

  DBMS_OUT.PUT.PUT_LINE('Salary of Employee'||r_emp.ename||'is'|| r_emp.salary);

  END LOOP;

  CLOSE c_emp;

  END;

  %ROWTYPE也可以用游标名来定义,这样的话就必须要首先声明游标:

  SET SERVERIUTPUT ON

  DECLARE

  CURSOR c_emp IS SELECT ename,salary FROM emp;

  R_emp c_emp%ROWTYPE;

  BEGIN

  OPEN c_emp;

  LOOP

  FETCH c_emp INTO r_emp;

  EXIT WHEN c_emp%NOTFOUND;

  DBMS_OUT.PUT.PUT_LINE('Salary of Employee'

  ||r_emp.ename||'is'|| r_emp.salary);

  END LOOP;

  CLOSE c_emp;

  END;
 
 带参数的游标

  与存储过程和函数相似,可以将参数传递给游标并在查询中使用。这对于处理在某种条件下打开游标的情况非常有用。它的语法如下:
  CURSOR cursor_name[(parameter[,parameter],...)] IS select_statement;
  
定义参数的语法如下:

  
Parameter_name [IN] data_type[{:=|DEFAULT} value]


  与存储过程不同的是,游标只能接受传递的值,而不能返回值。参数只定义数据类型,没有大小。

  另外可以给参数设定一个缺省值,当没有参数值传递给游标时,就使用缺省值。游标中定义的参数只是一个占位符,在别处引用该参数不一定可靠。

  在打开游标时给参数赋值,语法如下:

 
 OPEN cursor_name[value[,value]....];

  参数值可以是文字或变量。

  例:
  DECALRE

  CURSOR c_dept IS SELECT * FROM dept ORDER BY deptno;

  CURSOR c_emp (p_dept VARACHAR2) I