08-Oracle游标管理(定义,打开、获取数据及关闭游标)

news2025/2/4 22:36:02

目标

1.确定何时需要显示游标
2.声明、打开和关闭显示游标
3.从显示游标中提取数据
4.了解与游标有关的属性
5.使用游标 FOR 循环检索游标中的数据
6.在游标 FOR 循环的子查询中声明游标
7.评估使用逻辑运算符结合在一起的布尔条件

游标

1、在使用一个 PL/SQL 块来 执行 DML 语句 只返回一行结果 SELECT 语句时,将创建一个 隐式游标
2、可用将游标视为内存中的一个数组或区域,它包含当前处理的值。
3、当 SELECT 语句 返回多行结果 时,用户必须创建一个 显示游标 。然后查询所返回的数据就将放在显示游标中进行处理。

示例:显示当用户没有创建一个显示游标以获得多行结果时发生的情况。

DECLARE
	v_title books.title%TYPE;
	v_retail books.retail%TYPE;	
BEGIN
	SELECT title,retail
	INTO v_title,v_retail
	FROM books NATURAL JOIN orderitems
	WHERE order#=1012;
	DBMS_OUTPUT.PUT_LINE('Books title: '||v_title||' Retail price: '||v_retail);
END;
示例中虽然包括了一个 WHERE 子句来确保只处理一个订单,但是在这个订单中包括了不止一本书。当PL/SQL 块将会 检索多个行 时,必须使用 显示游标 来存储要处理的数据。与Oracle 自动维护的隐式游标不同,必须通过 PL/SQL 语句来手工声明、打开和关闭显示游标。

声明显示游标

显示游标是在 PL/SQL 块的声明部分声明的。
声明游标的语法:
CURSOR cursor_name IS 
	selectquery;

前面示例中,需要一个显示游标来检索订单1012中的图书的书名和零售价。

DECLARE
	CURSOR books_cursor IS
		SELECT title,retail
		FROM books NATURAL JOIN orderitems
		WHERE order#=1012;
示例中声明了一个名为 BOOKS_CURSOR 的游标来存储行。然后 SELECT 语句将检索图书的书名和零售价。
游标的结构是由使用 SELECT 语句检索的数据定义的
注意 :虽然需要每一本书的 ISBN 来联接 BOOKS 表和 ORDERITEMS 表,以便确定要选择的正确图书,但是在游标本身中并没有包括这一列。
目前只是声明了游标, 在进行任何处理之前,必须首先打开游标。

打开显示游标

在打开游标时,将分配必要的内存,执行 SELECT 语句,然后 SELECT 子句检索的数据加载到游标中。
打开游标的语法
OPEN cursor_name;

示例:
OPEN books_cursor;


打开游标之后,可以将游标中包含的数据赋给变量以进行处理

关闭显示游标

从游标中检索了所有数据之后,必须明确 关闭 它。
PL/SQL 块的可执行部分使用 CLOSE 命令来关闭显示游标
CLOSE 命令的语法
CLOSE cursor_name


CLOSE books_cursor;

从显示游标中提取数据

SELECT 语句不能用来检索显示游标中的数据。
必须使用 FETCH 命令来提取这种游标中的数据。
FETCH 命令检索游标中的行,然后将值赋给变量。注意,必须首先在 PL/SQL 块的声明部分声明变量,然后才能在可执行部分引用它们。
FETCH 命令语法:
FETCH cursor_name INTO variablename[,…variablename];


FETCH books_cursor INTO v_title,v_retail;

示例:显示游标的使用

DECLARE
	v_title books.title%TYPE;
	v_retail books.retail%TYPE;
	CURSOR books_cursor IS
		SELECT title,retail
		FROM books NATURAL JOIN orderitems
		WHERE order#=1012;
BEGIN
	OPEN books_cursor;
	FETCH books_cursor INTO v_title,v_retail;
	DBMS_OUTPUT.PUT_LINE('Books title: '||v_title||' Retail price: '||v_retail);
	CLOSE books_cursor;
