19.oracle11g中的游标

oracle11g中的游标

  • 一、案例引入
  • 二、什么是游标
  • 三、隐式游标
    • 1、隐式游标的属性
    • 2、创建语法
    • 3、示例
  • 四、显示游标
    • 1、显示游标的属性
    • 2、创建语法
    • 3、示例
  • 五、REF游标
    • 1、REF游标的属性
    • 2、创建语法
    • 3、示例
  • 六、循环游标
    • 1、 循环游标的作用
    • 2、用for 与 loop 创建
    • 3、示例

在这里插入图片描述

一、案例引入

假设我们有一个名为employee的表,其中存储了员工的信息,包括员工ID、姓名、部门和工资等。现在我们需要编写一个PL/SQL存储过程,用于计算每个部门的平均工资,并将结果输出到控制台。在这个业务案例中,我们可以使用游标来实现这个逻辑,因为需要对每个部门进行单独的计算并输出结果。

首先,让我们创建一个名为employee的示例表,并插入一些数据:

CREATE TABLE employee (employee_id NUMBER,employee_name VARCHAR2(100),department VARCHAR2(100),salary NUMBER
);INSERT INTO employee (employee_id, employee_name, department, salary) VALUES (1, 'Alice', 'HR', 3000);
INSERT INTO employee (employee_id, employee_name, department, salary) VALUES (2, 'Bob', 'HR', 3500);
INSERT INTO employee (employee_id, employee_name, department, salary) VALUES (3, 'Charlie', 'IT', 4000);
INSERT INTO employee (employee_id, employee_name, department, salary) VALUES (4, 'David', 'IT', 3800);
INSERT INTO employee (employee_id, employee_name, department, salary) VALUES (5, 'Eve', 'IT', 4200);

接下来,我们可以编写一个存储过程,使用游标计算每个部门的平均工资,并将结果输出到控制台:

CREATE OR REPLACE PROCEDURE calculate_average_salary IS-- 声明游标CURSOR department_cursor ISSELECT department, AVG(salary) AS avg_salaryFROM employeeGROUP BY department;-- 声明游标变量department_name employee.department%TYPE;avg_salary NUMBER;
BEGIN-- 打开游标OPEN department_cursor;-- 循环处理结果集LOOPFETCH department_cursor INTO department_name, avg_salary;EXIT WHEN department_cursor%NOTFOUND;-- 在这里可以处理每一行数据,例如打印到控制台DBMS_OUTPUT.PUT_LINE('Department: ' || department_name || ', Average Salary: ' || avg_salary);END LOOP;-- 关闭游标CLOSE department_cursor;
END;
/

在上面的示例中,我们首先声明了一个名为department_cursor的游标,它用于查询每个部门的平均工资。然后在存储过程中打开游标,使用循环逐行从游标中获取数据,并在循环中处理每一行数据,最后关闭游标。当我们调用calculate_average_salary存储过程时,它会计算每个部门的平均工资,并将结果输出到控制台。

这个示例演示了如何使用游标在Oracle中处理业务逻辑,通过游标,我们可以更灵活地处理查询结果集中的数据,实现更复杂的数据操作逻辑。

二、什么是游标

在Oracle 11g中,游标是一种用于在PL/SQL程序中处理查询结果集的数据结构。它允许程序员在程序中对查询结果集进行逐行处理,可以用来遍历和操作查询结果集中的数据。游标可以分为隐式游标、显式游标、 REF 游标

  • 隐式游标:

    1. 隐式游标是在PL/SQL块中执行SELECT语句时自动创建和管理的,程序员无需显式声明和使用。
    2. 隐式游标的查询结果集会被自动保存在系统生成的游标中,程序员可以直接在PL/SQL块中对结果集进行处理。
    3. 通过检查隐式游标的属性可以获得最近执行的DML 语句的信息。

  • 显式游标则需要程序员显式地声明和使用,通常包括以下步骤:

    1. 声明游标:使用DECLARE语句声明游标,指定查询语句和游标的名称。
    2. 打开游标:使用OPEN语句打开游标,执行查询语句并将结果集保存在游标中。
    3. 循环处理结果集:使用FETCH语句从游标中逐行获取数据,并在循环中处理每一行数据。
    4. 关闭游标:使用CLOSE语句关闭游标,释放游标占用的资源。

  • REF 游标:REF 游标用于处理运行时才能确定的动态 SQL 查询的结果

