一、为什么使用游标
返回多条记录时使用游标更简便
二、定义
游标(cursor)是Oracle系统在内存中开辟的一个工作区,在其中存放SELECT语句返回的查询结果
三、游标的用途
可以存放select返回的结果
四、游标的分类
1. 隐式游标:不用声明也可以使用
由Oracle在内部声明
由Oracle自行管理游标
可以使用游标属性从最近执行的SQL语句中获取信息
用于处理DML语句以及返回单行的查询
属性如下:
(1)SQL%ROWCOUNT:返回整型值,返回最近一条执行的SQL语句所影响到的记录数
例子:
declare
v_deptno emp.deptno%type:=10;
v_row_delete number;
begin
delete from emp
where deptno=v_deptno;
v_row_delete:=sql%rowcount; --返回最近一条记录数
dbms_output.put.line(v_row_delete);
end;
(2)SQL%FOUND:返回布尔型值,根据最近一条执行的SQL语句所影响的记录行数是否大于0,如果大于0,返回true,否则,返回false
(3)SQL%NOTFOUND:返回布尔型值,根据最近一条执行的SQL语句所影响的记录行数是否大于0,乳沟大于0,返回false,否则,返回true
(4)SQL%ISOPEN:布尔型属性,询问游标是否打开,在隐式游标中,总是返回false
2. 显示游标:由程序员声明,存储select返回的数据,可以返回多条记录
使用游标时,select语句查询的结果可以是单条记录,多条记录,也可以是0条记录
游标工作区中,存在着一个指针(POINTER),在初始状态它指向查询结果的首记录
要访问查询结果的所有记录,可以通过FETCH语句,进行指针的异动来实现
使用游标进行操作,包括定义游标、打开游标、提取数据以及关闭游标几步
--pointer:从游标中第一条记录开始检索
--fetch:从游标区中获取数据赋值给变量
--四步骤:
--1.声明游标:cursor emp_cursor
--注意:在子查询中不能使用into,如有需要,可以使用order子句
--2.开启游标:open emp_cursor
--3.获取数据:fetch emp_cursor into v_var
--4.关闭游标:close emp_cursor
declare
v_name emp.ename%type;
v_job emp.job%type;
cursor emp_cursor is
select ename,job from emp; --声明游标
begin
open emp_cursor; --打开游标执行sql语句
for v_count in 1..5 loop
--获取数据并把数据赋值给变量
--注意:变量赋值的顺序要和select后面的顺序一致
fetch emp_cursor into v_name,v_job;
dbms_output.put_line(v_ename||' '||v_job);
end loop;
close emp_cursor; --关闭游标
end;
属性如下:
(1)%isopen:布尔,如果游标是打开的,其值为TRUE
(2)%found:布尔,如果FETCH语句返回一条记录,其值为TRUE
(3)%notfound:布尔,如果FETCH语句没有返回记录,其值为TRUE
(4)%rowcount:数值,返回迄今为止已经从游标中取出的记录数目
应用:
declare
v_empno emp.empno%type;
v_ename emp.ename%type;
cursor emp_cursor is
select empno,ename from emp;
begin
if not emp_cursor%isopen
open emp_cursor;
end if;
loop
fetch emp_cursor into v_empno,v_ename;
exit when emp_cursor%notfound; --当没有记录返回时退出循环
end loop;
dbms_output.put_line(emp_cursor%rowcount);
end;
五、带参数的游标
declare
v_ename emp.ename%type;
--声明游标并定义参数
cursor emp_cursor(p_deptno number,p_sal number)
is
select ename
where deptno=p_deptno and sal>p_sal;
begin
--开启游标并给参数赋值
open emp_cursor(10,3000);
loop
--获取数据
fetch emp_cursor into v_ename;
exit when emp_cursor%notfound;
dbms_output.put_line(v_ename);
end loop;
close emp_cursor;
end;