1、游标的概念 游标可以对查询返回的结果集进行处理。 游标就像一个指针,可以在查询返回的结果集中自由的上下移动。 对当前指向的记录进行update、delete等操作。 游标通过一个子查询定义数据操作范围:select * from emp; 2、游标的分类 隐式游标:DML操作如update、delete。Oracle数据库都会隐含的帮我们打开一个游标,将需要操作的数据放到内存中进行操作。 显式游标:用户自己定义的游标类型,用户根据业务需要处理用户的数据。 3、显示游标 语法:CURSOR 游标名称([参数列表]) [return 返回类型] IS 子查询 [FOR UPDATE[OF 数据列,数据列,][NOWAIT]] 4、游标操作步骤: a、声明游标 b、打开游标 if v_emp_cursor%isopen then null; else open v_emp_cursor; end if; c、循环操作游标 fetch v_emp_cursor into v_emp; dbms_output.put_line(v_emp.empno||’ ‘||v_emp.ename); fetch v_emp_cursor into v_emp; dbms_output.put_line(v_emp.empno||’ ‘||v_emp.ename); 循环1 fetch v_emp_cursor into v_emp; while v_emp_cursor%found loop dbms_output.put_line(v_emp.empno||’ ‘||v_emp.ename); fetch v_emp_cursor into v_emp; end loop; 循环2 loop exit when v_emp_cursor%notfound; dbms_output.put_line(v_emp.empno||’ ‘||v_emp.ename); fetch v_emp_cursor into v_emp; end loop; 循环3(for循环,不用打开和关闭游标,它天生就是游标而生,自动打开关闭游标,自动获取下一行) for x in v_emp_cursor loop dbms_output.put_line(x.empno||’ ‘||x.ename); end loop; d、关闭游标 close v_emp_cursor; 记得关闭游标,不然数据一直占用内存 5、游标变量 declare cursor v_emp_cursor(v_deptno emp.deptno%type) is select * from emp where deptno=v_deptno; begin for x in v_emp_cursor(10)或者v_emp_cursor(&v_deptno) loop dbms_output.put_line(x.empno||’ ‘||x.ename); end loop; 6、显示游标数据保存到嵌套表中 语法 FETCH 游标名称 BULK COLLECT INTO 嵌套表名称; declare cursor c_emp return emp%rowtype is select * from emp; tpye v_emp_type is table of emp%rowtype; v_emp v_emp_type; begin if c_emp%isopen then null; else open c_emp; end if; fetch c_emp bulk collect into v_emp_type; for x in v_emp_type.first…v_emp_type.last loop dbms_output.put_line(v_emp_type(x).empno||’ '||v_emp_type(x).ename); end loop; close c_emp;
7、显示游标修改数据 语法 CURSOR 游标名称([参数列表]) [RETURN 返回类型] IS 子查询 [FOR UPDATE[OF 数据列,数据列] [NOWAIT]] 本节主要目的: for update for update nowait where current of 游标名称 for update of column1,column2…(针对子查询是笛卡尔乘积) 题目:一次性上涨工人工资,工资上涨原则如下: 10部门上涨15% 20部门上涨22% 30部门上涨39% 每个员工的工资最高为5000,上涨到5000后就不能再上涨了 DECLARE CURSOR V_EMP_CURSOR IS SELECT * FROM EMP (FOR UPDATE加锁,防止游标运行期间其它事务影响我的命令块;FOR UPDATE NOWAIT防止游标一直等待); V_SAL EMP.SAL%TYPE; BEGIN FOR V_EMP IN V_EMP_CURSOR LOOP –DBMS.OUTPUT.PUT_LINE(V_EMP.EMPNO); IF V_EMP.EMPNO=10 THEN V_SAL:=V_EMP.SAL0.15; IF V_SAL<5000 THEN UPDATE EMP SET SAL=V_SAL WHERE EMP.EMPNO=V_EMP.EMPNO; ELSE UPDATE EMP SET SAL=5000 WHERE EMP.EMPNO=V_EMP.EMPNO; END IF; ELSIF V_EMP.EMPNO=20 THEN V_SAL:=V_EMP.SAL0.22; IF V_SAL<5000 THEN –UPDATE EMP SET SAL=V_SAL WHERE EMP.EMPNO=V_EMP.EMPNO; UPDATE EMP SET SAL=V_SAL WHERE current of V_EMP_CURSOR(这个时候必须要有FOR UPDATE); ELSE UPDATE EMP SET SAL=5000 WHERE EMP.EMPNO=V_EMP.EMPNO; END IF; ELSIF V_EMP.EMPNO=20 THEN V_SAL:=V_EMP.SAL*0.39; IF V_SAL<5000 THEN UPDATE EMP SET SAL=V_SAL WHERE EMP.EMPNO=V_EMP.EMPNO; ELSE UPDATE EMP SET SAL=5000 WHERE EMP.EMPNO=V_EMP.EMPNO; END IF; ELSE NULL; END IF; COMMIT; END LOOP; END;