通过游标,程序员可以更灵活地处理查询结果集中的数据,实现更复杂的数据操作逻辑。因此,游标在Oracle 11g中广泛应用于PL/SQL程序中对查询结果集进行处理。

三、隐式游标

1、隐式游标的属性

隐式游标是在PL/SQL块中执行SELECT语句时自动创建和管理的,程序员无需显式声明和使用。隐式游标的属性包括以下几个方面:

  1. %ROWCOUNT:返回最近一次执行的SQL语句所影响的行数。
  2. %FOUND:如果最近一次FETCH语句成功获取了一行数据,则返回TRUE;否则返回FALSE。
  3. %NOTFOUND:如果最近一次FETCH语句未成功获取一行数据,则返回TRUE;否则返回FALSE。
  4. %ISOPEN:如果隐式游标当前处于打开状态,则返回TRUE;否则返回FALSE。

这些属性可以在PL/SQL块中直接使用,用于判断查询结果集的状态和影响行数等信息。例如,可以使用%ROWCOUNT获取受影响的行数,使用%FOUND%NOTFOUND判断是否成功获取了数据行,使用%ISOPEN判断游标是否处于打开状态。

2、创建语法

隐式游标的语法非常简单,它可以在PL/SQL的FOR循环语句中使用SELECT语句来隐式创建和使用游标。FOR循环语句的语法如下:

FOR loop_index IN select_statement LOOP-- 在这里处理每一行数据
END LOOP;

其中,loop_index是循环索引变量,它会在每次循环迭代中自动赋值为查询结果集中的一行数据。select_statement是SELECT语句,它用于查询数据并返回结果集。

3、示例

下面是一个简单的示例,演示了如何在PL/SQL中使用隐式游标:

CREATE OR REPLACE PROCEDURE calculate_order_total_amount IS
BEGIN-- 使用隐式游标,在FOR循环中迭代处理查询结果FOR order_rec IN (SELECT customer_id, SUM(order_amount) AS total_amount FROM orders GROUP BY customer_id) LOOP-- 在这里可以处理每一行数据,例如打印到控制台DBMS_OUTPUT.PUT_LINE('Customer ID: ' || order_rec.customer_id || ', Total Amount: ' || order_rec.total_amount);END LOOP;
END;
/

在上面的示例中,我们使用了一个隐式游标来处理查询结果集中的数据。在FOR循环中,我们使用了一个SELECT语句来查询所有订单的总金额,并按客户ID分组。在循环中,PL/SQL引擎会自动创建一个隐式游标来执行SELECT语句,并迭代处理查询结果集中的数据。在循环中,我们可以使用order_rec变量来访问每一行数据的字段值,并对数据进行处理。

需要注意的是,隐式游标只能用于一次性使用的简单查询,如果需要对结果集进行多次迭代或进行复杂的数据操作,建议使用显式游标来实现。

四、显示游标

当使用显式游标时,可以通过游标属性来访问有关游标的信息,包括游标的状态、当前行的数据等。下面是关于显式游标的属性、创建语法和应用场景的详细介绍,包含具体代码示例。

1、显示游标的属性

显式游标具有以下几个常用的属性:

  • %FOUND:如果最近的FETCH语句成功获取了一行数据,则为TRUE;否则为FALSE。
  • %NOTFOUND:如果最近的FETCH语句未能成功获取一行数据,则为TRUE;否则为FALSE。
  • %ROWCOUNT:返回最近的OPEN、FETCH或CLOSE语句所涉及的行数。
  • %ISOPEN:如果游标是打开状态,则为TRUE;否则为FALSE。

这些属性可以帮助开发人员在处理游标时了解游标的状态和当前行的数据。

2、创建语法

创建显式游标的语法如下:

DECLARECURSOR cursor_name ISselect_statement;

