Oracle游标解析

本节对Oracle中的游标进行详细讲解。

本节所举实例来源Oracle中scott用户下的emp表dept表:

一、游标:

1、概念:

游标的本质是一个结果集resultset,主要用来临时存储从数据库中提取出来的数据块。

二、游标的分类:

1、显式游标:由用户定义,需要的操作:定义游标、打开游标、提取数据、关闭游标,主要用于对查询语句的处理。

属性:%FOUND        %NOTFOUND        %ISOPEN          %ROWCOUNT

Example:打印emp表的员工信息

DECLARE
  CURSOR emp_cursor IS SELECT empno,ename,job FROM emp;
  v_empno emp.empno%TYPE;
  v_name emp.ename%TYPE;
  v_job emp.job%TYPE;
BEGIN
  OPEN emp_cursor;
  LOOP
    FETCH emp_cursor INTO v_empno,v_name,v_job;
    DBMS_OUTPUT.PUT_LINE(‘员工号为:‘||v_empno||‘姓名是‘||v_name||‘职位:‘||v_job);
    EXIT WHEN emp_cursor%NOTFOUND;
  END LOOP;
  CLOSE emp_cursor;
END; 

这里严格按照显示游标的书写规则:DECLARE emp_cursor定义游标OPEN emp_cursor打开游标FETCH emp_cursor INTO...提取数据CLOSE emp_cursor关闭游标,因为提取出来的数据属于多行,所以通过loop循环打印即可。

Example2:检验游标是否打开,如果打开显示提取行数

DECLARE
  CURSOR emp_cursor IS SELECT empno,ename,job FROM emp;
  v_empno emp.empno%TYPE;
  v_name emp.ename%TYPE;
  v_job emp.job%TYPE;
BEGIN
  OPEN emp_cursor;
  LOOP
       FETCH emp_cursor INTO v_empno,v_name,v_job;
       EXIT WHEN emp_cursor%NOTFOUND;
  END LOOP;
  IF emp_cursor%ISOPEN THEN
    DBMS_OUTPUT.PUT_LINE(‘游标已打开‘);
    DBMS_OUTPUT.PUT_LINE(‘读取了‘||emp_cursor%ROWCOUNT||‘行‘);
  ELSE
    DBMS_OUTPUT.PUT_LINE(‘游标没有打开‘);
  END IF;
  CLOSE emp_cursor;
END;

通过%ISOPEN属性判断游标是否打开,%ROWCOUNT判断获取行数。

2、隐式游标:由系统定义并为它创建工作区域,并且隐式的定义打开提取关闭,隐式游标的游标名就是‘SQL‘,属性和显示游标相同,主要用于对单行select语句或dml操作进行处理。

Example:又用户输入员工号修改员工工资如成功则打印输出成功标志。

为了尽量不改变原表,创建新表emp_new和原表数据相同:

CREATE TABLE emp_new
AS
SELECT * FROM emp;
BEGIN
  UPDATE emp_new SET sal = sal+500 WHERE empno=&empno;
  IF SQL%FOUND THEN
    DBMS_OUTPUT.PUT_LINE(‘成功修改‘);
    COMMIT;
  ELSE
    DBMS_OUTPUT.PUT_LINE(‘修改失败‘);
    ROLLBACK;
  END IF;
END;

这里注意增删改以后要对做的操作进行commit提交,如果操作失败则rollback回滚刚才的操作。

3、参数游标:

在定义游标时加入参数的游标,可以配合游标for循环快速找到需要的数据。这里先讲一下游标for循环

A、游标FOR循环:

隐含的执行了打开提取关闭数据,代码精简很多。Expression:

FOR table_record IN table_cursor LOOP

  STATEMENT;

END LOOP;

Example:使用游标For循环打印输出员工信息:

DECLARE
CURSOR emp_cursor IS SELECT empno,ename,job FROM emp;
BEGIN
  FOR emp_record IN emp_cursor LOOP
    DBMS_OUTPUT.PUT_LINE(‘员工号:‘||emp_record.empno||‘员工姓名‘||emp_record.ename||‘员工职位‘||emp_record.job);
  END LOOP;
