oracle数据库对象-游标

游标分为隐式游标和显示游标。

一、隐式游标
对于select * into和DML操作(update、delete、insert)都附带有一个隐式游标。

隐式游标的属性

SQL%ROWCOUNT   整型  代表DML语句成功执行的数据行数
SQL%FOUND    布尔型  值为TRUE代表插入、删除、更新或单行查询操作成功
SQL%NOTFOUND 布尔型  与SQL%FOUND属性返回值相反
SQL%ISOPEN   布尔型  DML执行过程中为真,结束后为假


当系统使用一个隐式游标时,可以通过隐式游标的属性来了解操作的状态和结果,进而控制程序的流程。隐式游标可以使用名字SQL来访问,但要注意,通过SQL游标名总是只能访问前一个DML操作或单行SELECT操作的游标属性。所以通常在刚刚执行完操作之后,立即使用SQL游标名来访问属性。

例子:

--/
DECLARE
v_emp emp%rowtype;
BEGIN
delete from emp where empno = 9999;
IF SQL%notfound THEN
  dbms_output.put_line('隐式游标 属性为notfound');
END IF;
dbms_output.put_line('delete无记录不会出现异常');
END;
/



运行结果:

隐式游标 属性为notfound
delete无记录不会出现异常

二、显式游标
1、游标的使用有4个步骤:
1)声明游标
CURSOR 游标名(参数1, 参数2, … , 参数n) IS select语句;

2)打开游标
OPEN 游标名;

3)提取数据
FETCH 游标名 INTO 变量1, 变量2 …

FETCH 游标名 INTO 记录变量;

4)关闭游标
CLOSE 游标名;

例子:

--/
DECLARE
  CURSOR c_emp IS select * from emp; --声明游标
  v_emp c_emp%rowtype;
  --v_emp emp%rowtype;
BEGIN
  OPEN c_emp; --打开游标
  LOOP
    FETCH c_emp INTO v_emp; --提取数据
    EXIT WHEN c_emp%notfound;
    dbms_output.put_line(v_emp.empno);
  END LOOP;
  CLOSE c_emp; --关闭游标
END;
/


说明:
1)关于退出循环的判断
如果用以下方式写:

EXIT WHEN c_emp%notfound;
FETCH c_emp INTO v_emp; --提取数据

v_emp中的值会多打印一次。

c_emp取到最后一条记录,然后再次循环,此时先判断c_emp是否为空,c_emp不为空,再fetch数据,此时游标才为空,v_emp中的记录不变,所以会多打印一行。

2)关于记录变量的定义
v_emp c_emp%rowtype;

v_emp emp%rowtype;
两种方式都可以。

2、游标循环
1)第一种方式,就是把游标的4个步骤都做一遍

2)第二种方式,使用for循环遍历

--/
DECLARE
  CURSOR c_emp IS select * from emp;
BEGIN
  FOR v_emp IN c_emp
  LOOP
    dbms_output.put_line(v_emp.ename);
  END LOOP;
END;
/


这个小程序里面,只有游标的声明,for循环中省略了游标的打开、数据提取、关闭。记录变量的声明也省略了。

3)第三种方式,更简单的for循环遍历

--/
BEGIN
  FOR re IN select * from emp
  LOOP
    dbms_output.put_line(re.ename);
  END LOOP;
END;
/


这个小程序里面,省略了游标的声明、打开、数据提取、关闭。记录变量的声明也省略了。

3、显式游标属性
虽然可以使用前面的形式获得游标数据,但是在游标定义以后使用它的一些属性来进行结构控制是一种更为灵活的方法。显式游标的属性如下所示。

使用方法:
游标名%属性

显式游标的属性

%ROWCOUNT    整型  获得FETCH语句返回的数据行数
%FOUND     布尔型  最近的FETCH语句返回一行数据则为真,否则为假
%NOTFOUND  布尔型  与%FOUND属性返回值相反
%ISOPEN    布尔型  游标已经打开时值为真,否则为假


小结:
使用游标可以先声明这个游标,然后使用简便的for循环来遍历数据。

参考资料:
http://heisetoufa.iteye.com/blog/366483/