其中,cursor_name 是游标的名称,select_statement 是 SELECT 语句,用于定义游标要查询的数据集。

3、示例

显式游标适用于以下场景:

  • 需要对查询结果集进行多次迭代处理。
  • 需要在不同的地方打开和关闭游标,或者在不同的地方获取游标的状态信息。
  • 需要在游标的生命周期中手动控制游标的状态。
  1. 下面是一个具体的代码示例,演示了显式游标的属性、创建语法和应用场景:

    CREATE OR REPLACE PROCEDURE process_employee_salary IS-- 声明显式游标CURSOR emp_cursor ISSELECT employee_id, employee_name, salary FROM employees;emp_rec emp_cursor%ROWTYPE; -- 声明一个记录类型的变量,用于存储游标返回的数据BEGIN-- 打开游标OPEN emp_cursor;-- 获取游标的状态信息IF emp_cursor%ISOPEN THENDBMS_OUTPUT.PUT_LINE('Cursor is open');END IF;-- 迭代处理查询结果集LOOPFETCH emp_cursor INTO emp_rec; -- 获取游标返回的数据EXIT WHEN emp_cursor%NOTFOUND; -- 当没有更多数据时退出循环-- 处理数据,例如打印到控制台DBMS_OUTPUT.PUT_LINE('Employee ID: ' || emp_rec.employee_id || ', Name: ' || emp_rec.employee_name || ', Salary: ' || emp_rec.salary);END LOOP;-- 获取行数DBMS_OUTPUT.PUT_LINE('Total rows processed: ' || emp_cursor%ROWCOUNT);-- 关闭游标CLOSE emp_cursor;-- 获取游标的状态信息IF NOT emp_cursor%ISOPEN THENDBMS_OUTPUT.PUT_LINE('Cursor is closed');END IF;END;
    /
    

    在上面的示例中,我们创建了一个名为 emp_cursor 的显式游标,用于查询员工表中的数据。在过程中,我们打开了游标,使用 FETCH 语句迭代处理查询结果集,获取了游标的状态信息,获取了行数,并在最后关闭了游标。这个示例展示了显式游标的属性、创建语法和应用场景。

  2. 带参数的显示游标案例
    以下是一个带参数的游标示例,其中我们使用参数来过滤查询结果集:

    -- 创建带参数的游标
    DECLARECURSOR student_cursor (grade_param NUMBER) ISSELECT xh, xmFROM studentWHERE grade = grade_param;xh_val student.xh%TYPE;xm_val student.xm%TYPE;grade_val NUMBER := 1; -- 设置参数的默认值
    BEGIN-- 打开游标OPEN student_cursor(grade_val);-- 迭代处理查询结果集LOOPFETCH student_cursor INTO xh_val, xm_val;EXIT WHEN student_cursor%NOTFOUND;-- 处理查询结果,例如打印到控制台DBMS_OUTPUT.PUT_LINE('Student ID: ' || xh_val || ', Name: ' || xm_val);END LOOP;-- 关闭游标CLOSE student_cursor;
    END;
    /
    

    在上面的示例中,我们创建了一个带参数的游标 student_cursor,该游标接受一个名为 grade_param 的参数,并用于过滤查询结果集。我们在声明游标时指定了参数,并在打开游标时传入参数的值。这样就可以根据参数的值来过滤查询结果集,实现了带参数的游标功能。

五、REF游标

在Oracle数据库中,REF游标是一种特殊类型的游标,用于处理具有引用类型的数据。以下是关于REF游标的属性、创建语法和应用场景的详细介绍,包含具体代码示例。

1、REF游标的属性

REF游标具有以下常用属性:

  • %FOUND:如果最近的FETCH语句成功获取了一行数据,则为TRUE;否则为FALSE。
  • %NOTFOUND:如果最近的FETCH语句未能成功获取一行数据,则为TRUE;否则为FALSE。
  • %ROWCOUNT:返回最近的OPEN、FETCH或CLOSE语句所涉及的行数。
  • %ISOPEN:如果游标是打开状态,则为TRUE;否则为FALSE。

这些属性与普通显式游标的属性相似,用于获取游标的状态信息。

