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所示。

相关推荐
白鲸开源8 小时前
(二)从分层架构到数据湖仓架构:数据仓库分层下的技术架构与举例
大数据·数据库·数据分析
好玩的Matlab(NCEPU)8 小时前
Redis vs RabbitMQ 对比总结
数据库·redis·rabbitmq
21号 18 小时前
16.MySQL 服务器配置与管理
服务器·数据库·mysql
我的offer在哪里8 小时前
MongoDB
数据库·mongodb
练习时长一年10 小时前
AI开发结构化输出
数据库
IvorySQL10 小时前
灾难恢复工具内核细节探究与分享
数据库·postgresql·开源
lypzcgf10 小时前
商城小程序数据库表结构文档
数据库·小程序·电商
jjw_zyfx11 小时前
Ubuntu上vue3 vite使用MBTiles搭建地图服务器
服务器·数据库·ubuntu
EndingCoder11 小时前
Node.js SQL数据库:MySQL/PostgreSQL集成
javascript·数据库·sql·mysql·postgresql·node.js
静听山水12 小时前
SQLite
数据库·sqlite