END;
解释示例语句
  声明部分定义了变量 v_title v_retail 以及名为 books_cursor 的游标。
  游标是由一个 SELECT 语句定义的,该语句检索包括在订单 1012 中的图书的书名和零售价。
  这个块的可执行部分,打开了之前声明的游标。
  FETCH 语句用来检索游标中的行并将值赋给 v_title v_retail 变量。
  包括了 DBMS_OUTPUT 程序包以显示变量的内容。

结果

结果中发现只有一行数据输出

 独立执行这个PL/SQL块的SELECT语句,显示

要想显示订单 1012 中每一本书的书名和零售价, 应该将检索和显示游标内容的语句包括在一个循环中
基本、 FOR WHILE 循环都要求包括 某种条件 来确定应该在何时终止循环。
每一种游标(隐式游标和显示游标)都有 4 个可以用作 PL/SQL 块中的条件的属性。
最经常用来控制循环的三个游标属性是:
  %ROWCOUNT
  %FOUND
  %NOTFOUND
%ROWCOUNT 属性包含一个整数值,代表在执行块时处理的行数。
  %FOUND %NOTFOUND 属性用来反映是否已经找到了要处理的行。如果在执行块的过程中影响了一行或多行,那么 %FOUND 属性将包含布尔值 TRUE ,相反,如果没有行受到影响,那么 %NOTFOUND 属性为 TRUE
  还有一个属性, %ISOPEN 通常用来确定在执行 PL/SQL 块之后是否关闭游标。

游标属性

说明

%ROWCOUNT

指出处理的行

%FOUND

如果处理了一行或多行,这包含值TRUE——如果没有处理行,则为FALSE

%NOTFOUND

如果没有处理行,则包含值TRUE——如果处理了一行或多行,则为FALSE

%ISOPEN

如果在处理之后不关闭数据,这包含值TRUE——如果关闭游标,则为FALSE。在发生隐式游标时,由于它是自动关闭的,因此这个值在处理之后总是FALSE

如果在一个 PL/SQL 块中包括了一个基本循环来控制一组语句的执行,那么必须包括一个条件来结束这个循环。
可以将条件指定为“当游标不再包含任何值时,就结束循环”。
DECLARE
	v_title books.title%TYPE;
	v_retail books.retail%TYPE;
	CURSOR books_cursor IS
		SELECT title,retail
		FROM books NATURAL JOIN orderitems
		WHERE order#=1012;
BEGIN
	OPEN books_cursor;
	LOOP
		FETCH books_cursor INTO v_title,v_retail;
		EXIT WHEN books_cursor%NOTFOUND;
		DBMS_OUTPUT.PUT_LINE('Books title: '||v_title||' Retail price: '||v_retail);
	END LOOP;
	CLOSE books_cursor;
END;
显示结果

游标FOR循环

因为经常使用循环来控制游标中检索的行的处理,所有 Oracle 包括了一种快捷方法来处理 PL/SQL 块中的显示游标。 游标 FOR 循环 可以用来 自动(或隐含)打开和关闭一个游标 ,也可以用来 提取游标中的数据
游标 FOR 循环的语法:
FOR record_name IN cursor_name LOOP
	statements;
	[statement;…]
END LOOP;
说明:
  不是检索游标中的行并向变量赋值,而是 将行的内容赋给一个记录
  “记录”是一种复合数据类型 可以使其结构与检索的行的结构相同 。要想指定记录的结构与检索的行的结构相同,可以在定义记录时使用 %ROWTYPE 属性。
  %TYPE 属性相似, %TYPE 用来定义基于一个单独列的变量,而 %ROWTYPE 属性定义了基于数据库表中包含的所有列的记录。

示例:包含游标FOR循环的PL/SQL

DECLARE
	CURSOR books_cursor IS
		SELECT title,retail
		FROM books NATURAL JOIN orderitems
		WHERE order#=1012;
	r_books books%ROWTYPE;