2、创建语法

创建REF游标的语法如下:

DECLARECURSOR cursor_name ISSELECT REF(column_name) FROM table_name;

其中,cursor_name 是游标的名称,column_name 是包含引用类型数据的列名,table_name 是包含引用类型数据的表名。

3、示例

REF游标适用于以下场景:

  • 处理包含引用类型数据的表,例如使用对象类型或嵌套表类型。
  • 需要在游标中返回引用类型数据的引用。
  • 需要在游标的生命周期中手动控制游标的状态。

下面是一个具体的代码示例,演示了REF游标的属性、创建语法和应用场景:

CREATE OR REPLACE PROCEDURE process_ref_cursor IS-- 声明REF游标CURSOR ref_cursor ISSELECT REF(e) FROM employees e;emp_ref employees%ROWTYPE; -- 声明一个记录类型的变量,用于存储引用类型数据的引用BEGIN-- 打开游标OPEN ref_cursor;-- 获取游标的状态信息IF ref_cursor%ISOPEN THENDBMS_OUTPUT.PUT_LINE('REF Cursor is open');END IF;-- 迭代处理查询结果集LOOPFETCH ref_cursor INTO emp_ref; -- 获取游标返回的引用数据EXIT WHEN ref_cursor%NOTFOUND; -- 当没有更多数据时退出循环-- 处理引用数据,例如打印到控制台DBMS_OUTPUT.PUT_LINE('Employee Name: ' || emp_ref.last_name);END LOOP;-- 获取行数DBMS_OUTPUT.PUT_LINE('Total rows processed: ' || ref_cursor%ROWCOUNT);-- 关闭游标CLOSE ref_cursor;-- 获取游标的状态信息IF NOT ref_cursor%ISOPEN THENDBMS_OUTPUT.PUT_LINE('REF Cursor is closed');END IF;END;
/

在上面的示例中,我们创建了一个名为 ref_cursor 的REF游标,用于查询包含引用类型数据的员工表。在过程中,我们打开了REF游标,使用 FETCH 语句迭代处理查询结果集,获取了游标的状态信息,获取了行数,并在最后关闭了游标。这个示例展示了REF游标的属性、创建语法和应用场景。

六、循环游标

循环游标是一种在数据库中遍历结果集的方法。它可以用于迭代处理查询结果,对每一行数据执行特定的操作。以下是关于循环游标的详细介绍:

1、 循环游标的作用

循环游标的作用是遍历查询结果集中的数据,并对每一行数据执行特定的操作。这种遍历方式允许开发人员逐行处理结果集,执行复杂的业务逻辑,或者将结果集中的数据进行进一步处理。

  • 数据处理:循环游标常用于对查询结果进行逐行处理,例如计算、数据转换等。
  • 数据校验:可以使用循环游标来逐行校验查询结果,确保数据的完整性和准确性。
  • 数据导出:通过循环游标,可以逐行将查询结果导出到其他数据源或文件中。

2、用for 与 loop 创建

使用循环游标,有两种常见的创建语法,一种是使用 FOR 循环,另一种是使用 LOOP 循环。

  • 使用 FOR 循环创建循环游标的语法如下所示:

    DECLAREvariable1 datatype;variable2 datatype;
    BEGINFOR rec IN (SELECT column1, column2, ... FROM table_name WHERE condition) LOOPvariable1 := rec.column1;variable2 := rec.column2;-- 在此处处理查询结果END LOOP;
    END;
    /
    
  • 使用 LOOP 循环创建循环游标的语法如下所示:

    DECLARECURSOR cursor_name ISSELECT column1, column2, ...FROM table_nameWHERE condition;variable1 datatype;variable2 datatype;
    BEGINOPEN cursor_name;LOOPFETCH cursor_name INTO variable1, variable2, ...;EXIT WHEN cursor_name%NOTFOUND;-- 在此处处理查询结果END LOOP;CLOSE cursor_name;
    END;
    /
    

3、示例

