oracle 游标的管理

8.2.1游标的概念和类型

游标(CURSOR)存储于服务器端,当服务器执行了一个查询后,查询返回的记录集存放在光标中,通过光标上的操作可以把这些记录检索到客户端的应用程序。光标是一种变量,它对应于一个查询语句确定的结果集。它用于逐行处理表中的数据。游标必须在plsql块的declare部分声明光标(光标),与定义局部变量在同一个位置。

游标中包含一个数据行指针用来指向当前数据行

打开游标时指针指向第一行,使用 FETCH ... INTO 语句后指向下一行。

指针指到最后一条记录为止(实际上指针最后一条记录之后是不存在的为空,这里只是表示遍历完所有数据),此时游标的%FOUND属性值为FALSE。

游标分为显示游标、隐式游标、REF游标。

8.2.2显示游标

显示游标是用户声明和操作的一种游标,通常用于操作查询结果集(查询语句返回的查询结果)

显示游标的格式如下:

cursor 游标名(游标输入参数)

is select 语句

使用游标的过程格式如下:

--打开游标

OPEN cursor name;

--提取数据

FETCH cursor_name INTO variable1,variable...;

--关闭游标

CLOSE cursor name;

显示游标有4个属性:

%ISOPEN :游标打开。

%FOUND:变量最后从游标中获取记录的时候,在结果集中找到了记录。

%NOTFOUND :变量最后从游标中获取记录的时候,在结果集中没有找到记录。

%ROWCOUNT :返回到目前为止,已经从游标缓冲区中提取到数据的行数。

【例8-4】定义一个和表 sm_emp结构一致的游标,并输出职工姓名和工资。

具体代码如下:

--第八章\yb.sql

---建立职工工资表

create table SM_EMP

(

empid VARCHAR2(30),

name VARCHAR2(30),

salary NUMBER(6,2),

telno CHAR(8)

)

--插入数据

Insert into SM_EMP

select '1101','王海',3500,'8863976' from dual;

Inser into SM_EMP

select '1135','孙宁',5000,'8563923' from dual;

Inser into SM_EMP

select '1236','张欣',8000,'8763125' from dual;

commit;

--建立存储过程,取出游标的数据

create or replace procedure pro_curortest

is

V_ename VARCHAR2(30);

V_salary number(6,2);

CURSOR c_emp IS SELECT name,salary FROM sm_emp;

BEGIN

OPEN c_emp;

LOOP

FETCH c_emp INTO v_ename,v_salary;

--将游标中的字段的值fetch到变量中

EXIT WHEN c_emp%NOTFOUND;

--当游标中没有数据时跳出loop

DBMS_OUTPUT.PUT_LINE ('Sal of Employee ' || v_ename

|| ' is '|| v_salary);

END LOOP;

CLOSE c_emp;

END;

执行后,结果如图8-4所示。

图8-4使用游标显示表中数据。

游标中可以定义参数,游标参数只能指定数据类型,而不能指定长度。

【例8-5】定义一个和表 sm_emp结构一致的游标,该游标有如数参数职工号。根据

输入的职工号输出对应职工姓名。

建立存储过程代码如下:

--第八章\yb.sql

create or replace procedure pro_cursorcs

is

cursor emp_cursor(no number) is select name from SM_EMP where empid=no;

v_ename SM_EMP.name%type;

begin

open emp_cursor('1135');

loop

fetch emp_cursor into v_ename;

exit when emp_cursor%notfound;

dbms_output.put_line(v_ename);

end loop;

close emp_cursor;

end;

执行后,结果如图8-5所示。

图8-5输出职工工资表的姓名。

使用游标处理结果集时,可以配合使用FOR语句来完成。使用FOR语句遍历游标中的数据时,可以把它的计时器看做一个自动的RECORD类型变量,

FOR循环是为了简化游标使用过程而设计的。使用游标FOR循环检索游标时,游标的打开、数据提取、数据是否检索到的判断与游标的关闭都是Oracle系统自动进行的。

【例8-6】使用for 循环建立游标,求出职工工资表所有员工的总薪水。

建立存储过程代码如下:

--第八章\yb.sql

create or replace procedure pro_forcursor

Is

---定义游标

CURSOR c_emp IS

SELECT name,salary

FROM sm_emp

ORDER BY name;

v_tot_sal NUMBER (10,2);

BEGIN

v_tot_sal :=0;

--游标for循环,求出雇员的工资总数。

FOR r_emp IN c_emp LOOP

