文章目录

  • 1 概述
    • 1.1 思维导图
  • 2 语法
    • 2.1 基本写法(4步)
    • 2.2 游标4大属性
  • 3 分类
    • 3.1 静态游标
      • 3.1.1 隐式游标 dml
      • 3.1.2 显式游标 cursor
    • 3.2 动态游标
      • 3.2.1 自定义类型 ref cursor
      • 3.2.2 系统类型 sys_refcursor
  • 4 扩展
    • 4.1 三种游标循环效率对比
    • 4.2 实例:实际开发中,游标遍历数据

1 概述

1. 游标是什么?用来存储多条查询数据的一种数据结构('结果集'),它有一个 '指针',从上往下移动('fetch'),从而能够 '遍历每条记录'2. 优缺点(1) 提高 sql '执行效率'(2) 牺牲 '内存'

游标概念图:

1.1 思维导图

2 语法

2.1 基本写法(4步)

-- 测试基础数据
create table stu_info (id   number(3),name varchar2(30),sex  varchar2(2)
);insert into stu_info(id, name, sex) values (1, '小游子', '女');
insert into stu_info(id, name, sex) values (2, '小优子', '男');
commit;

游标语法:4 个步骤,获取 学生信息表(stu_info)的记录

declare-- 1 声明游标cursor cur_stu_info isselect * from stu_info;v_stu_info cur_stu_info%rowtype;
begin-- 2 开启游标open cur_stu_info;-- 3 获取数据(一次获取一行)fetch cur_stu_infointo v_stu_info;dbms_output.put_line(v_stu_info.id || ' : ' || v_stu_info.name);-- 4 关闭游标close cur_stu_info;end;

执行截图:

1 : 小游子

2.2 游标4大属性

属性            返回值类型      作用
sql%isopen      布尔型         判断游标是否 '开启'
sql%found       布尔型         判断游标是否 '获取' 到值
sql%notfound    布尔型         判断游标是否 '没有获取' 到值(常用于 "退出循环")
sql%rowcount    整型              '当前' 成功执行的数据行数(非 "总记录数")

特别说明:sql%notfound

Oracle 官方文档解释:Before the first fetch%NOTFOUND returns NULL. If fetch never executes susscessfully. the loop is never exited, because then EXIT WHEN statement executes only if it’s WHEN condition is true. To be safe. you might want to use the following EXIT statement instead:
EXIT WHEN SQL%NOTFOUND OR SQL%NOTFOUND IS NULL;

简单说,退出循环的必要条件:fetch 语句执行成功 + 第一次 fetch 的值返回 null

-- **************************************************************
-- 功能:循环读取数据
-- 核心:先后顺序 = 先 fetch ... 再 exit when *%notfound
-- **************************************************************
declarecursor cur_stu_info isselect * from stu_info t where t.id = 9;v_stu_info cur_stu_info%rowtype;
beginopen cur_stu_info;loopfetch cur_stu_infointo v_stu_info; -- 可测试,这段 fetch 放在 %notfound 后面exit when cur_stu_info%notfound;dbms_output.put_line('该语句不会执行,因为没有 id = 9 的记录');end loop;close cur_stu_info;
end;

3 分类

3.1 静态游标

3.1.1 隐式游标 dml

1. 自动创建(1) DML(2) select into2. 自动管理(1) 无需人为干预(自动声明、打开、关闭)(2) 默认游标名:'SQL'

演示:

declarev_count number;
begininsert into stu_info (id, name, sex) values (3, '瑶瑶', '女');if sql%found thendbms_output.put_line('插入成功!');end if;update stu_info t set t.name = '悠悠' where t.id = 3;if sql%found thendbms_output.put_line('更新成功!');end if;delete from stu_info t where t.id = 3;if sql%found thendbms_output.put_line('删除成功!');end if;select count(1) into v_count from stu_info t;if sql%found thendbms_output.put_line('总记录为: ' || v_count);end if;if sql%isopen thendbms_output.put_line('不可能的,永远不可能走这一步');elsedbms_output.put_line('系统已自动关闭游标');end if;
end;

测试结果:

插入成功!
更新成功!
删除成功!
总记录为: 2
系统已自动关闭游标

3.1.2 显式游标 cursor

由关键字 cursor 声明,可带参数,也可不带参数

情况1:不带参数:同上 -> 游标语法:(4 个步骤)

情况2:带参数(声明参数值和类型):

declarev_stu_info stu_info%rowtype;-- 步骤1: 声明游标cursor cur_stu_info(v_id stu_info.id%type) isselect * from stu_info t where t.id = v_id;
begin-- 步骤2: 打开游标open cur_stu_info(1);-- 步骤3: 提取数据fetch cur_stu_infointo v_stu_info;dbms_output.put_line(v_stu_info.id || ' : ' || v_stu_info.name);-- 步骤4: 关闭游标close cur_stu_info;end;

