oracle中的cursor属性有哪些,Oracle学习11:游标(cursor)--显式游标隐式游标、游标四个属性、循环遍历...
1.概述
上文PLSQL学习中提到的知识,可以发现,基本都可以通过Java等语言实现,而为了实现程序的可移植性,实际开发工作中我们也是如此做的。
那么PLSQL的重点是什么呢?接下来我们来介绍游标cursor的概念。
之前提到,在不使用显式游标的情况下,PLSQL的中select语句只能返回一条记录,那么我们如果想要返回多条记录,或者遍历整个结果集该如何实现呢。
这里我们可以通过cursor实现。
1.1 cursor是什么
cursor是光标,游标的意思。比如我们的鼠标的光标就是cursor。
那么在数据库中cursor是什么呢?
当运行DML(select,update,insert,delete)语句时,ORACLE会在内存中为其分配缓冲区(Context Area),PL/SQL打开一个内建游标并处理结果,游标是维护查询结果的内存中的一个区域。
游标在运行DML语句时打开,完成后关闭。
通俗的说:
我们知道,select语句会产生一个结果集,而游标是指在这个结果集上的第一条记录的一个指针。
而我们每次取出(fetch)一条记录,cursor就会自动指向下一条记录。
如果学过Java的话,可以这样理解,cursor类似于Java中的迭代器iterator。
1.2 cursor作用
基于以上的理解,cursor自然就被用于:取出每一条记录,遍历结果集。
1.3 cursor的四个属性
cursor有如下四个属性:
%isopen:布尔类型。判断游标是否打开,打开为true。对于隐式游标而言,这个值总是false,因为隐式游标在DML语句执行时打开,结束时就立即关闭。
%found:布尔类型。在执行任何DML语句前SQL%FOUND和SQL%NOTFOUND的值都是NULL。在执行DML语句后,SQL%FOUND的属性值将是:
. TRUE :INSERT
. TRUE :DELETE和UPDATE,至少有一行被DELETE或UPDATE.
. TRUE :SELECT INTO至少返回一行
%notfound:布尔类型。当SQL%FOUND为TRUE时,SQL%NOTFOUND为FALSE
%rowcount:数值类型。在执行任何DML语句之前,SQL%ROWCOUNT的值都是NULL,对于SELECT INTO语句,如果执行成功,SQL%ROWCOUNT的值为1,如果没有成功,SQL%ROWCOUNT的值为0,同时产生一个异常NO_DATA_FOUND。
注:PLSQL中的布尔类型的值为null、true、false。
2.显式游标和隐式游标
在游标声明之前,我们来看下显式游标和隐式游标。
2.1 隐式游标
事实上,当我们在PLSQL中进行非查询(或者返回单条记录的查询)语句,如update、delete、insert等时,ORACLE 系统会自动地为这些操作设置游标并创建其工作区,并且隐式游标的名字为SQL,由ORACLE 系统定义。
对于隐式游标的操作,如定义、打开、取值及关闭操作,都由ORACLE 系统自动地完成,无需用户进行处理。
PL/SQL管理隐式游标,当查询开始时隐式游标打开,查询结束时隐式游标自动关闭。
用户只能通过隐式游标的相关属性,来完成相应的操作。在隐式游标的工作区中,所存放的数据是与用户自定义的显示游标无关的、最新处理的一条SQL 语句所包含的数据。
简单实例
对于如下一张表ljb_test,更新每个人的薪水:
set serveroutput on;
begin
update ljb_test set salary = salary + 1;
dbms_output.put_line('更新了'||SQL%rowcount||'行数据'); --must before commit
commit;
end;
/
结果如下:
这里需要指出的是:关于隐式游标的属性操作,必须在commit之前,可以尝试把打印输出放在commit之后,得到的结果是0。这里之所以结果加了2,是因为我实验了两次。
2.2 显式游标
当查询返回结果超过一行时,就需要一个显式游标,此时用户不能使用select into语句。
显式游标在PL/SQL块的声明部分声明,在执行部分或异常处理部分打开,取数据,关闭。
这里要做一个声明,我们所说的游标通常是指显式游标,而显式游标需要被声明。
2.2.1 cursor的声明、打开、关闭、从游标提取数据
声明游标
CURSOR cursor_name IS select_statement;
打开游标
OPEN cursor_name;
关闭游标
CLOSE cursor_name;
从游标提取数据
从游标得到一行数据使用FETCH命令。每一次提取数据后,游标都指向结果集的下一行。
语法如下:
FETCH cursor_name INTO variable[,variable,...]
如:
set serveroutput on;
declare
cursor c is select * from ljb_test; --1.声明游标的时候Oracle不会从数据库中取数据
v_test c%rowtype;
begin
open c; --2.打开游标,此时从数据库中取数据,并把结果集放在内存中
fetch c into v_test; --3.获取数据,fetch的时候游标自动往下移动一格
dbms_output.put_line(v_test.name);
fetch c into v_test;
dbms_output.put_line(v_test.name);
close c; --4.关闭游标,清掉内存。成对编程
end;
/
命令行运行,结果如下:
2.2.2 遍历结果集
如果我们想要遍历整个测试表,显然需要通过循环来进行。
正常情况下如果遵循循环遍历游标应当遵从以下步骤:
1、打开游标
2、开始循环
3、从游标中取值
4、检查那一行被返回
5、处理
6、关闭循环
7、关闭游标
事实上,我们确实可以通过该方式实现,即通过while循环和do while循环。
但是,for循环却不无需这么复杂,这里我们重点介绍for循环。
上文提到,PLSQL中有三种循环,这里需要指出的是,使用游标遍历时,最简单最稳定的就是for循环,但另外两种循环仍然会做简单介绍。如下:
2.2.2.1 for循环遍历
FOR循环的游标按照正常的声明方式声明,但是不需要显式的打开、关闭、取数据,测试数据的存在、定义存放数据的变量等等。
for循环是最简单也是最不容易出错的方式,推荐采用for循环遍历。
set serveroutput on;
declare
cursor c is select * from ljb_test;
--无需在此声明变量v_test
begin
--无需显式打开游标
for v_test in c loop
--无需显式fetch
dbms_output.put_line(c%rowcount||'--'||v_test.name);
end loop;
--无需显式关闭游标
end;
/
九条记录全部被打印,运行结果如下:
2.2.2.2 while循环遍历
declare
cursor c is select * from ljb_test; --声明游标的时候Oracle不会从数据库中取数据
v_test c%rowtype;
begin
open c; --打开游标,此时从数据库中取数据,并把结果集放在内存中
fetch c into v_test; --获取数据,fetch的时候游标自动往下移动一格
while c%found loop
dbms_output.put_line(c%rowcount||'--'||v_test.name);
fetch c into v_test;
end loop;
close c; --关闭游标,清掉内存。成对编程
end;
/
九条记录被遍历,结果如下:
如果我们把fetch语句和打印语句调换一下位置,结果会怎样?
可以看到,第一个记录被跳过取,最后一个打印两边。原因是,我们第一次打印前fetch了两次,而最后一个虽然c无法fetch到数据,但是上一个的c%fetch仍然是true。
所以,采用while循环一定注意fetch和打印的顺序。do while类似。
2.2.2.3 do while循环遍历
declare
cursor c is select * from ljb_test; --声明游标的时候Oracle不会从数据库中取数据
v_test c%rowtype;
begin
open c;
loop
fetch c into v_test;
exit when(c%notfound);
dbms_output.put_line(c%rowcount||'--'||v_test.name); --如果顺序反了,就会最后一条记录打印两次
end loop;
close c; --关闭游标,清掉内存。成对编程
end;
/
2.2.3 含参游标
类似于函数,我们可以将参数传递给游标并在查询中使用。
CURSOR cursor_name[(parameter[,parameter],...)]
IS select_statement;
参数定义方式为:
Parameter_name [IN] data_type[{:=|DEFAULT} value]
需要注意的是:游标只能接受传递的值,而不能返回值。参数只定义数据类型,没有大小。
declare
cursor c(v_dep ljb_test.dep%type, v_salary ljb_test.salary%type)
is select * from ljb_test where dep = v_dep and salary = v_salary;
begin
for v_temp in c(3,4000) loop
dbms_output.put_line(v_temp.name);
end loop;
end;
/
结果如下:
2.4 可更新游标
declare
cursor c is select * from ljb_test for update; --添加for update即可
begin
for v_temp in c loop
if(v_temp.salary<3500) then
update ljb_test set salary = salary * 2 where current of c; --更新条件
elsif(v_temp = 5000) then
delete from ljb_test where current of c; --更新条件
end if;
end loop;
commit;
end;
/
oracle中的cursor属性有哪些,Oracle学习11:游标(cursor)--显式游标隐式游标、游标四个属性、循环遍历...相关推荐
- 资源放送丨《Oracle中为什么没有Double Write?Oracle支持原子写吗?》PPT视频
点击上方"蓝字" 关注我们,享更多干货! 前段时间,墨天轮邀请数据库资深专家 李真旭(Roger) 老师分享了<Oracle中为什么没有Double Write?Oracle ...
- oracle中exist什么意思,oracle中not exists 是什么意思 , oracle数据库中exists的作用
导航:网站首页 > oracle中not exists 是什么意思 , oracle数据库中exists的作用 oracle中not exists 是什么意思 , oracle数据库中exist ...
- oracle中执行动态sql语句吗,oracle中有没有可动态执行sql语句的函数
oracle中有没有可动态执行sql语句的函数 关注:233 答案:2 手机版 解决时间 2021-03-05 15:53 提问者祗剩寂寞 2021-03-04 22:38 oracle中有没有可 ...
- oracle中 xD转义,【转】oracle X表汇总
最早从那里看到关于比较详细的X$表的介绍,后来陆续从其他Oracle专家那里得到了不少信息.在Steve Adams 的书中对X$表多有提及,而且他的站点也是个资源比较丰富的地方.不过在中文Oracl ...
- oracle中触发器只能用于表吗,Oracle触发器的分类和使用
Oracle触发器的分类和使用 摘要:在Oracle中,触发器是一种特殊的存储过程,它在发生某种数据库事件时由Oracle 系统自动触发.触发器通常用于加强数据的完整性约束和业务规则等,对于表来说,触 ...
- oracle中闪回和回滚,oracle闪回操作详解
Oracle的闪回 oracle中为什么会有闪回呢!它的作用是什么呢?我们来学习一下闪回吧!闪回和回滚异曲同工之妙. 一闪回的介绍 (1)在Oracle的操作工程中,会不可避免地出现操作失误或者用户失 ...
- oracle中何时会用到join,Oracle中join用法的演示
以下的文章主要介绍的是Oracle中join用法,如果你是其方面的新手,对Oracle中oin的实际用法很感兴趣,但是却找不到一些资料去对其进行更深入的了解的话,你不妨浏览以下的文章对其进行了解. O ...
- oracle中代表任意一个字符的,oracle 语法
1.基本语法:SELECT *[列名 [[AS] 别名], 列名2...] FROM 表名 [[AS] 别名]; 2. 使用||做连接:Oracle中的字符串用单引号. 例:SELECT " ...
- oracle 中触发器的作用是什么,oracle创建触发器及作用举例
--创建触发器及作用举例 create or replace trigger tri before delete on emp --在删除emp表数据之前需要做的事根据自己的业务去写,before是在 ...
- oracle 几种锁,oracle_基于oracle中锁的深入理解,ORACLE里锁有以下几种模式:0:no - phpStudy...
基于oracle中锁的深入理解 ORACLE里锁有以下几种模式:0:none 1:null 空 2:Row-S 行共享(RS):共享表锁 3:Row-X 行专用(RX):用于行的修改 4:Share ...
最新文章
- oracle数据库备份方法主要有哪几种,Oracle数据库备份方法有哪三种?
- MIT提出Matlab插件mNeuron:实现深度模型神经元的可视化
- 成功解决AttributeError: module tensorflow.compat has no attribute v1
- 简述python中面向对象的概念_简述Python中的面向对象编程的概念
- baidu patchrom项目开发详细教程(Being updated)
- LSGO软件技术团队内部技术交流
- html5群组选择器,css选择器
- js 获取当前元素的父元素的父元素的id
- C++中在浏览器打开html文件
- hydra安装及使用
- Docker部署项目的步骤,按步骤一步一步来,一切都会成功
- Mark:SQL Server关于CAST和CONVERT的区别和用法
- 7. 如何创建 CSS
- java 通过身份证计算年龄性别
- 艺术与科技的跨界融合 Jya美学家电品牌发布
- java dao 单元测试,你应该如何单元测试DAO层
- 再见,2018俄罗斯世界杯!
- 我的Python心路历程 第十期 (10.10 股票实战可视化历史趋势)
- 如何将低dpi图片升级到300dpi
- 龙威ol服务器维护是什么意思,《龙威OL》六大职业定位介绍
热门文章
- libiconv字符集转换库使用方法
- 用php做居中金字塔,[菜鸟学php] php版自定义函数实现金字塔
- 911计算机专业基础综合,青岛大学10数据结构911计算机专业综合
- 12306一直提示网络有问题_教你怎么在12306官网订购火车票 火车票查询12306订购...
- hdu2069(Coin Change)
- Python 使用pdfplumber 提取PDF页面表格的内容
- mysql 备份脚本 linux,LINUX中MySQL如何按时备份脚本
- linux 编译链接出错,Qt编译和链接错误
- c语言 数组指针传递给函数_嵌入式开发-C语言-指针与数组
- java脚本含义_set -e在bash脚本中的含义是什么?