END;

这里游标FOR循环省去了对于取到的数据的变量的命名和赋值,同时如果全部打印则不用写循环条件,代码精简了很多。

如果想让代码更加精简,则可以去掉对游标的声明引入子查询即可,操作如下。

BEGIN
  FOR emp_record IN (SELECT empno,ename,job FROM emp) LOOP
    DBMS_OUTPUT.PUT_LINE(‘员工号:‘||emp_record.empno||‘员工姓名‘||emp_record.ename||‘员工职位‘||emp_record.job);
  END LOOP;
END;

代码更加精简,得到的结果相同。和隐式游标是不是有点像,但隐式游标主要用于的是单行select和dml语句的操作,注意2者用法的区别。

下面继续参数游标的实例:

Example:输入部门号打印员工信息:

DECLARE
CURSOR emp_cursor(dno NUMBER)IS SELECT empno,ename,job FROM emp WHERE deptno=dno;
BEGIN
  FOR emp_record IN emp_cursor(&dno) LOOP
    DBMS_OUTPUT.PUT_LINE(‘员工号‘||emp_record.empno||‘姓名‘||emp_record.ename||‘职位‘||emp_record.job);
  END LOOP;
END;

这里既然有参数,那么必然会有对游标的声明,在结合游标FOR循环快速超找所需要的数据。

三、使用游标修改数据的注意事项

1、使用游标修改数据时,为防止他人在自己操作数据时对数据进行修改,oracle提供for update子句进行加锁。

同时在你使用update或delete时,必须使用where current of+name_cursor语句,以及在最后记得提交。如果

是级联操作则可以使用for update of 来进行相关表的加锁。

Example1:对职位是PRESIDENT的员工加1000工资,MANAGER的人加500工资

CREATE TABLE emp_new
AS
SELECT * FROM emp;
DECLARE
CURSOR empnew_cursor IS SELECT ename,job FROM emp_new FOR UPDATE;
BEGIN
  FOR empnew_record IN empnew_cursor LOOP
    DBMS_OUTPUT.PUT_LINE(‘姓名‘||empnew_record.ename||‘职位‘||empnew_record.job);
    IF empnew_record.job=‘PRESIDENT‘ THEN
      UPDATE emp_new SET sal=sal+1000 WHERE CURRENT OF empnew_cursor;
    ELSIF empnew_record.job=‘MANAGER‘ THEN
      UPDATE emp_new SET sal=sal+500 WHERE CURRENT OF empnew_cursor;
    END IF;
  END LOOP;
  COMMIT;
END;
SELECT * FROM EMP WHERE job in(‘PRESIDENT‘,‘MANAGER‘);
SELECT * FROM EMP_NEW WHERE job in(‘PRESIDENT‘,‘MANAGER‘);

可以看到这里工资有了相应的变化。

至此,Oracle游标解析完毕,总而言之,游标只是作为我们从数据库中提取出来的一部分数据,我们针对这个结果集做一系列的操作。

                                            2018-09-07    16:15:34

原文地址:https://www.cnblogs.com/loveleaf/p/9603785.html

时间: 2024-10-10 18:55:03

Oracle游标解析的相关文章

【翻译】Oracle游标详细说明

这篇文章是选取官方文档的部分章节翻译过来的,去除了原文中的例子,并在结尾补充了几个例子.有兴趣的朋友可以点击文章末尾的连接去阅读官方文档. 一.游标的定义 游标是指向专用SQL区域的指针,该区域存储有关处理特定SELECT或DML语句的信息.本章解释的游标是会话游标.会话游标存在于会话中直到会话结束.由PL/SQL创建和管理的游标称为隐式游标,由用户创建和管理的游标称为显式游标.你可以通过游标的属性获取任意会话游标的相关信息.通过查询动态性能视图V$OPEN_CURSOR,可以列出当前已经打开和

[转载]oracle游标概念讲解

