显式游标
处理显式游标需要四个 PL/SQL步骤:
定义游标:就是定义一个游标名,以及与其相对应的SELECT 语句
CURSOR cursor_name IS select_statement;
打开游标:OPEN cursor_name
提取游标:就是检索结果集合中的数据行,放入指定的输出变量中
FETCH cursor_name INTO {variable_list | record_variable };
关闭游标:当提取和处理完游标结果集合数据后,应及时关闭游标,以释放该游标所占用的系统资源,
并使该游标的工作区变成无效,不能再使用FETCH 语句取其中数据。
关闭后的游标可以使用OPEN 语句重新打开
CLOSE cursor_name;
例:
1 DECLARE 2 3 v_ename emp.ename%TYPE; 4 5 v_sal emp.sal%TYPE; 6 7 CURSOR c_cursor IS SELECT ename, sal FROM emp WHERE rownum<11; 8 9 BEGIN 10 11 OPEN c_cursor; 12 13 FETCH c_cursor INTO v_ename, v_sal; 14 15 WHILE c_cursor %FOUND LOOP 16 17 DBMS_OUTPUT.PUT_LINE(v_ename||‘---‘||to_char(v_sal) ); 18 19 FETCH c_cursor INTO v_ename, v_sal; 20 21 END LOOP; 22 23 CLOSE c_cursor; 24 25 END;
参数化游标
例:
DECLARE v_ename emp.ename%TYPE; v_sal emp.sal%TYPE; CURSOR c_cursor(P_sal emp.sal%type) IS SELECT ename, sal FROM emp WHERE sal >= P_sal; BEGIN OPEN c_cursor(1000); FETCH c_cursor INTO v_ename, v_sal; WHILE c_cursor %FOUND LOOP DBMS_OUTPUT.PUT_LINE(v_ename||‘---‘||to_char(v_sal) ); FETCH c_cursor INTO v_ename, v_sal; END LOOP; CLOSE c_cursor; END;
游标属性
%FOUND :布尔型属性,当最近一次读记录时成功返回,则值为TRUE;
%NOTFOUND :布尔型属性,与%FOUND相反
%ISOPEN: 布尔型属性,当游标已打开时返回 TRUE;
%ROWCOUNT:数字型属性,返回已从游标中读取的记录数。
处理隐式游标
例:
1 DECLARE 2 3 V_deptno emp.deptno%TYPE :=&p_deptno; 4 5 BEGIN 6 7 DELETE FROM emp WHERE deptno=v_deptno; 8 9 IF SQL%NOTFOUND THEN 10 11 DELETE FROM dept WHERE deptno= 20; 12 13 END IF; 14 15 END;
游标检索循环
例:
1 DECLARE 2 3 v_empno emp.empno%TYPE; 4 5 v_sal emp.sal%TYPE; 6 7 CURSOR c_cursor IS SELECT empno, sal FROM emp; 8 9 BEGIN 10 11 OPEN c_cursor; 12 13 LOOP 14 15 FETCH c_cursor INTO v_empno, v_sal; 16 17 EXIT WHEN c_cursor %NOTFOUND; 18 19 IF v_sal<=1200 THEN 20 21 UPDATE emp SET sal=sal+50 WHERE empno=v_empno; 22 23 DBMS_OUTPUT.PUT_LINE(‘编码为‘||v_empno||‘工资已更新!‘); 24 25 END IF; 26 27 DBMS_OUTPUT.PUT_LINE(‘记录数:‘|| c_cursor %ROWCOUNT); 28 29 END LOOP; 30 31 CLOSE c_cursor; 32 33 END;
游标的FOR循环
FOR index_variable IN cursor_name[value[, value]…] LOOP
-- 游标数据处理代码
END LOOP;
例:
1 DECLARE 2 3 CURSOR c_sal IS SELECT empno, ename, sal FROM emp ; 4 5 BEGIN 6 7 --隐含打开游标 8 9 FOR v_sal IN c_sal LOOP 10 11 --隐含执行一个FETCH语句 12 13 DBMS_OUTPUT.PUT_LINE( to_char(v_sal.empno)||’---‘||v_sal.ename||’---‘||to_char(v_sal.sal)) ; 14 15 --隐含监测c_sal%NOTFOUND 16 17 END LOOP; 18 19 --隐含关闭游标 20 21 END;
SELECT FOR UPDATE 游标
游标修改和删除操作是指在游标定位下,修改或删除表中指定的数据行。这时,要求游标查询语句中必须使用FOR UPDATE选项
SELECT . . . FROM … FOR UPDATE [OF column[, column]…] [NOWAIT]
例: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;
游标变量
与游标一样,游标变量也是一个指向多行查询结果集合中当前数据行的指针。但与游标不同的是,游标变量是动态的,而游标是静态的。游标只能与指定的查询相连,即固定指向一个查询的内存处理区域,而游标变量则可与不同的查询语句相连,它可以指向不同查询语句的内存处理区域(但不能同时指向多个内存处理区域,在某一时刻只能与一个查询语句相连),只要这些查询语句的返回类型兼容即可。
游标变量为一个指针,它属于参照类型,所以在声明游标变量类型之前必须先定义游标变量类型。
TYPE ref_type_name IS REF CURSOR [ RETURN return_type] (强[弱]游标变量)
例:声明两个强类型定义游标变量和一个弱类型游标变量
1 DECLARE 2 3 TYPE deptrecord IS RECORD( 4 5 Deptno dept.deptno%TYPE, 6 7 Dname dept.deptno%TYPE, 8 9 Loc dept.loc%TYPE ); 10 11 TYPE deptcurtype IS REF CURSOR RETURN dept%ROWTYPE; 12 13 TYPE deptcurtyp1 IS REF CURSOR RETURN deptrecord; 14 15 TYPE curtype IS REF CURSOR; 16 17 Dept_c1 deptcurtype; 18 19 Dept_c2 deptcurtyp1; 20 21 Cv curtype;
打开游标变量 :打开游标变量时使用的是OPEN…FOR 语句
提取游标变量数据 :
关闭游标变量 :
例:强类型参照游标变量类型
1 DECLARE 2 3 TYPE emp_job_rec IS RECORD( 4 5 Employee_id emp.empno%TYPE, 6 7 Employee_name emp.ename%TYPE, 8 9 Job_title emp.job%TYPE); 10 11 TYPE emp_job_refcur_type IS REF CURSOR RETURN emp_job_rec; 12 13 Emp_refcur emp_job_refcur_type ; 14 15 Emp_job emp_job_rec; 16 17 BEGIN 18 19 OPEN emp_refcur FOR 20 21 SELECT empno, ename, job FROM emp ORDER BY deptno; 22 23 FETCH emp_refcur INTO emp_job; 24 25 WHILE emp_refcur%FOUND LOOP 26 27 DBMS_OUTPUT.PUT_LINE(emp_job.employee_id||’: ‘||emp_job.employee_name||‘ is a ’||emp_job.job_title); 28 29 FETCH emp_refcur INTO emp_job; 30 31 END LOOP; 32 33 END;
例:弱类型参照游标变量类型
1 DECLARE 2 3 Type refcur_t IS REF CURSOR; 4 5 Refcur refcur_t; 6 7 TYPE sample_rec_type IS RECORD ( 8 9 Id number, 10 11 Description VARCHAR2 (30) ); 12 13 sample sample_rec_type; 14 15 selection varchar2(1) := UPPER (SUBSTR (‘&tab’, 1, 1)); 16 17 BEGIN 18 19 IF selection=’D’ THEN 20 21 OPEN refcur FOR SELECT deptno, dname FROM dept; 22 23 DBMS_OUTPUT.PUT_LINE(‘Department data’); 24 25 ELSIF selection=’E’ THEN 26 27 OPEN refcur FOR SELECT empno, ename||’ is a ‘||job FROM emp; 28 29 DBMS_OUTPUT.PUT_LINE(‘Employee data’); 30 31 ELSE 32 33 DBMS_OUTPUT.PUT_LINE(‘Please enter ‘‘D’’ or ‘‘E’’ ’); 34 35 RETURN; 36 37 END IF; 38 39 DBMS_OUTPUT.PUT_LINE(‘----------------------‘); 40 41 FETCH refcur INTO sample; 42 43 WHILE refcur%FOUND LOOP 44 45 DBMS_OUTPUT.PUT_LINE(sample.id||’: ‘||sample.description); 46 47 FETCH refcur INTO sample; 48 49 END LOOP; 50 51 CLOSE refcur; 52 53 END;