游标是为处理这些语句而分配的一大块内存
游标的一个常见的用法是保存查询结果以备以后使用
一个游标结果集是通过执行SELECT 查询来建立的
数据库游标允许你选择一组数据,通过翻阅这组数据记录(通常被称为数据集),检查每一个游标所在的特定的行。
游标的分类:
静态游标
显式游标 (explicit cursor)
隐式游标 (implicit cursor)
REF游标(即游标变量)
显式游标是由用户显式声明的游标
显式游标的操作有声明(declare),使用前的打开(open),使用,使用后的关闭(close)四部分
SET SERVEROUT ON
DECLARE
v_ename EMP.ENAME%TYPE;
v_salary EMP.SAL%TYPE;
CURSOR c_emp IS SELECT ename,sal FROM emp;
BEGIN
OPEN c_emp;
FETCH c_emp INTO v_ename,v_salary;
DBMS_OUTPUT.PUT_LINE('Salary of Employee '|| v_ename ||' is '|| v_salary);
FETCH c_emp INTO v_ename,v_salary;
DBMS_OUTPUT.PUT_LINE('Salary of Employee '|| v_ename ||' is '|| v_salary);
FETCH c_emp INTO v_ename,v_salary;
DBMS_OUTPUT.PUT_LINE('Salary of Employee '|| v_ename ||' is '|| v_salary);
CLOSE c_emp;
END;
/
显式游标的属性:
%FOUND 如果最近最后一次从当前游标中抽取出数据,则返回TRUE;否则返回FALSE
%NOTFOUND 与%FOUND相反
%ROWCOUNT 当前总共已抽取的记录数
%ISOPEN 如果游标已经打开,则返回TRUE;否则返回FALSE
v_ename EMP.ENAME%TYPE;
v_salary EMP.SAL%TYPE;
CURSOR c_emp IS SELECT ename,sal FROM emp;
BEGIN
OPEN c_emp;
LOOP
FETCH c_emp INTO v_ename,v_salary;
EXIT WHEN c_emp%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('Salary of Employee '|| v_ename ||'is' ||v_salary);
END LOOP;
CLOSE c_emp;
END;
/
PL/SQL为所有SQL数据操纵语句(包括返回一行的查询)隐式声明游标
不能对一个SQL游标(隐式游标)显式的执OPEN, CLOSE和FETCH语句
Oracle会自动的为隐式游标 --打开SQL游标、处理SQL游标、然后再关闭该游标
%FOUND 如果DML语句影响一行或多行,则与该条语句配套的隐式游标的%FOUND属性返回TRUE,否则返回FALSE
%NOTFOUND 与%FOUND相反
%ROWCOUNT 统计DML语句返回的行数
%ISOPEN 隐式游标关联的SQL语句执行完后,ORACLE自动关闭该游标。因此,%ISOPEN属性的值始终为FALSE
BEGIN
DELETE FROM EMP WHERE DEPTNO=40;
IF sql%NOTFOUND THEN
DBMS_OUTPUT.PUT_LINE('未找到值');
ELSE
DBMS_OUTPUT.PUT_LINE('共删除' || sql%ROWCOUNT || '行');
END IF;
END;
/
REF游标可在运行时与不同的查询相关联
REF游标也可称为游标变量
声明一个引用游标类型,语法如下:
TYPE <type name> IS REF CURSOR [RETURN <record type>]
使用REF游标
DECLARE
TYPE RefCur IS REF CURSOR RETURN dept%rowtype;
Cur1 RefCur;
BEGIN
open Cur1 for select * from dept;
close Cur1;
--error,Cur1中的结果集结构必须是dept%rowtype
--open Cur1 for select * from emp;
close Cur1;
END;
带参数的游标:可以将参数传递给游标并在查询中使用
CURSOR cursor_name[(parameter[,parameter],...)]
IS select_statement;
游标中的更新和删除
CURSOR c1 IS
SELECT empno,sal FROM emp WHERE comm IS NULL
FOR UPDATE OF comm; -- 所更新的列名
v_comm NUMBER(10,2);
BEGIN
FOR r1 IN c1 LOOP
IF r1.sal<500 THEN
v_comm:=r1.sal*0.25;
ELSE
v_comm:=r1.sal*0.20;
END IF;
UPDATE emp
SET comm=v_comm
WHERE CURRENT OF c1;
END LOOP;
END;
/