DBMS_OUTPUT.PUT_LINE ('Name:' || r_emp.name ||'salary:' || r_emp.salary);

v_tot_sal :=v_tot_sal +r_emp.salary;

END LOOP;

DBMS_OUTPUT.PUT_LINE ('Total salary is'||v_tot_sal);

END;

执行后,结果如图8-6所示。

图8-6输出职工总的工资。

8.2.3隐性游标

对于非查询语句,如修改、删除操作,由Oracle 系统自动为这些操作设置游标并创建其工作区,这些由系统隐含创建的游标称为隐性游标,隐性游标的名字为SQL,这是由Oracle 系统定义的。

对于隐性游标的操作,如定义、打开、取值及关闭操作,都由Oracle 系统自动地完成,无需用户进行处理。用户只能通过隐式游标的相关属性,来完成相应的操作。

【例8-7】删除职工工资表中工号1101的记录,然后输出该语句影响的行数。

匿名块代码如下:

--第八章\yb.sql

declare

num int:=0;

begin

delete from sm_emp where empid='1101';

if sql%notfound then

dbms_output.put_line('该行数据没有发现');

else

dbms_output.put_line('数据被发现并删除,影响的行数为:'||sql%rowcount);

end if;

end;

执行后,结果如图8-7所示。

图8-7输出结果影响的行数

8.2.4ref 游标

ref游标:动态关联结果集的临时对象,即在运行的时候动态决定执行查询。

ref游标主要分为两类,强类型和弱类型的,强类型的为带有RETURN语句的REF动态游标,弱类型为不带有RETURN语句的REF动态游标。

定义REF动态游标类型,格式如下:

TYPE <类型名> IS REF CURSOR

RETURN <返回类型>;

打开REF动态游标,格式如下:

OPEN <游标名> FOR <查询语句>

【例8-8】建立包,在该包中定义ref游标。然后建立存储过程 list,如果输入参数为1,则返回职工表数据,如果为其他值,则返回部门表数据。

建立职工表和部门表,插入数据代码如下:

--第八章\yb.sql

create table SM_EMP

(

empid VARCHAR2(30),

name VARCHAR2(30),

salary NUMBER(6,2),

telno CHAR(8)

);

--插入数据

insert into SM_EMP

select '021101','王海',3500,'8863976' from dual;

insert into SM_EMP

select '031135','孙宁',5000,'8563923' from dual;

insert into SM_EMP

select '041236','张欣',8000,'8763125' from dual;

commit;

create table department

(bmbh varchar2(10),

bmmc varchar2(20));

insert into department

select '1101','人力资源' from dual;

insert into department

select '1201','物流' from dual;

insert into department

select '1501','企业管理部' from dual;

commit;

建立一个包,在该包中定义一个ref游标,代码如下:

CREATE OR REPLACE PACKAGE globalPkg AUTHID CURRENT_USER AS

TYPE result_set IS REF CURSOR;

END globalPkg;

建立存储过程,代码如下:

create or replace procedure list(result_set in out sys_refcursor, which in number)

is

begin

--打开动态游标时在为它指定查询语句

--1就是返回员工表,其他就返回部门表

if which=1 then

open result_set for select * from sm_emp;

else

open result_set for select * from department;

end if;

end;

执行后,如果输入1,结果如图8-8所示。

图8-8显示职工表数据

执行后,如果输入2,如图8-9所示。

相关推荐
西门吹雪分身33 分钟前
Redis之RedLock算法以及底层原理
数据库·redis·算法
一代...33 分钟前
【redis】初识redis
数据库·redis·缓存
clarance201538 分钟前
MCP技术革命:元控制协议如何重构AI与数据库的交互范式
数据库·人工智能·重构
Arbori_262151 小时前
Oracle REGEXP_SUBSTR
数据库·oracle
solihawk1 小时前
国产数据库与Oracle数据库事务差异分析
数据库·oracle
·云扬·1 小时前
【BUG】Redis RDB快照持久化及写操作禁止问题排查与解决
数据库·redis·bug
橘猫云计算机设计1 小时前
基于django云平台的求职智能分析系统(源码+lw+部署文档+讲解),源码可白嫖!
数据库·spring boot·后端·python·django·毕业设计
babytiger2 小时前
Ubuntu2404装机指南
数据库·postgresql
镜舟科技2 小时前
如何高效使用 Text to SQL 提升数据分析效率?四个关键应用场景解析
数据库·sql·数据分析
King.6243 小时前
数据服务化 VS 数据中台:战略演进中的价值重构
大数据·数据库·sql·oracle·重构