测试结果(都一样,因为都是取得 id=1 的记录):

1 : 小游子

3.2 动态游标

3.2.1 自定义类型 ref cursor

有两种使用情况
1. 弱类型,无 return(常用)
2. 强类型,有 return(游标的类型必须和 return 的类型完全一致)(1) '字段数量、字段类型、字段顺序' 均完全同 return 一致(2) 此时 open ... for 后只能用 sql 语句,而不能是 '字符串'

情况1:弱类型,无 return(常用)

declarev_sql_select varchar(200);v_id         scott.stu_info.id%type;v_name       scott.stu_info.name%type;type cur_stu_type is ref cursor; -- 无 returncur_stu_info cur_stu_type;begin-- 测试v_id := 1;v_sql_select := 'SELECT t.id, t.name FROM stu_info t WHERE t.id <= :b1';open cur_stu_info for v_sql_selectusing v_id; -- 绑定变量(大数据处理常用优化手段)fetch cur_stu_infointo v_id, v_name;dbms_output.put_line(v_id || ' :' || v_name);close cur_stu_info;end;

输出结果:

1 :小游子

情况2:强类型,有 return

declarev_sql_select    varchar(200);v_stu_info_rows scott.stu_info%rowtype;type cur_stu_type is ref cursor return scott.stu_info%rowtype; -- 有 return cur_stu_info cur_stu_type;begin-- 测试/*  v_id := 1;v_sql_select := 'SELECT t.id, t.name FROM stu_info t WHERE t.id <= :b1';*/open cur_stu_info forselect t.id, t.name, t.sex from stu_info t;fetch cur_stu_infointo v_stu_info_rows;dbms_output.put_line(v_stu_info_rows.id || ' :' || v_stu_info_rows.name);close cur_stu_info;end;

输出结果:(同弱类型一样)

1 :小游子

3.2.2 系统类型 sys_refcursor

常用,省去了手动定义动态游标的步骤,以下效果等同:

declare-- type cur_stu_type is ref cursor; -- 手动定义动态游标-- cur_stu_info cur_stu_type;-- 声明动态游标, 这一个步骤等于上面两个步骤cur_stu_info sys_refcursor;
begin
end;

4 扩展

4.1 三种游标循环效率对比

结论:一般来说 '批量处理' 的速度要最好,'隐式游标' 的次之,'单条处理' 的最差
说明:若有兴趣,可以在数据量多的表里面,分别尝试下列三种写法,并打印时间,用作比较1. 批量处理open 游标;loopfetch 游标 bulk collect  into 集合变量(也就是 table 类型哦) limit 数值; -- 一般 500 左右exit when 条件; -- cursor.count = 0逻辑处理;end loop;close 游标;2. 隐式游标for x in (sql 语句) loop逻辑处理;end loop;3. 单条处理open  游标;loopfetch 游标 into 变量;exit when 条件;逻辑处理;end loop;close 游标;

4.2 实例:实际开发中,游标遍历数据

-- *************************************************
-- 功能:读取表 stu_info 数据
-- *************************************************
declarev_sql_select varchar(300);cur_stu_info sys_refcursor;type record_stu_info is record(v_id   scott.stu_info.id%type,v_name scott.stu_info.name%type);type table_stu_info is table of record_stu_info;v_stu_info_table table_stu_info;beginv_sql_select := 'SELECT t.id, t.name FROM stu_info t WHERE t.id <= :b1';open cur_stu_info for v_sql_selectusing 3; -- 绑定变量,此处 3,仅用作测试loopfetch cur_stu_info bulk collectinto v_stu_info_table limit 1; -- 数据量太少,仅当前测试使用哦,实际开发 建议 500 左右-- 此时 %notfound 不合适,count 适用-- 因为 可能找到数据了(found 非空值),但是小于 limit nexit when v_stu_info_table.count = 0; -- 退出条件!for i in v_stu_info_table.first .. v_stu_info_table.last loopdbms_output.put_line('序号:' || v_stu_info_table(i).v_id || ' , ' ||'姓名:' || v_stu_info_table(i).v_name);end loop;end loop;close cur_stu_info;exceptionwhen others then-- 异常时,仍要 关闭游标if cur_stu_info%isopen thenclose cur_stu_info;end if;dbms_output.put_line(sqlcode || ' : ' || sqlerrm);dbms_output.put_line(dbms_utility.format_error_backtrace);
end;

测试结果:(建议在 ‘测试窗口’ debug 看看执行步骤)

序号:1 , 姓名:小游子
序号:2 , 姓名:小优子

如果对 table 类型、record 类型有疑问,
请点击 %type、%rowtype、record,varry、table 的使用详解

