光标
为了出来sql语句 , Oracle分配一个上下文区域,用于处理所需的信息,
而光标就是指向上下问的句柄或指针、用于控制上下文区和控制处理语句时,上下文区发生的事情
一、显示光标(游标)
1、 在PL/SQL中的定义的光标就是显示光标,需要手动open、fetch、close
步骤
A、 cursor 光标名称 is select 语句
B、open 光标名称
C、fetch 光标名称 into 变量列表
D、 close 光标
2、 示例代码
CREATE OR REPLACE PROCEDURE sp_cursor
AS
CURSOR x IS SELECT ename,sal FROM emp;
v_name emp.ename%TYPE;
v_sal emp.sal%TYPE;
BEGIN
OPEN x ;
FETCH x INTO v_name,v_sal;
WHILE x%FOUND
LOOP
dbms_output.put_line(v_name||' '||v_sal);
FETCH x INTO v_name,v_sal;
END LOOP;
END;
3、光标的属性
%FOUND 当最近一次读取记录成功时,返回true
%NOTFOUND 与 %FOUND恰好相反
%isopen 当光标打开时返回true
%rowcount 返回已从光标的记录数
4、参数化光标
(1) 在声明光标的时候,让光标名称带上参数、在使用的时候才将具体的值即(实参)赋给查询语句当做查询条件
(2)示例代码
CREATE OR REPLACE PROCEDURE sp_cursor1
AS
CURSOR c(dno NUMBER) IS
SELECT * FROM emp WHERE emp.deptno = dno;
BEGIN
FOR x IN c(10)
LOOP
dbms_output.put_line(x.ename||' '||x.sal);
END LOOP;
END;
二、隐式光标
所有的sql语句在上下文区域都能够执行,所以每一个sql都有一个光标指向上下文区域,此光标就是
称为sql光标,sql光标不用手工打开,fetch和关闭。
---根据员工部门编号查询并输出姓名
---特点:可能无数据(返回0行)或者数据太多(返回多行)
CREATE OR REPLACE PROCEDURE pro_excep
AS
v_name emp.ename%TYPE;
BEGIN
SELECT ename INTO v_name FROM emp
WHERE emp.deptno=10;
dbms_output.put_line('ename:'||v_name);
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line('数据没有找到');
WHEN too_many_rows THEN
dbms_output.put_line('数据过多');
WHEN OTHERS THEN
dbms_output.put_line('查询失败');
END;
DML操作和单行SELECT语句会使用隐式游标,它们是:
* 插入操作:INSERT。
* 更新操作:UPDATE。
* 删除操作:DELETE。
* 单行查询操作:SELECT ... INTO ...
三、光标循环
1、简单循环可以用loop和end loop实现(但是必须说明循环跳转的语句,不然会很容易出现无限循环的语句)
2、while循环、当条件满足时,再执行循环
3、光标for循环
可以控制次数
4、select for update 光标
四、光标变量
1、光标变量是一种引用类型,在使用时给他分配内存空间
exec sql allcate :variable
五、动态SELECT语句和动态游标的用法
定义动态游标类型的语句如下:
A、TYPE 游标类型名 REF CURSOR;
B、 声明游标变量的语句如下:
C、 游标变量名 游标类型名;
D、 在可执行部分可以如下形式打开一个动态游标:
E、 OPEN 游标变量名 FOR 查询语句字符串;
示例代码:
declare
type cur_type is ref cursor;
cur cur_type;
rec scott.emp%rowtype;
str varchar2(50);
letter char:= 'A';
begin
loop
str:= 'select ename from emp where ename like ''%'||letter||'%''';
open cur for str;
dbms_output.put_line('包含字母'||letter||'的名字:');
loop
fetch cur into rec.ename;
exit when cur%notfound;
dbms_output.put_line(rec.ename);
end loop;
exit when letter='Z';
letter:=chr(ascii(letter)+1);
end loop;
end;