1)查询返回单行记录时→隐式游标;
2)查询返回多行记录并逐行进行处理时→显式游标
显式游标例子:
DECLARE CURSOR CUR_EMP IS SELECT * FROM EMP; ROW_EMP CUR_EMP%ROWTYPE; BEGIN OPEN CUR_EMP; FETCH CUR_EMP INTO ROW_EMP; WHILE CUR_EMP%FOUND LOOP DBMS_OUTPUT.PUT_LINE(ROW_EMP.EMPNO || '----' || ROW_EMP.ENAME); FETCH CUR_EMP INTO ROW_EMP; END LOOP; CLOSE CUR_EMP; END;
执行结果看窗口中的Output
--使用显式游标修改数据(给所有的部门经理加薪1000)
DECLARE CURSOR EMP_CUR IS SELECT EMPNO, ENAME, SAL FROM EMP WHERE JOB = 'MANAGER' FOR UPDATE; EMP_ROW EMP_CUR%ROWTYPE; BEGIN OPEN EMP_CUR; LOOP FETCH EMP_CUR INTO EMP_ROW; IF EMP_CUR%NOTFOUND THEN EXIT; ELSE UPDATE EMP SET SAL = SAL + 1000 WHERE CURRENT OF EMP_CUR; END IF; END LOOP; COMMIT; CLOSE EMP_CUR; END;
注意:
1、如果游标打开之前或关闭之后,使用游标属性,Oracle会抛出一个INVALID_CURSOR错误(ORA-01001);
2、如果在第一次fetch后结果集是空的,%found=false,%NotFound=true,%ROWCOUNT=0;
3、如果使用了BULK COLLECT,那么%ROWCOUNT的值可能不是0或1,实际上他返回的是提取到相关集合的行数。
DECLARE CURSOR EMP_CUR IS SELECT EMPNO, ENAME, SAL FROM EMP WHERE JOB = 'MANAGER' FOR UPDATE; BEGIN FOR EMP_ROW IN EMP_CUR LOOP UPDATE EMP SET SAL = SAL - 1000 WHERE CURRENT OF EMP_CUR; END LOOP; COMMIT; END;
--游标for循环(给所有的部门经理减薪1000)
DECLARE CURSOR EMP_CUR IS SELECT * FROM EMP FOR UPDATE; BEGIN FOR EMP_ROW IN EMP_CUR LOOP IF EMP_ROW.JOB = 'MANAGER' THEN UPDATE EMP SET SAL = SAL + 5000 WHERE CURRENT OF EMP_CUR; ELSE UPDATE EMP SET SAL = SAL + 1000 WHERE CURRENT OF EMP_CUR; END IF; END LOOP; END;
游标FOR循环确实很好的简化了游标的开发,我们不再需要 open、fetch和close语句,不再需要用 %FOUND 属性检测是否到最后一条记录,这一切Oracle隐式的帮我们完成了。