Oracle 游标详解(cursor)相关推荐

  1. ORACLE游标详解

    文章目录 一.概述 二.显示游标 1.声明游标 2.打开游标 3.读取游标 4.关闭游标 三.隐式游标 四.游标的属性 1.%FOUND(是否找到游标) 2.%NOTFOUND(是否没找到游标) 3. ...

  2. Oracle 错误代码详解

    Oracle 错误代码详解及解决方式–ORA ORA-00001: 违反唯一约束条件 (.) 错误说明:当在唯一索引所对应的列上键入重复值时,会触发此异常. ORA-00017: 请求会话以设置跟踪事 ...

  3. oracle有哪两种内存结构,Oracle体系结构详解(物理构造,内存结构和逻辑结构)...

    当前位置:我的异常网» 数据库 » Oracle体系结构详解(物理构造,内存结构和逻辑结构 Oracle体系结构详解(物理构造,内存结构和逻辑结构) www.myexceptions.net  网友分 ...

  4. Oracle 存储过程详解(上)

    目录 一.存储过程与存储函数的定义 二.创建 / 执行存储过程所需的权限 1.resource权限 2.create.execute procedure权限 三.创建 / 执行存储过程 四.变量与参数 ...

  5. Oracle 体系结构详解

    Oracle 体系结构详解 什么是Orcale数据库? Orcale数据库(Oracle DateBase)是一款关系型数据库(这里就不多做介绍了),通常情况下,我们会把承载我们核心数据的系统通称为数 ...

  6. Oracle 表详解(table)

    文章目录 1 概述 2 语法 2.1 创建表 create table 2.2 修改表 alter table 2.3 删除表 drop table 2.4 清空表 truncate table 2. ...

  7. Oracle ASM 详解 收藏

    Oracle ASM 详解 ASM:Automatic Storage Management, 是Oracle 主推的一种面向Oracle的存储解决方案, ASM 和 RDBMS 非常相似,ASM 也 ...

  8. oracle分区表编程,Oracle分区表详解

    当前位置:我的异常网» 编程 » Oracle分区表详解 Oracle分区表详解 www.myexceptions.net  网友分享于:2013-10-28  浏览:25次 Oracle分区表详解 ...

  9. Oracle 冷备份详解【实战案例】

    Oracle 冷备份详解 --准备工作 select * from v$database; select file_name from dba_data_files; create tablespac ...

  10. oracle里面asm的作用,Oracle ASM 详解

    Oracle ASM 详解 ASM:Automatic Storage Management, 是Oracle 主推的一种面向Oracle的存储解决方案, ASM 和 RDBMS 非常相似,ASM 也 ...

最新文章

  1. 在Ubuntu下构建Bullet以及执行Bullet的样例程序
  2. 广义逆高斯分布及推广(To be continued)
  3. 英国正式启用首批5G服务
  4. 【渝粤教育】21秋期末考试建设工程法规10221k1
  5. Linux:chmod命令-修改文件或目录的权限
  6. 【clickhouse】Clickhouse 版本号历史
  7. ECMAScript 6中的Set和Map数据结构
  8. 18.1 集群介绍 18.2 keepalived介绍 18.3/18.4/18.5 用keepalived配置高可用集群
  9. sublime ctrl b突然不能用解决方法
  10. Adobe Acrobat Pro 2017安装
  11. 国产6678开发记录
  12. Hadoop架构与原理:Hadoop系统架构原理解析
  13. 分治法_乒乓球比赛赛程安排(C语言)
  14. 十大javascript难点
  15. 北京交通大学计算机全球排名,2017美国研究生计算机专业排名 - 2017北京交通大学计算机考研成绩310分,能调剂到什么大学...
  16. 什么是教养?不给人制造麻烦,就是最好的教养。
  17. 嵌入式状态机编程简介
  18. 【转】24个GE SFP/10 GE SFP+端口是什么意思
  19. 管理信息系统复试——管理信息系统基础
  20. Java中使用HSSFWorkbook POI导出下载excel文件

热门文章

  1. edi许可证和ICP区别
  2. 移动端rem适配(375)设计稿
  3. 深入了解PowerManagerService(一)之Android 11.0 Power 键亮屏灭屏流程分析
  4. MP3格式音频数据文件解析
  5. 初学unity(简单场景制作)
  6. php 生成思维导图,JavaScript如何生成思维导图(mindmap)
  7. 算算职场薪水账 到手3000元税前工资约3760元
  8. 【文献阅读】大脑中与音乐体验和与音乐错误(冲突)监测相关的神经激活
  9. zoj 1101 Gamblers 为什么总是WA?
  10. 2022-2028年中国酒店PMS行业市场行情动态及发展趋向分析报告