oracle-游标总结
本篇文章最开始会介绍一些游标相关的定义,可以简单看下,看不懂也没有关系,下面会有实例来一一解释。
什么是游标
在pl/sql块中执行select update delete insert语句的时候,oracle会在内存中为其分配上下文,即一个缓冲区。游标就是指向该区的一个指针,或是命名一个工作区,或是一种结构化数据类型,它为应用程序提供了一种对多行数据查询结果集中的每一行数据进行单独处理的方法。
游标的应用场景
我们在java里经常会有如下的操作,从数据库中查出来一些数据,放入一个list中,之后后台循环这个list,并从list中取值用于它用,那么场景变换到oracle中呢?这时候就要用到了游标,关于游标的定义,很繁琐,不容易理解,好奇的小伙伴可以自行百度搜索一下,我这里说下我的理解,游标在oracle里就类似于一个list,我们通过oracle中的for循环的方式,去从游标里取值操作,或者通过游标的循环来操作,这就是游标的应用。
游标的分类
游标可以分为显式游标和隐式游标。
显式游标
1. 声明游标:主要包括游标名称和为游标提供结果集的select语句。cursor...is...
2. 打开游标:在游标声明之后,必须打开才能使用。其实就是执行定义的select语句,执行之后,将查询结果加入内存中,游标停在查询结果的首部,注意不是第一行。open...
3. 读取游标:当打开一个游标之后,就可以读取游标中的数据了,读取游标就是逐行将结果集中的数据保存到变量中。fetch...into
4. 关闭游标:当所有的结果集都被检索之后,游标就应该被关闭,与游标相关联的资源可以被释放了。close...
隐式游标
在执行sql语句的时候,oracle会自动创建一个隐式游标。这个游标是内存中处理该语句的工作区域。
游标的属性
无论是显式游标还是隐式游标,都具有%found,%notfound,%rowcount,%isopen 四个属性,通过这四个属性可以获知sql语句的执行结果以及该游标的状态信息,它们描述与游标操作相关的DML语句的执行情况。游标属性只能用在plsql的流程控制语句内,不能用在sql语句内。注意:当使用隐形游标的属性时,需要在属性的前面加上隐式游标的默认名称-SQL。
1. %found:布尔型属性,(是否找到游标)如果sql语句至少影响到一行数据,则该属性为true,否则为false
2. %notfound:布尔型属性,(是否没找到游标)与%found属性功能相反。
3. %rowcount:数字型属性,(游标行数)返回受sql语句影响的行数。也可以理解成游标抽取过的记录行数。
4. %isopen:布尔型属性,(游标是否打开)当游标已经打开时返回true,游标关闭时返回false。隐性游标总为true,因此隐性游标中不用打开和关闭游标,也不用检查其打开状态。
5. 参数化游标:定义游标的时候,可以带上参数
游标的变量
上面所讲的游标都是与一个已知的sql语句关联,也就是静态的,但是游标变量可以在运行时与不同的语句关联,是动态的,游标变量被用于处理多行的查询结果集。游标变量不同于特定的查询绑定,而是在打开游标时才能确定所对应的查询。因此游标变量可以一次对应多个查询。使用游标变量之前,必须先声明,然后在运行时必须为其分配存储空间。
1. 游标变量的声明:type <变量名> is ref cursor return <返回类型>
2. 游标变量的打开:open <游标变量> for <select语句>
3. 游标变量的关闭:跟静态游标一样 close
说了这么多,可能对于一些刚接触游标来说的伙伴们还是无法理解,那么就让我们写个例子来深入理解一下什么是游标吧。
下面这个例子是在存储过程里使用游标,对于存储过程不熟悉的可以先看我写的关于oracle存储过程的讲解部分,之后再回来学习。
首先我们需要创建一个表用作测试,表名T_USER,数据库中随意添加几条数据。
下面看这个例子。
fetch into循环游标
功能是:从t_user表中取出id,name,age数据,分别输出到控制台。
1 create or replace procedure test1 as--定义一个存储过程 名字叫做test1 无参数 2 cursor test1_cursor is select id,name,age from t_user;--声明显式游标 游标的名字是test1_cursor 3 v_id t_user.id%type;--定义一个变量 名字是v_id 类型是表t_user里的id的类型 4 v_name t_user.name%type; 5 v_age t_user.age%type; 6 begin 7 open test1_cursor;--打开游标 8 loop 9 fetch test1_cursor into v_id,v_name,v_age;--从游标中抓取出来放在后面这三个变量中 10 exit when test1_cursor%notfound;--当游标中没有数据了,退出 11 dbms_output.put_line('id='||v_id||' name='||v_name||' age='||v_age);--输出语句 输出三个值 12 end loop; 13 close test1_cursor;--关闭 14 end test1;
结果是:
for循环游标
1 create or replace procedure test2 as--定义一个存储过程 名字叫做test2 无参数 2 cursor test2_cursor is select id,name,age from t_user;--声明显式游标 游标的名字是test2_cursor 3 begin 4 for test1_cur in test2_cursor loop 5 dbms_output.put_line('id='||test1_cur.id||' name='||test1_cur.name||' age='||test1_cur.age);--输出语句 输出三个值 6 end loop; 7 end test2;
for循环的好处
1. 使用for循环不需要关注游标是否打开或关闭。
2. for循环会自动将数据fetch到记录型变量。
3. for循环不需要关注何时要退出,也就是不需要写退出满足条件。遍历完成就会退出。
此外还有while循环,感兴趣的可以百度查一下。
持续更新!!