原文URL:http://www.2cto.com/database/201203/122387.html ORACLE游标概念讲解 什么是游标?  ①从表中检索出结果集,从中每次指向一条记录进行交互的机制.      ②关系数据库中的操作是在完整的行集合上执行的.   由SELECT 语句返回的行集合包括满足该语句的WHERE 子句所列条件的所有行.由该语句返回完整的行集合叫做结果集.      应用程序,尤其是互动和在线应用程序,把完整的结果集作为一个单元处理并不总是有效的.      这些

Duang!危险的oracle游标

1.引言 SQL是面向集合的语言,其结果一般是集合量(含多条记录),而pl/sql的变量是标量,一组变量一次只能存放一条记录.很多时候查询结果的记录数是不确定的,无法提前声明足够的变量.于是引入了游标的概念,游标使得数据库操作更灵活,但同时也给黑客入侵数据库带来了机会.安华金和数据库安全实验室(DBSec Labs)基于游标的应用原理,本文讨论游标可能带来什么安全隐患以及如何应对这些安全隐患. 2.游标的分类 oracle数据库游标是Pl/sql执行DQL.DML等语句的时候,oracle在内存

oracle 游标例子

CREATE OR REPLACE PROCEDURE PRC_WAP_ACTIVEUSERS(RETCODE OUT VARCHAR2) /*********************************************************** * 功能:WAP指标--活跃用户统计(分批提交) * 参数:RETCODE(返回编码:0000成功) * 作者: * 创建时间:2013-01-16 * 版本:1.0 * 修改人: * 修改时间: ********************

Oracle游标—for、loop、if结合应用

一.需求 什么时候会用到Oracle游标,以及其中的for.loop.if呢? 先看这样一个需求: 有一张学生授课表T_TEACHING,每个学生都有数门课程: 主键ID(自增) 课程号COURSE_ID 学号USER_ID 1 01 201501 2 02 201501 3 03 201501 4 01 201502 5 01 201503 6 01 201504 7 02 201504 ... ... ... 但是因为某些原因,导致有的学生课程不全(本应该每个学生都有3门课),应该如何把不全

Oracle游标循环更新数据案例

declare v_XTXMBH number; v_ZJZJZJRQ varchar2(40); cursor c_job is SELECT XT.XTXMBH AS XTXMBH, QJ.ZJZJZJRQ AS ZJZJZJRQ FROM XTXMXX XT, QJGLXX_ZQL_MID QJ WHERE XT.XTXMBH = QJ.XTXMBH AND XT.XTXMCLRQ >= '20120630' AND (QJ.ZJQHZJRQ IS NULL OR QJ.ZJZJZJRQ

oracle游标小试

有时候需要大面积的修改数据,这个时候用循环语句效率不高.而临时表又不能满足点对点修改的时候,游标似一种不错的选择(PS:好像游标也是为循环而生的吧) 现在有两张表 t1(ryid number,name nvarchar2(50),salary number,paydate date……)用来存员工每月的工资 t2(ryid number,paySalary number)每个月发的工资数目 现将t2中的paySalary添加到t1中 可以直接用update来实现: 现用oracle的for游标

Oracle 游标示例,带异常处理

Oracle游标示例一则,带异常处理. DECLARE CURSOR c_dl IS SELECT ID, NSRSBH, WSPZXH, ZXYY_DM, HZRQ, SWJG_DM, GXSJ FROM T_GUOS_ZXXX WHERE gxsj > begin_gxsj; c_row c_dl%ROWTYPE; BEGIN FOR c_row IN c_dl LOOP BEGIN IF (c_row.GXSJ > max_gxsj) THEN BEGIN max_gxsj := c_r

Oracle游标-循环查询表中数据(表名),并执行

Oralce 表中存有一个字段,该字段存储表名,要把该表中的所有表名查询出来(即表名结果集),且执行结果集from 表名结果集: declare v_ccount varchar2(100); --定义一个游标变量 cursor c_job is --查询该表中的所有表名 select tablename from tbname; c_row c_job%rowtype; begin --循环待处理数据,即以上查出的结果集 for c_row in c_job loop ---执行语句 from