以下是一个具体的示例代码,演示了使用 FOR 循环和 LOOP 循环创建循环游标,并遍历查询结果集:

  • 使用 FOR 循环:

    DECLARExh_val student.xh%TYPE;xm_val student.xm%TYPE;
    BEGINFOR rec IN (SELECT xh, xm FROM student) LOOPxh_val := rec.xh;xm_val := rec.xm;DBMS_OUTPUT.PUT_LINE('Student ID: ' || xh_val || ', Name: ' || xm_val);END LOOP;
    END;
    /
    

    这段代码是一个 PL/SQL 块,用于遍历名为 student 的表中的数据,并输出学生的学号和姓名到控制台。具体解释如下:

    • DECLARE:声明部分,用于声明变量和游标。
    • xh_val student.xh%TYPE;:声明一个变量 xh_val,其类型与表 student 中的 xh 字段相同。
    • xm_val student.xm%TYPE;:声明一个变量 xm_val,其类型与表 student 中的 xm 字段相同。
    • BEGIN:开始部分,标志着 PL/SQL 块的开始。
    • FOR rec IN (SELECT xh, xm FROM student) LOOP:使用 FOR 循环创建一个游标 rec,并执行 SELECT 语句以从表 student 中获取学号和姓名。
    • xh_val := rec.xh;:将当前行的学号赋值给变量 xh_val
    • xm_val := rec.xm;:将当前行的姓名赋值给变量 xm_val
    • DBMS_OUTPUT.PUT_LINE('Student ID: ' || xh_val || ', Name: ' || xm_val);:输出当前行的学号和姓名到控制台。
    • END LOOP;:结束 FOR 循环。
    • END;:PL/SQL 块的结束。
  • 使用 LOOP 循环:

    DECLARECURSOR student_cursor ISSELECT xh, xmFROM student;xh_val student.xh%TYPE;xm_val student.xm%TYPE;
    BEGINOPEN student_cursor;LOOPFETCH student_cursor INTO xh_val, xm_val;EXIT WHEN student_cursor%NOTFOUND;DBMS_OUTPUT.PUT_LINE('Student ID: ' || xh_val || ', Name: ' || xm_val);END LOOP;CLOSE student_cursor;
    END;
    /
    

    这段代码是一个 PL/SQL 块,用于遍历名为 student 的表中的数据,并输出学生的学号和姓名到控制台。具体解释如下:

    • DECLARE:声明部分,用于声明变量和游标。
    • CURSOR student_cursor IS SELECT xh, xm FROM student;:声明一个名为 student_cursor 的游标,用于从表 student 中选择学号和姓名。
    • xh_val student.xh%TYPE;:声明一个变量 xh_val,其类型与表 student 中的 xh 字段相同。
    • xm_val student.xm%TYPE;:声明一个变量 xm_val,其类型与表 student 中的 xm 字段相同。
    • BEGIN:开始部分,标志着 PL/SQL 块的开始。
    • OPEN student_cursor;:打开游标 student_cursor
    • LOOP:开始一个循环,用于逐行处理查询结果。
    • FETCH student_cursor INTO xh_val, xm_val;:从游标中获取下一行数据,并将学号和姓名赋值给对应的变量。
    • EXIT WHEN student_cursor%NOTFOUND;:如果游标中没有更多的数据,则退出循环。
    • DBMS_OUTPUT.PUT_LINE('Student ID: ' || xh_val || ', Name: ' || xm_val);:输出当前行的学号和姓名到控制台。
    • END LOOP;:结束循环。
    • CLOSE student_cursor;:关闭游标 student_cursor
    • END;:PL/SQL 块的结束。

    在上面的示例中,我们演示了使用 FOR 循环和 LOOP 循环创循环游标,并遍历查询结果集,将学生的学号和姓名逐行输出到控制台。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Rust日报】2023-11-22 Floneum -- 基于 Rust 的一款用于 AI 工作流程的图形编辑器

Floneum -- 基于 Rust 的一款用于 AI 工作流程的图形编辑器 Floneum 是一款用于 AI 工作流程的图形编辑器,专注于社区制作的插件、本地 AI 和安全性。 Floneum 有哪些特性: 可视化界面:您无需任何编程知识即可使用Floneum。可视化图形编辑器可…

