1游标简介
当用户执行数据库查询操作时,数据库会将满足指定查询条件的数据以数据表的方式返回给用户,而如果用户需要对返回结果的每一行数据进行操作,就必须依靠游标来完成。
注意点:数据量较大时,使用游标会降低性能,所以使用时要综合来考虑。
Oracle数据库游标分类:静态游标和REF游标。其中静态游标分为:隐式游标、显示游标。
2隐式游标
2.1定义
在PL/SQL块中所编写的每条sql语句都是隐式游标。
2.2 使用
DECLARE
v_empRow myemp%ROWTYPE;
BEGIN
SELECT * INTO v_empRow FROM myemp WHERE empno=7369;
IF SQL%FOUND THEN
dbms_output.put_line('ename='||v_empRow.ename||',job='||v_empRow.job);
dbms_output.put_line('操作的行数为:'||SQL%ROWCOUNT);
END IF;
END;
运行结果为:ename=SMITH,job=CLERK
操作的行数为:1
以上脚本中, SQL%ROWCOUNT是记录操作的行数,SQL%FOUND是判断是否有数据。详细情况如下:
属性 | 描述 |
---|---|
%FOUND | 当用户使用DMl操作时,该属性返回TRUE |
%ISOPEN | 判断游标是否打开,该属性对任何的隐私游标总是返回FALSE,表示已经打开 |
%NOTFOUND | 如果执行DML操作时没有返回的数据行,则返回TRUE,否则返回FALSE |
%ROWCOUNT | 返回更新操作的行数或SELECT INTO 返回的行数 |
3显示游标
3.1定义
显示游标是指在声明块中直接定义的游标。
语法:CURSOR 游标名称 [RETURN 返回值类型] IS 子查询 [FOR UPDATE [OF 数据列,数据列,][NOWAIT]];
3.2使用
显示游标操作步骤可大致为4步:
1、声明游标:使用CURSOR定义
2、打开游标:使用OPEN操作
3、使用游标:使用循环和FETCH...INTO操作
4、关闭游标:使用CLOSE操作
3.3举例
定义显示游标,以myemp表举例。
DECLARE
CURSOR cur_emp IS SELECT * FROM myemp;
v_empRow myemp%ROWTYPE;
BEGIN
IF cur_emp%ISOPEN THEN --游标已经打开
NULL;
ELSE --游标未打开
OPEN cur_emp;
END IF;
FETCH cur_emp INTO v_empRow; --取游标当前行数据
WHILE cur_emp%FOUND LOOP
dbms_output.put_line(cur_emp%ROWCOUNT || '/ename=' || v_empRow.ename || ',sal=' || v_empRow.sal);
FETCH cur_emp INTO v_empRow; --把游标指向下一行
END LOOP;
CLOSE cur_emp;
END;
运行结果:
显示游标属性与隐式游标是有区别的。如下:
属性 | 描述 |
---|---|
%FOUND | 光标打开后未曾执行FETCH,则值为NULL;如果最近一次在该光标上执行的FETCH返回一行,则值为TRUE,否则为FALSE |
%ISOPEN | 如果光标是打开状态,则值为TURE,否则为FALSE |
%NOTFOUND | 如果该光标最近一次FETCH语句没有返回行,则值为TURE;否则为FALSE。如果光标刚刚打开还未执行,则值为NULL |
%ROWCOUNT | 其值为在该光标到目前为止执行FETCH语句所返回的行数。光标打开时,初始值为0,每执行一次FETCH如果返回一行则值增加1 |
4 REF游标
4.1定义
在定义游标时不绑定具体的查询,而是动态的打开指定类型的查询。
语法:TYPE 游标变量类型名称 IS REF CURSOR [RETURN 数据类型];
4.2使用
DECLARE
TYPE mydept_ref IS REF CURSOR RETURN mydept%ROWTYPE; --定义游标类型
cur_mydept mydept_ref;
v_deptRow mydept%ROWTYPE;
BEGIN
OPEN cur_mydept FOR SELECT * FROM mydept;
LOOP
FETCH cur_mydept INTO v_deptRow;
EXIT WHEN cur_mydept%NOTFOUND; --如果没有数据则退出
dbms_output.put_line('dname='||v_deptRow.dname||',loc='||v_deptRow.loc);
END LOOP;
CLOSE cur_mydept;
END;
运行结果: