DECLARE
cursor mycur is select * from emp;
empInfo emp%ROWTYPE;
BEGIN
open mycur;
fetch mycur into empInfo;
while(mycur%found)
loop
dbms_output.put_line('编码:'||empInfo.Empno||';姓名:'||empInfo.Ename);
-- 使游标向下一行
fetch mycur into empInfo;
end loop;
END;
注意 1: 在打开游标之前最好先判断游标是否已经是打开的。
通过 ISOPEN 判断,
格式:
游标%ISOPEN IF mycur%ISOPEN THEN
null ; ELSE
OPEN mycur ; END IF ;
注意 2:可以使用 ROWCOUNT 对游标所操作的行数进行记录。
代码:
DECLARE
cursor mycur is select * from emp;
empInfo emp%ROWTYPE;
cou number;
BEGIN
if mycur%isopen then
null;
else
open mycur;
end if;
loop
fetch mycur into empInfo;
exit when mycur%notfound;
cou:=mycur%rowcount;--记录总数
dbms_output.put_line('总数:'||cou);
end loop;
/* open mycur;
fetch mycur into empInfo;
while(mycur%found)
loop
dbms_output.put_line('编码:'||empInfo.Empno||';姓名:'||empInfo.Ename);
fetch mycur into empInfo;
end loop;
*/
END;
应用举例:
一次性上涨全部雇员的工资。根据它所在的部门涨工资,规则:
• 10 部门上涨 10%
• 20 部门上涨 20%
• 30 部门上涨 30%
所有部门的上涨工资,最不能超过 5000,如果超过 5000,则工资就为 5000。
declare
cursor mycur is select * from emp;
empInfo emp%rowtype;
s emp.sal%type;
begin
for empInfo in mycur loop
if empInfo.deptno = 10 then s := empInfo.sal*1.1;
elsif empInfo.deptno = 20 then
s := empInfo.sal*1.2;
elsif empInfo.deptno = 30 then s := empInfo.sal* 1.3;
end if;
if s > 5000 then s := 5000; end if;
update emp set sal = s where empno = empInfo.empno;
end loop;
end;
游标属性
%FOUND 布尔型属性,当最近一次读记录时成功返回,则值为TRUE;
%NOTFOUND 布尔型属性,与%FOUND相反;
%ISOPEN 布尔型属性,当游标已打开时返回 TRUE;
%ROWCOUNT 数字型属性,返回已从游标中读取的记录数。
游标修改和删除操作
游标修改和删除操作是指在游标定位下,修改或删除表中指定的数据行。这时,要求游标查询语句中必须使用FOR UPDATE选项,以便在打开游标时锁定游标结果集合在表中对应数据行的所有列和部分列。
为了对正在处理(查询)的行不被另外的用户改动,ORACLE 提供一个 FOR UPDATE 子句来对所选择的行进行锁住。该需求迫使ORACLE锁定游标结果集合的行,可以防止其他事务处理更新或删除相同的行,直到您的事务处理提交或回退为止。
语法:
SELECT . . . FROM … FOR UPDATE [OF column[, column]…] [NOWAIT]
如果另一个会话已对活动集中的行加了锁,那么SELECT FOR UPDATE操作一直等待到其它的会话释放这些锁后才继续自己的操作,对于这种情况,当加上NOWAIT子句时,如果这些行真的被另一个会话锁定,则OPEN立即返回并给出:
ORA-0054 :resource busy and acquire with nowait specified.
如果使用 FOR UPDATE 声明游标,则可在DELETE和UPDATE 语句中使用WHERE CURRENT OF cursor_name子句,修改或删除游标结果集合当前行对应的数据库表中的数据行。
例12:从EMP表中查询某部门的员工情况,将其工资最低定为 1500;
DECLARE
V_deptno emp.deptno%TYPE :=&p_deptno;
CURSOR emp_cursor IS SELECT empno, sal
FROM emp WHERE deptno=v_deptno FOR UPDATE NOWAIT;
BEGIN
FOR emp_record IN emp_cursor LOOP
IF emp_record.sal < 1500 THEN
UPDATE emp SET sal=1500 WHERE CURRENT OF emp_cursor;
END IF;
END LOOP;
-- COMMIT;
END;