暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

oracle存储过程简单入门(五)-游标(cursor)的学习

软件实施干货分享 2020-07-29
1409

一、游标(Cursor)的定义与作用:

  游标是SQL的一个内存工作区,由系统或用户以变量的形式定义。游标的作用就是用于临时存储从数据库中提取的数据块。在某些情况下,需要把数据从存放在磁盘的表中调到计算机内存中进行处理,最后将处理结果显示出来或最终写回数据库。这样数据处理的速度才会提高,否则频繁的磁盘数据交换会降低效率。 

二、游标(Cursor)的应用场景

  游标既然像查询结果集list ,那使用cursor 的情况,肯定会有下边这两种情况,才可能使用到cursor :

需要依据查询到的结果集,作为条件,进行下一步的查询。

需要在结果集某个位置上,满足某种条件时,对数据进行不同的修改。

三、游标(Cursor)的类别

 游标有两种,显示游标和隐式游标。

在每个用户会话中,可以同时打开多个游标,其数量由数据库初始化参数文件中的OPEN_CURSORS参数定义。
对于不同的SQL语句,游标的使用情况不同:

SQL语句

游标

非查询语句

隐式的

结果是单行的查询语句

隐式的或显示的

结果是多行的查询语句

显示的

隐式游标: 

  上一篇中用到的SELECT…INTO…查询语句,一次只能从数据库中提取一行数据,对于这种形式的查询和DML操作,系统都会使用一个隐式游标。 对于隐式游标的操作,如定义、打开、取值及关闭操作,都由ORACLE 系统自动地完成,无需用户进行处理。用户只能通过隐式游标的相关属性,来完成相应的操作。在隐式游标的工作区中,所存放的数据是与用户自定义的显示游标无关的、最新处理的一条SQL 语句所包含的数据。


DML操作和单行SELECT语句会使用隐式游标,它们是:

插入操作:INSERT。

更新操作:UPDATE。

删除操作:DELETE。

单行查询操作:SELECT … INTO …


当然,隐式游标还有一种写法,如下,并没有定义游标:

create or replace procedure test_cryptic_procedure
as
begin
for cryptic_rec in (
select * from ly_ds
)
loop
dbms_output.put_line('名称:'||cryptic_rec.ly_mc||' 年龄:'||cryptic_rec.ly_nl);
end loop;
end;
复制

 如下方式执行:

set serveroutput on;
begin
test_cryptic_procedure;
end;
复制

将会看到如下的结果:

匿名块已完成
名称:eee 年龄:23
名称:王五 年龄:22
名称:赵六六 年龄:29
名称:李四 年龄:20
复制

显式游标: 

  显示游标还分为静态游标和动态游标 。显示游标的写法会在存储过程中定义Cursor ,并且一般都有固定的四个步骤:声明游标 、打开游标 、提取数据 、关闭游标 。显式游标打开后,必须显式地关闭。游标一旦关闭,游标占用的资源就被释放,游标变成无效,必须重新打开才能使用。 

  隐式游标其实默认已经打开游标,并在执行完成后关闭游标释放资源。显式游标主要是用于对查询语句的处理,尤其是在查询结果为多条记录的情况下; 

显示游标(Cursor)的例子
create or replace procedure test_select3_procedure
(sex varchar)
AS
--游标的定义
Cursor test_cursor is
select id,ly_mc,LY_NB,ly_nl from ly_ds where LY_NB=sex;
cur test_cursor%rowtype; --游标的类型,我理解类似于list的泛型
BEGIN
for cur in test_cursor loop
exit when test_cursor%notfound;
dbms_output.put_line('数据是:'||cur.id||'_'||cur.ly_mc||'_'||cur.LY_NB||'_'||cur.ly_nl);
end loop;
END;
复制

上边,首先看Cursor test_cursor is 这一行,它的意思是定义一个游标,test_cursor 为你要定义的名字,而is 后边是一个sql,也就是说当前这个sql的查询结果,赋值给游标test_cursor 。 

  然后,往下,接着cur test_cursor%rowtype ,这个是定义了一个类型,而这个类型,即是游标test_cursor 的返回结果类型,类型的名字为cur 。有点类似于java语言 中List 集合中的一个泛型 。 

  另外,关于for 是一个循环的写法,for cur in test_cursor ,即,从游标test_cursor 中取出一个结果cur 。 

  还有,注意,loop 和end loop 这是一个循环的开始标志和结束标志,但它俩兄弟是一个很执着的循环,如果没有定义退出条件,永远不会退出的,所以在上边的循环里边,有了退出条件exit when test_cursor%notfound; ,即当游标test_cursor 中没有数据了,就退出循环。 

  当然loop 循环的退出,发生下边的情况,才能退出:

①有exit,并满足条件后退出。

②loop中抛出了异常。

③存在goto 标识。

  最后,可能大家注意到,上边并没有显示游标中一定有的四个步骤, 

声明游标 、打开游标 、提取数据 、关闭游标 ,那是因为for 循环这样的遍历会自动给我们打开游标,并在结束后关闭游标,下边会学习其他的遍历方法,但是都没有for 这样智能,所以觉得for 循环游标,是个很好的选择。

  执行上边的存储过程:

set serveroutput on;
execute test_select3_procedure('女');
复制

会得到如下的遍历结果,正是我根据条件
查询到的结果集。

PROCEDURE TEST_SELECT3_PROCEDURE 已编译
匿名块已完成
数据是:2_王五_女_22
数据是:3_赵六六_女_29
数据是:4_李四_女_20
复制

参考链接:

https://blog.csdn.net/wohaqiyi/article/details/81607172

文章转载自软件实施干货分享,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论