BEGIN
	FOR r_books IN books_cursor LOOP
		DBMS_OUTPUT.PUT_LINE('Books title: '||r_books.title||' Retail price: '||r_books.retail);
	END LOOP;
END;
示例说明
  在块的声明部分定义了 记录 r_books ,它具有 books 表的结构。
  可执行部分包含一个游标 FOR 循环,它 隐含打开 books_cursor 的游标,并将其内容 赋给 r_books 记录
  对名为 books_cursor 的游标中包含的每一行都执行一次这个游标 FOR 循环。这个循环中包含的唯一一个语句将显示当前正在处理的行。
  注意 :在 DBMS_OUTPUT 程序包显示的字符引用了记录中包含的列名称。因为将数据赋值给一个记录而不是单独的变量,所以显示值的唯一方法就是指定包含所需数据的列名称。在使用 %ROWTYPE 属性定义这个记录时,还为从 books 表中检索的各个值指定了列名称。要想指定应该显示哪一列或哪些列,必须在列名称之前添加包含数据的记录的名称,如 r_books.title
  在处理了 books_cursor 中包含的最后一行之后,这个循环将会终止,将隐含关闭游标。
在使用游标 FOR 循环时, 可以使用一个子查询来声明游标
不在 PL/SQL 块中的声明部分声明游标,可以 使用 IN 子句中的 SELECT 语句来代替游标名称。
注意: 因为游标没有一个名字,所以不能应用游标属性,例如 %NOTFOUND
示例 :使用子查询的游标 FOR 循环
BEGIN
	FOR r_books IN (SELECT title,retail
		FROM books NATURAL JOIN orderitems
		WHERE order#=1012) LOOP
		DBMS_OUTPUT.PUT_LINE('Books title: '||r_books.title||' Retail price: '||r_books.retail);
	END LOOP;
END;

修改示例,实现确定订单1012中购买的图书以及总应付款额。

DECLARE
	v_ordertotal NUMBER(5,2):=0;
BEGIN
	FOR r_books IN (SELECT title,retail,quantity
		FROM books NATURAL JOIN orderitems
		WHERE order#=1012) LOOP
		DBMS_OUTPUT.PUT_LINE('Books title: '||r_books.title||' Retail price: '||r_books.retail);
		v_ordertotal :=v_ordertotal + r_books.retail*r_books.quantity;
	END LOOP;
	DBMS_OUTPUT.PUT_LINE('Total Amount Due: '||v_ordertotal);
END;

带有逻辑运算符的游标循环控制

如果只需要处理特定数量的行,应该怎么办?
示例 :确定 books 表中 5 本价格最高的图书。
分析:
  考虑可以创建以一个子查询,选择 ROWNUM 小于或等于 5 的图书。
  还可以在 PL/SQL 块中嵌一个游标,从游标中提取行时,提取它们的顺序与最初将它们放在游标中的顺序相同。要想确保游标中的第一行包含零售价最高的图书,可以在声明游标时向定义游标的 SELECT 语句添加一个 ORDER BY 子句,根据 Retail 列降序排列。
  在使用 %ROWCOUNT 属性作为循环条件时,用户可以指定从游标中提取的行,可以在循环条件中使用 AND 逻辑运算符以及 %FOUND 属性,以便确保只有在游标包含额外的行时才会继续循环。

DECLARE
	v_title books.title%TYPE;
	v_retail books.retail%TYPE;
	v_number NUMBER(2):=&How_Many_Books_To_Display;
	CURSOR books_cursor IS
		SELECT title,retail
		FROM books
		ORDER BY retail DESC;	
BEGIN
	OPEN books_cursor;
	FETCH books_cursor INTO v_title,v_retail;
	WHILE books_cursor%ROWCOUNT<=v_number AND
		books_cursor%FOUND LOOP
		DBMS_OUTPUT.PUT_LINE(v_title||','||v_retail);
		FETCH books_cursor INTO v_title,v_retail;
	END LOOP;
	CLOSE books_cursor;
END;

v_number NUMBER(2):=&How_Many_Books_To_Display; 要求用户输入要显示的图书数量,如果用户输出数字 3 ,那么在输出中将显示 3 本价格最高的图书
WHILE books_cursor%ROWCOUNT<=v_number AND books_cursor%FOUND 两个条件使用 AND 逻辑运算符结合在一起,所有这两个条件都必须为 TRUE ,否则这个循环就不会执行
FETCH books_cursor INTO v_title,v_retail; WHILE 语句之前,确保在访问 WHILE 之前找到了一行。如果没有提取任何行,那么无论用户要求多少本书或者游标中实际存在多少行, %FOUND 属性都将为 NULL ,循环不会执行

AND

TRUE

FALSE

NULL

OR

TRUE

FALSE

NULL

TRUE

TRUE

FALSE

NULL

TRUE

TRUE

TRUE

TRUE

FALSE

FALSE

FALSE

FALSE

FALSE

TRUE

FALSE

NULL

NULL

NULL

FALSE

NULL

NULL

TRUE

NULL

NULL

游标的使用——处理隐式游标

显式游标主要是用于对查询语句的处理,尤其是在查询结果为多条记录的情况下;而 对于非查询语句,如修改、删除操作,则由 ORACLE 系统自动地为这些操作设置游标并创 建其工作区,这些由系统隐含创建的游标称为隐式游标,隐式游标的名字为 SQL ,这是由 ORACLE 系统定义的。
对于隐式游标的操作,如定义、打开、取值及关闭操作,都由 ORACLE 系统自动地完成,无需用户进行处理。
用户只能通过隐式游标的相关属性,来完成相应的操作。 在隐式游标的工作区中,所存放的数据是与用户自定义的显示游标无关的、最新处理的一条 SQL 语句所 包含的数据。

格式调用为: SQL%

注: INSERT, UPDATE, DELETE, SELECT 语句中不必明确定义游标。

隐式游标属性
  SQL %FOUND 布尔型属性 , 当最近一次读记录时成功返回,则值为 true
  SQL %NOTFOUND 布尔型属性 , %found 相反;
  SQL %ROWCOUNT 数字型属性 , 返回已从游标中读取得记录数;
  SQL %ISOPEN 布尔型属性 , 取值总是 FALSE SQL 命令执行完毕立即关闭隐式游标。

:删除图书库存中某出版社出版的图书,如果不再存在该出版社的图书,则在出版设信息中删除该出版社信息.

DECLARE
v_pubid books.pubid%TYPE :=&in_pubid;
BEGIN
	DELETE FROM books WHERE pubid=v_pubid;
	DBMS_OUTPUT.PUT_LINE('删除出版社编号为'||v_pubid||'的图书记录');
	COMMIT;
	IF SQL%NOTFOUND THEN
	DELETE FROM publisher WHERE pubid=v_pubid;
	END IF;
	COMMIT;
END;

练习

1. 删除订单表中指定客户编号的订单信息,如果不再存在该客户的订单,则在客户信息中删除该客户信息 .

总结

从一个表中检索多个行时,就需要显示游标
在使用数据填充显示游标之前必须定义并打开它
在打开游标时,将执行定义这个游标的 SELECT 语句
可以使用 FETCH 命令来检索显示游标中的数据
必须关闭显示游标
游标 FOR 循环将隐含(或自动)打开和关闭显示游标并提取游标中的数据
游标属性可以用来确定游标是否是打开的以及游标所处理的行数(如果有)

本人从事软件项目开发20多年,2005年开始从事Java工程师系列课程的教学工作,录制50多门精品视频课程,包含java基础,jspweb开发,SSH,SSM,SpringBoot,SpringCloud,人工智能,在线支付等众多商业项目,每门课程都包含有项目实战,上课PPT,及完整的源代码下载,有兴趣的朋友可以看看我的在线课堂

讲师课堂链接:https://edu.csdn.net/lecturer/893

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/401477.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2月更新 | Visual Studio Code Python

我们很高兴地宣布&#xff0c;2023年2月版 Visual Studio Code Python 和 Jupyter 扩展现已推出&#xff01;此版本包括以下改进&#xff1a;从激活的终端启动 VS Code 时的自动选择环境 使用命令 Python: Create Environmen 时可选择需求文件或可选依赖项 预发布&#xff1a;改…

性能优化之HBase性能调优

HBase是Hadoop生态系统中的一个组件&#xff0c;是一个分布式、面向列存储的内存型开源数据库&#xff0c;可以支持数百万列&#xff08;MySQL4张表在HBase中对应1个表&#xff0c;4个列&#xff09;、超过10亿行的数据存储。可用作&#xff1a;冷热数据分离HBase适合作为冷数据…

坐标系、视窗体(裁剪区域),存储着色器

坐标系 两种常见的投影/坐标系&#xff0c;正交和透视&#xff0c;实际上只是特定的4x4变换矩阵。啥都不规定默认的就是-1.0~1.0的笛卡尔坐标系。 正交&#xff1a; 在opengl的核心框架下&#xff0c;没有提供任何内置渲染管线&#xff0c;所以在提交一个几何图形进行渲染之前&…

Ubuntu Protobuf 安装(测试有效)

安装流程 下载软件 下载自己要安装的版本&#xff1a;https://github.com/protocolbuffers/protobuf 下载源码编译&#xff1a; 系统环境&#xff1a;Ubuntu16&#xff08;其它版本亦可&#xff09;&#xff0c;Protobuf-3.6.1 编译源码 cd protobuf# 当使用 git clone 下来的…

【C语言】操作符详解总结(万字)

操作符详解1. 操作符分类2. 算术操作符3. 移位操作符3.1 整数的二进制是怎么形成的3.2 左移操作符3.3 右移操作符4. 位操作符5. 赋值操作符6. 单目操作符6.1 单目操作符介绍6.2 sizeof 和 数组7. 关系操作符8. 逻辑操作符9. 条件操作符9.1 练习19.2 练习210. 逗号表达式11. 下标…

【Vue】vue2导出页面内容为pdf文件,自定义选中页面内容导出为pdf文件,打印选中页面内容,预览打印内容

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言一、安装html2canvas和jspdf二、导出pdf使用步骤1.在utils文件夹下创建htmlToPdf.js2.在main.js中引入3.在页面中使用三、打印预览1. 引入print-js2.页面中impor…

PG数据库实现高可用方案(包括通用型方案Corosync+pacemaker协作)

实现高可用方案首先了解一下高可用集群高可用&#xff1a;透明切换&#xff0c;故障切换&#xff0c;连接管理器/集群管理器pgpool-Ⅱ&#xff1a;连接池、复制、负载均衡功能PatroniCorosyncpacemaker高可用解决方案Corosyncpacemakercorosyncpacemaker架构协作资源分配&#…

功耗降低99%,Panamorph超清VR光学架构解析

近期&#xff0c;投影仪变形镜头厂商Panamorph获得新型VR显示技术专利&#xff08;US11493773B2&#xff09;&#xff0c;该专利方案采用了紧凑的结构&#xff0c;结合了Pancake透镜和光波导显示模组&#xff0c;宣称比传统VR方案的功耗、发热减少99%以上&#xff0c;可显著提高…

通讯录(C++实现)

系统需求通讯录是一个可以记录亲人、好友信息的工具。本章主要利用C来实现一个通讯录管理系统系统中需要实现的功能如下:添加联系人:向通讯录中添加新人&#xff0c;信息包括&#xff08;姓名、性别、年龄、联系电话、家庭住址&#xff09;最多记录1000人显示联系人:显示通讯录…

【006】Redis主从/哨兵/分片集群Docker搭建

项目源码合集 https://gitee.com/qiuyusy/small-project-study 搭建过程疯狂踩坑,记录一下希望各位少走弯路 目录主从搭建配置文件redis.conf运行容器测试优化哨兵集群配置文件运行容器测试代码读写分离分片集群mkdir -p /opt/docker/redis_study/redis_0/conf mkdir -p /opt/…

藏经阁(五)温湿度传感器 SHT3x-DIS 手册 解析

文章目录芯片特性芯片内部框图芯片引脚定义芯片温湿度范围芯片寄存器以及时序讲解信号转换公式芯片特性 湿度和温度传感器完全校准&#xff0c;线性化温度补偿数字输出供电电压范围宽&#xff0c;从2.4 V到5.5 VI2C接口通讯速度可达1MHz和两个用户可选地址典型精度 2% RH和 0.…

Python 二分查找:bisect库的使用

✅作者简介&#xff1a;人工智能专业本科在读&#xff0c;喜欢计算机与编程&#xff0c;写博客记录自己的学习历程。 &#x1f34e;个人主页&#xff1a;小嗷犬的个人主页 &#x1f34a;个人网站&#xff1a;小嗷犬的技术小站 &#x1f96d;个人信条&#xff1a;为天地立心&…

优先级队列详解

目录优先级队列简介关于堆为什么得用完全二叉树用堆来实现优先级队列插入/删除/获取优先级最高的元素模拟实现使用PriorityQueue的注意事项PriorityQueue常用接口优先级队列的构造方法优先级队列简介 PriorityQueue&#xff0c;即优先级队列。它可以保证每次出出来的数据是队列…

探究:kafka生产者/消费者与多线程安全

目录 1. 多线程安全 1.1. 生产者是多线程安全的么&#xff1f; 1.1. 消费者是多线程安全的么&#xff1f; 2. 消费者规避多线程安全方案 2.1. 每个线程维护一个kafkaConsumer 2.2. [单/多]kafkaConsumer实例 多worker线程 2.3.方案优缺点对比 1. 多线程安全 1.1. 生产…

我的Git stash不小心清空了怎么办,提了代码能反悔吗

文章目录1. 前言2. git stash清空场景2. git stash clear后如何还原3.Git撤销已经推送(push)至远端仓库的信息1. 前言 本文总结的知识很实用哈&#xff0c;虽然是git工具的不常用操作&#xff0c;但是绝对不是冷知识&#xff0c;学会可以从会用git升级到git高手。 主要是两种场…

Centos7 安装Mysql8.0

1、到指定目录下下载安装包[rootVM-0-14-centos ~]# cd /usr/local/src2、下载mysql8[rootVM-0-14-centos src]# wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.20-linux-glibc2.12-x86_64.tar.xz3、解压mysql8, 通过xz命令解压出tar包&#xff0c; 然后通过t…

KDZD耐电压高压击穿强度测试仪

一、技术参数 01、输入电压&#xff1a; 交流 220 V。 02、输出电压&#xff1a; 交流 0--50KV ; 直流 0—50kv 。 03、电器容量&#xff1a;3KVA。 04、高压分级&#xff1a;0—50KV&#xff0c;&#xff08;全程可调&#xff09;。 05、升压速率&#xff1a;0.1KV/s-…

c++11 标准模板(STL)(std::unordered_map)(八)

定义于头文件 <unordered_map> template< class Key, class T, class Hash std::hash<Key>, class KeyEqual std::equal_to<Key>, class Allocator std::allocator< std::pair<const Key, T> > > class unordered…

【C++】你不得不爱的——继承

凡是面向对象的语言&#xff0c;都有三大特性&#xff0c;继承&#xff0c;封装和多态&#xff0c;但并不是只有这三个特性&#xff0c;是因为者三个特性是最重要的特性&#xff0c;那今天我们一起来看继承&#xff01; 目录 1.继承的概念及定义 1.概念 2.继承的定义 2.基类…

Linux进程学习【进程地址】

✨个人主页&#xff1a; Yohifo &#x1f389;所属专栏&#xff1a; Linux学习之旅 &#x1f38a;每篇一句&#xff1a; 图片来源 &#x1f383;操作环境&#xff1a; CentOS 7.6 阿里云远程服务器 Perseverance is not a long race; it is many short races one after another…