ORACLE游标(oracle游标属性)

ORACLE游标(oracle游标属性)文章目录1概述1.1思维导图2语法2.1基本写法(4步)2.2游标4大属性3分类3.1静态游标3.1.1隐式游标dml3.1.2显式游标cursor3.2动态游标3.2.1自定义类型refcursor3.2.2系统类型sys_refcursor4扩展4.1三种游标循环效率对比4.2实例:实际开发中,游标遍历数据1概述1.游标是什么?用来存储多条查询数据的一种数据结构(’结果集’),它有一个’指针’,从上往下移动(’fetch’),从而能够’

大家好,又见面了,我是你们的朋友全栈君。

1 概述

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

游标概念图:
在这里插入图片描述

1.1 思维导图

Oracle 游标详解

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 is
    select * from stu_info;
  v_stu_info cur_stu_info%rowtype;
begin
  -- 2 开启游标
  open cur_stu_info;

  -- 3 获取数据(一次获取一行)
  fetch cur_stu_info
    into 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
-- ************************************************************** 
declare
  cursor cur_stu_info is
    select * from stu_info t where t.id = 9;
  v_stu_info cur_stu_info%rowtype;
begin

  open cur_stu_info;

  loop
    fetch cur_stu_info
      into 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 into
   
2. 自动管理
   (1) 无需人为干预(自动声明、打开、关闭)
   (2) 默认游标名:'SQL'

演示:

declare
  v_count number;
begin
  insert into stu_info (id, name, sex) values (3, '瑶瑶', '女');
  if sql%found then
    dbms_output.put_line('插入成功!');
  end if;

  update stu_info t set t.name = '悠悠' where t.id = 3;
  if sql%found then
    dbms_output.put_line('更新成功!');
  end if;

  delete from stu_info t where t.id = 3;
  if sql%found then
    dbms_output.put_line('删除成功!');
  end if;

  select count(1) into v_count from stu_info t;
  if sql%found then
    dbms_output.put_line('总记录为: ' || v_count);
  end if;

  if sql%isopen then
    dbms_output.put_line('不可能的,永远不可能走这一步');
  else
    dbms_output.put_line('系统已自动关闭游标');
  end if;
end;

测试结果:

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

3.1.2 显式游标 cursor

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

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

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

declare
  v_stu_info stu_info%rowtype;

  -- 步骤1: 声明游标
  cursor cur_stu_info(v_id stu_info.id%type) is
    select * from stu_info t where t.id = v_id;
begin
  -- 步骤2: 打开游标
  open cur_stu_info(1);

  -- 步骤3: 提取数据
  fetch cur_stu_info
    into 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(常用)

declare
  v_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; -- 无 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 for v_sql_select
    using v_id; -- 绑定变量(大数据处理常用优化手段)

  fetch cur_stu_info
    into v_id, v_name;

  dbms_output.put_line(v_id || ' :' || v_name);

  close cur_stu_info;

end;

输出结果:

1 :小游子

情况2:强类型,有 return

declare
  v_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 for
    select t.id, t.name, t.sex from stu_info t;

  fetch cur_stu_info
    into 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 游标;
   loop
      fetch 游标 bulk collect  
       into 集合变量(也就是 table 类型哦) limit 数值; -- 一般 500 左右
       
       exit when 条件; -- cursor.count = 0
       逻辑处理;
    end loop;
    close 游标;

2. 隐式游标
   for x in (sql 语句) loop
      逻辑处理;
   end loop;

3. 单条处理
   open  游标;
   loop
      fetch 游标 
       into 变量;
     
       exit when 条件;
       逻辑处理;
   end loop;
   close 游标;

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

-- *************************************************
-- 功能:读取表 stu_info 数据
-- *************************************************
declare
  v_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;

begin
  v_sql_select := 'SELECT t.id, t.name FROM stu_info t WHERE t.id <= :b1';

  open cur_stu_info for v_sql_select
    using 3; -- 绑定变量,此处 3,仅用作测试

  loop
    fetch cur_stu_info bulk collect
      into v_stu_info_table limit 1; -- 数据量太少,仅当前测试使用哦,实际开发 建议 500 左右
    -- 此时 %notfound 不合适,count 适用
    -- 因为 可能找到数据了(found 非空值),但是小于 limit n
    exit when v_stu_info_table.count = 0; -- 退出条件!
  
    for i in v_stu_info_table.first .. v_stu_info_table.last loop
      dbms_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;

exception
  when others then
    -- 异常时,仍要 关闭游标
    if cur_stu_info%isopen then
      close 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 的使用详解

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/125383.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 基于机器学习的文本分类算法的研究[通俗易懂]

    基于机器学习的文本分类算法的研究[通俗易懂]1.简述文本分类的方法属于有监督的学习方法,分类过程包括文本预处理、特征抽取、降维、分类和模型评价。本文首先研究了文本分类的背景,中文分词算法。然后是对各种各样的特征抽取进行研究,包括词项频率-逆文档频率和word2vec,降维方法有主成分分析法和潜在索引分析,最后是对分类算法进行研究,包括朴素贝叶斯的多变量贝努利模型和多项式模型,支持向量机和深度学习方法。深度学习方法包括多层感知机,卷积神…

    2022年6月8日
    37
  • MongoDB 基础

    MongoDB 基础

    2021年7月8日
    78
  • 详解BP神经网络

    BackPropagationNeuronNetWok  BP神经网络学习算法可以说是目前最成功的神经网络学习算法。显示任务中使用神经网络时,大多数是使用BP算法进行训练.  在我看来BP神经网络就是一个”万能的模型+误差修正函数“,每次根据训练得到的结果与预想结果进行误差分析,进而修改权值和阈值,一步一步得到能输出和预想结果一致的模型。举一个例子:比如某厂商生产一种产品,投放到市场之…

    2022年4月6日
    55
  • CSS3选择器 | 每个前端开发者必须要掌握的技术

    CSS3选择器 | 每个前端开发者必须要掌握的技术目录属性选择符伪类选择符CSS3属性CSS3自适应属性选择符如果能够灵活运用属性选择器,目前为止需要依靠id或class名才能实现的样式完全可以使用属性选择器来实现。E[att]{}:选择具有att属性的E元素E[att=”val”]{}:选择具有att属性且属性值等于val的E元素E[att~=”val”]{}:用于选取属性值中包含指定词汇的元素E[att|=”val…

    2022年7月27日
    6
  • 宝马宣布与Mobileye合作,想让每辆车都成为行走的数据源

    宝马宣布与Mobileye合作,想让每辆车都成为行走的数据源

    2022年3月13日
    38
  • 组合模式解决什么问题_组合模式实例

    组合模式解决什么问题_组合模式实例组合模式 Composite动机模式定义实例结构要点总结笔记动机在软件某些情况下,客户代码过多地依赖于对象容器复杂的内部实现结构,对象内部实现结构(而非抽象接口)地变化将引起客户代码地频繁变化.带来代码地维护性,扩展性等弊端如何将”客户代码与复杂地对象容器结构”解耦?让对象容器自己来实现自身地复杂结构,从而使得客户代码就像处理简单对象一样来处理复杂地对象容器模式定义将对象组合成树形结构以表示”整体-部分”地层次结构.Composite使得用户对单个对象和组合对象地使用具有一致性(稳定)实例树形

    2022年8月9日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号