Educational Codeforces Round 158 (Rated for Div. 2)(A~E)(贪心,树形DP)

A - Line Trip 题意:有一条路,可以用一条数线来表示。你位于数线上的点 0 ,你想从点 0 到点 x ,再回到点 0。你乘汽车旅行,每行驶 1个单位的距离要花费 1 升汽油。当您从点 0出发时,汽车已加满油(油箱中的…

RocketMQ 消息中间件 知识点汇总

目录 RocketMQ1、什么是RocketMQ?常用术语:2、为什么需要消息队列3、什么是异步处理4、什么是服务解耦5、什么是流量控制6、消息队列两种模型队列模型:发布/订阅模型:总结:7、怎么保证消息不丢失8、如何处理消息被重复消费**出现消息重复的情况:****解决方法:**9、如何保…

基于官方YOLOv4开发构建目标检测模型超详细实战教程【以自建缺陷检测数据集为例】

本文是关于基于YOLOv4开发构建目标检测模型的超详细实战教程,超详细实战教程相关的博文在前文有相应的系列,感兴趣的话可以自行移步阅读即可:《基于yolov7开发实践实例分割模型超详细教程》 《YOLOv7基于自己的数据集从零构建模型完整训练、…

【HuggingFace Transformer库学习笔记】基础组件学习:pipeline

一、Transformer基础知识 pip install transformers datasets evaluate peft accelerate gradio optimum sentencepiece pip install jupyterlab scikit-learn pandas matplotlib tensorboard nltk rouge在host文件里添加途中信息,可以避免运行代码下载模型时候报错…

代码随想录算法训练营第五十四天|392.判断子序列 115.不同的子序列

文档讲解:代码随想录 视频讲解:代码随想录B站账号 状态:看了视频题解和文章解析后做出来了 392.判断子序列 class Solution:def isSubsequence(self, s: str, t: str) -> bool:dp [[0] * (len(t)1) for _ in range(len(s)1)]for i in ra…

matlab三维地形图

matlab三维地形图 %%%%—————Code to draw 3D bathymetry—————————— %-------Created by bobo,10/10/2021-------------------- clear;clc;close all; ncdisp E:\data\etopo\scs_etopo.nc filenmE:\data\etopo\scs_etopo.nc; londouble(ncread(filenm,lon)); lat…

黑马点评笔记 分布式锁

文章目录 分布式锁基本原理和实现方式对比Redis分布式锁的实现核心思路实现分布式锁版本一Redis分布式锁误删情况说明解决Redis分布式锁误删问题分布式锁的原子性问题分布式锁-Redission分布式锁-redission可重入锁原理分布式锁-redission锁重试和WatchDog机制分布式锁-redissi…

java学习part10 this

90-面向对象(进阶)-关键字this调用属性、方法、构造器_哔哩哔哩_bilibili 1.java的this java的this性质类似cpp的this, 但它是一种引用,所以用 this. xxx来调用。 this代表当前的类的实例,所以必须和某个对象结合起来使用,不能…

C#学习相关系列之base和this的常用方法

一、base的用法 Base的用法使用场景主要可以概括为两种: 1 、访问基类方法 2、 调用基类构造函数 使用要求:仅允许用于访问基类的构造函数、实例方法或实例属性访问器。从静态方法中使用 base 关键字是错误的。所访问的基类是类声明中指定的基类。 例如&…

uniapp高德、百度、腾讯地图配置 SHA1

uniapp高德、百度、腾讯地图配置 SHA1 当winr弹出cmd弹框后输入 keytool -list -v -keystore debug.keystore 显示keytool 不是内部或外部命令,也不是可运行的程序或批处理文件。可以先看看是否有下载jdk且配置了环境变量,具体操作如下:keyto…

力扣每日一道系列 --- LeetCode 206. 反转链表

📷 江池俊: 个人主页 🔥个人专栏: ✅数据结构探索 ✅LeetCode每日一道 🌅 有航道的人,再渺小也不会迷途。 LeetCode 206. 反转链表 思路一:头插 初始化两个指针,cur 和 newhead。…