游标是映射在结果集中一行数据上的位置实体,有了游标,用户就可以访问结果集中的任意一行数据了,将游标放置到某行后,即可对该行数据进行操作,例如提取当前行的数据等。
oracle 游标有4个属性:%ISOPEN,%FOUND,%NOTFOUND,%ROWCOUNT。
%ISOPEN判断游标是否被打开,如果打开%ISOPEN等于true,否则等于false;
%FOUND %NOTFOUND判断游标所在的行是否有效,如果有效,则%FOUNDD等于true,否则等于false;
%ROWCOUNT返回当前位置为止游标读取的记录行数。oracle 游标有4个属性:%ISOPEN,%FOUND,%NOTFOUND,%ROWCOUNT。
%ISOPEN判断游标是否被打开,如果打开%ISOPEN等于true,否则等于false;
%FOUND %NOTFOUND判断游标所在的行是否有效,如果有效,则%FOUNDD等于true,否则等于false;
%ROWCOUNT返回当前位置为止游标读取的记录行数。
----------------------------------------------------------------------------------------------------------------------------
游标分为显式游标和隐式游标。
当使用显式游标时,需要在定义显式游标时指定相应的select语句,这种显式游标成为静态游标。例如:
CURSOR mycur(vartype number) is
select emp_no,emp_zc from cus_emp_basic
where com_no = vartype;
当使用游标变量REF CURSOR时,在定义游标变量时不需要指定selelct语句,而是在打开游标时指定select语句,从而实现动态游标操作。例如:
DECLARE
TYPE c1 IS REF CURSOR;
emp_cursor c1;
v_ename emp.ename%TYPE;
v_sal emp.sal%TYPE;
BEGIN
OPEN emp_cursor FOR
select ename,sal FROM emp where deptno = 10;
LOOP
fetch emp_cursor INTO v_ename,v_sal;
EXIT WHEN emp_cursor%NOTFOUND;
dbms_output.put_line(v_name);
END LOOP;
CLOSE emp_cursor;
END;
-----------------------------------------------------------------------------------------------------------------------------
FOR UPDATE子句用于在游标结果集数据上加行共享锁,以防止其他用户在相应行上执行DML操作;当SELECT语句引用到多张表时,使用OF子句可以确定哪些表要加锁,如果没有OF子句,则会在SELECT语句所引用的全部表上加锁;NOWAIT子句用于指定不等待锁。在提取了游标数据之后,为了更新或删除当前游标行数据,必须在UPDATE或DELETE语句中引用WHERE CURRENT OF子句。
使用显式游标更新数据:
DECLARE
CURSOR emp_cursor IS
SELCET ename, sal FROM emp FOR UPDATE;
v_ename emp.ename%TYPE;
v_oldsal emp.sal%TYPE;
BEGIN
OPEN emp_cursor;
LOOP
FETCH emp_cursor INTO v_ename, v_oldsal;
EXIT WHEN emp_cursor%NOTFOUND;
IF v_oldsal<2000 THEN
UPDATE emp SET sal=sal+100 WHERE CURRENT OF emp_cursor;
END IF;
END LOOP;
CLOSE emp_cursor;
END;
--------------------------------------------------------------------------------------------------------------------------------
CURSOR表达式用于返回嵌套游标,例:
DECLARE
TYPE refcursor IS REF CURSOR;
CURSOR dept_cursor(no NUMBER) IS
SELECT a.dname, CURSOR(SELECT ename, sal FROM emp
WHERE deptno=a.deptno)
FROM dept a WHERE a.deptno=no;
empcur refcursor;
v_dname dept.dname%TYPE;
v_ename emp.ename%TYPE;
v_sal emp.sal%TYPE;
BEGIN
OPEN dept_cursor(&no);
LOOP
FETCH dept_cursor INTO v_dname, empcur;
EXIT WHEN dept_cursor%NOTFOUND;
dbms_output.put_line('部门名:'||v_dname);
LOOP
FETCH empcur INTO v_ename, v_sal;
EXIT WHEN empcur%NOTFOUND;
dbms_output.put_line('雇员名:'||v_ename||',工资:'||v_sal);
END LOOP;
CLOSE dept_cursor;
END;